При разработке конфигураций, предназначенных для кадрового учета или автоматизации детских учреждений (например, детских садов), часто возникает задача связать сотрудников с их детьми. На первый взгляд, создание табличных частей (ТЧ) в обоих справочниках кажется логичным решением: в справочнике Сотрудники храним список детей, а в справочнике Дети — список родителей-сотрудников. Однако такой подход ведет к дублированию информации и программным сложностям при синхронизации данных. В этой статье мы подробно разберем, почему архитектура на основе табличных частей является «антипаттерном», и как реализовать эту задачу правильно, используя механизмы платформы 1С.
Рассмотрим ситуацию, когда мы пытаемся синхронизировать две табличные части: ТЧДети у сотрудника и ТЧРодители у ребенка. При записи одного объекта нам придется программно открывать и перезаписывать другой. Это порождает несколько критических проблем:
Для решения этой задачи мы проанализируем лучший подход, который применяется в типовых решениях «1С:Предприятие».
Самый надежный и архитектурно верный способ — вынести связь в отдельный Регистр сведений (РС). Это позволит нам хранить информацию о родстве в одном месте, не перегружая справочники лишними данными.
Выясним, какую структуру должен иметь такой регистр. Оптимально создать непериодический независимый регистр сведений, назовем его РодственныеСвязи. Проанализируем его измерения и ресурсы:
ФизЛицо (тип СправочникСсылка.ФизическиеЛица). Это основной субъект, для которого мы указываем родственника.Родственник (тип СправочникСсылка.ФизическиеЛица). Это член семьи.СтепеньРодства (тип ПеречислениеСсылка.СтепениРодства). Здесь мы укажем значения: Мать, Отец, Сын, Дочь, Опекун и так далее.Важно отметить: в профессиональной разработке связи настраиваются не между «Сотрудниками», а между «Физическими лицами». Один и тот же человек может быть сотрудником сегодня, уволиться завтра, но остаться в базе как родитель. Использование справочника ФизическиеЛица как основы — залог стабильности системы.
Когда данные хранятся в регистре сведений, возникает вопрос: как пользователю увидеть их в карточке сотрудника или ребенка? Вместо того чтобы реально заполнять табличную часть, мы будем использовать Динамический список на форме.
Разберем по шагам процесс настройки такой формы:
Сотрудники).ДинамическийСписок.РодственныеСвязи.ГДЕ ФизЛицо = &ТекущееФизЛицо.Теперь, когда пользователь открывает карточку сотрудника, система «на лету» подтягивает данные из регистра. Это исключает дублирование и гарантирует актуальность информации.
Посмотрим на пример кода, который позволит нам добавить связь между родителем и ребенком непосредственно из формы. Предположим, мы нажимаем кнопку «Добавить родственника»:
Процедура ДобавитьРодственнуюСвязь(ФизЛицоСсылка, РодственникСсылка, СтепеньРодства)
МенеджерЗаписи = РегистрыСведений.РодственныеСвязи.СоздатьМенеджерЗаписи();
// Устанавливаем ключевые значения (измерения)
МенеджерЗаписи.ФизЛицо = ФизЛицоСсылка;
МенеджерЗаписи.Родственник = РодственникСсылка;
// Заполняем ресурс
МенеджерЗаписи.СтепеньРодства = СтепеньРодства;
// Записываем данные в базу
Попытка
МенеджерЗаписи.Записать(Истина); // Истина означает замещение существующей записи
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Ошибка при записи связи: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Обратите внимание, что для реализации двусторонней связи (чтобы и у ребенка был виден родитель, и у родителя ребенок) в регистр можно записывать две строки: одну для родителя, другую для ребенка с обратной степенью родства. Либо настроить запрос динамического списка так, чтобы он искал записи, где текущее лицо встречается либо в колонке ФизЛицо, либо в колонке Родственник.
Проанализируем ситуацию с точки зрения производительности и удобства отчетов:
Таким образом, мы выяснили, что связывание справочников через взаимные табличные части — это тупиковый путь, создающий проблемы при записи. Рассмотренный нами метод использования Регистра сведений в сочетании с Динамическими списками является стандартом «чистой» разработки на платформе 1С 8.3. Это обеспечивает высокую скорость работы интерфейса и целостность базы данных.