Как спроектировать регистр сведений для хранения телефонов сотрудника с контролем уникальности личного номера

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие часто возникают задачи, где необходимо совместить хранение одиночных (уникальных) данных и списочных (множественных) данных в рамках одного объекта. Типичный пример — задача с собеседования: создать регистр для телефонов сотрудников, где личный номер может быть только один, а номеров родственников — неограниченное количество. При этом проверку должна выполнять сама платформа за счет своей архитектуры, а не только программный код.

В этой статье мы подробно разберем несколько подходов к проектированию такой системы, проанализируем механику работы индексов регистра сведений и выясним, какое решение является наиболее элегантным с точки зрения архитектора 1С.

Понимание механики уникальности регистра сведений

Прежде чем переходить к решениям, проанализируем, как 1С обеспечивает уникальность записей. Уникальность записи в регистре сведений определяется набором его измерений. Платформа создает в СУБД первичный ключ (Primary Key), состоящий из всех измерений регистра. Если мы пытаемся записать строку с комбинацией измерений, которая уже существует, система выдаст ошибку «Запись с такими ключевыми полями существует».

Основная сложность задачи заключается в том, что для «личного телефона» нам нужна уникальность по полю Сотрудник, а для «телефонов родственников» — уникальность по комбинации Сотрудник + Кто-тоЕще. Рассмотрим, как этого добиться.

Решение 1: Использование необязательного измерения (классический ответ)

Это решение считается наиболее правильным в контексте «задач на сообразительность». Мы используем тот факт, что измерение может быть пустым.

Спроектируем структуру следующим образом:

  1. Измерение: Сотрудник (Тип: СправочникСсылка.Сотрудники).
  2. Измерение: Родственник (Тип: СправочникСсылка.ФизическиеЛица или Строка). Данное поле оставляем незаполненным для личного номера.
  3. Ресурс: НомерТелефона (Тип: Строка).

Разберем, как это работает на практике:

Важный нюанс: Чтобы различать типы записей в интерфейсе, можно использовать условное оформление: если поле Родственник не заполнено, выводить в колонке текст «Личный».

Решение 2: Использование технического индекса (Номер по порядку)

Рассмотрим ситуацию, когда нам нужно хранить просто «дополнительные телефоны» без привязки к конкретным личностям родственников. В этом случае можно использовать числовое измерение.

Структура регистра:

  1. Измерение: Сотрудник.
  2. Измерение: НомерПП (Тип: Число).
  3. Ресурс: НомерТелефона.

Логика работы:

Условимся, что НомерПП = 0 всегда зарезервирован за личным телефоном. Все остальные номера (родственников или дополнительные) записываются с инкрементом: 1, 2, 3 и так далее. Платформа автоматически ограничит количество записей с индексом 0 одной строкой на сотрудника, выполняя требование задачи.

Решение 3: Программный контроль в модуле набора записей

Хотя задача часто подразумевает «архитектурное» решение, в реальных проектах чаще используется программная проверка. Это позволяет сделать систему более гибкой и выводить пользователю понятные сообщения об ошибках.

Проанализируем пример кода, который необходимо разместить в модуле регистра сведений в обработчике ПередЗаписью:


Процедура ПередЗаписью(Отказ, Замещение)
    
    // Если запись идет через ОбменДанными.Загрузка, обычно проверки отключают
    Если ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

    // Допустим, у нас есть ресурс ВидТелефона (Перечисление: Личный, Родственника)
    // Проверяем только если в текущем наборе есть "Личный"
    КоличествоЛичных = 0;
    Для Каждого Запись Из ЭтотОбъект Цикл
        Если Запись.ВидТелефона = Перечисления.ВидыТелефонов.Личный Тогда
            КоличествоЛичных = КоличествоЛичных + 1;
        КонецЕсли;
    КонецЦикла;
    
    Если КоличествоЛичных > 1 Тогда
        Сообщить("У сотрудника не может быть более одного личного телефона!");
        Отказ = Истина;
        Возврат;
    КонецЕсли;

    // Также нужно проверить базу данных, если мы записываем не весь набор сразу, 
    // а по одной записи (хотя для РС это редкость при стандартных формах)
    // ... здесь должен быть запрос к таблице регистра ...
    
КонецПроцедуры

Преимущество этого метода в том, что мы не перегружаем структуру регистра лишними измерениями ради логики контроля. Помните: каждое новое измерение увеличивает размер индексов и может замедлять запись в высоконагруженных системах.

Решение 4: Разделение сущностей (Архитектурный подход)

Если мы проектируем крупную систему, стоит задаться вопросом: являются ли личный телефон и телефон родственника одной и той же сущностью? Личный телефон — это зачастую обязательный атрибут самого сотрудника.

Рассмотрим альтернативный вариант:

  1. Личный номер телефона добавить как Реквизит в справочник Сотрудники. Это на 100% гарантирует уникальность «один сотрудник — один телефон» на уровне структуры справочника.
  2. Для телефонов родственников создать подчиненный Регистр сведений, где измерением будет Сотрудник, а вторым измерением — Родственник или НомерТелефона.

Такой подход делает структуру данных прозрачной: нам не нужно гадать, какая запись в регистре является главной, так как основной контакт всегда находится «под рукой» в карточке сотрудника.

Сравнение методов

Выясним, какой метод выбрать в зависимости от ситуации:

Подводя итог, можно сказать, что гибкость платформы 1С позволяет решить задачу уникальности множеством способов. Выбор конкретного метода зависит от того, насколько критична производительность и насколько «чистой» должна быть архитектура вашего решения.

← На главную