В крупных торговых и производственных компаниях часто встречается практика работы по "рамочным договорам". Суть её заключается в том, что основной текст договора содержит общие юридические условия, а конкретные суммы, спецификации номенклатуры и графики платежей выносятся в отдельные приложения или дополнительные соглашения. В системе 1С:ERP Управление предприятием справочник ДоговорыКонтрагентов по умолчанию имеет плоскую структуру, что затрудняет навигацию и группировку сотен подчиненных документов.
В рамках данной статьи мы проанализируем, как реализовать связь "основной договор — приложение" с минимальными рисками для системы, разберем технические ограничения расширений и рассмотрим альтернативные штатные механизмы.
Прежде чем приступать к доработке кода, давайте проанализируем типовую логику, заложенную разработчиками 1С. В системе ERP разделены понятия правил продаж и финансовых условий:
Если ваша бизнес-задача заключается в группировке условий, попробуйте схему: одно ИндивидуальноеСоглашение (как основной контракт) и множество привязанных к нему Договоров (как спецификаций/приложений). Это позволит видеть все договоры в контексте одного соглашения без написания кода.
Если штатный механизм соглашений не подходит и требуется именно визуальная иерархия внутри справочника ДоговорыКонтрагентов, рассмотрим техническую сторону реализации. Основная сложность заключается в том, что для этого справочника в типовой конфигурации отключено использование иерархии.
Важное ограничение: Вы не сможете включить стандартную иерархию (свойство метаданных ИерархическийСправочник) через расширение, если она выключена в основной конфигурации. Попытка изменить это свойство в основной конфигурации приведет к снятию объекта с поддержки и возможным критическим ошибкам при реструктуризации базы данных в процессе обновления.
Для решения задачи мы пойдем путем добавления реквизита связи. Разберем этот процесс по шагам:
ДоговорыКонтрагентов.РодительскийДоговор с типом СправочникСсылка.ДоговорыКонтрагентов.Теперь мы можем определить логику: если поле РодительскийДоговор пустое, договор считается "корневым". Если заполнено — это приложение (дочерний элемент). При этом все взаиморасчеты в документах РеализацияТоваровУслуг или ПриобретениеТоваровУслуг будут вестись именно по дочерним договорам штатными средствами.
Просто добавить реквизит недостаточно — пользователям нужно удобно работать со списком. Рассмотрим, как реализовать дерево договоров. Мы не можем использовать стандартный режим отображения "Дерево" для неиерархического справочника, поэтому нам придется модифицировать динамический список формы списка.
Проанализируем шаги по настройке формы:
РодительскийДоговор.РодительскийДоговор.Таким образом, в интерфейсе пользователи увидят сгруппированные списки, где заголовком группы будет выступать основной договор, а внутри — все относящиеся к нему приложения. Это решает задачу навигации без изменения структуры метаданных.
Необходимо понимать, как данная доработка отразится на учете. Рассмотрим ситуацию: оплата и отгрузка происходят по "Дочернему договору 1". Типовые отчеты, такие как ВедомостьРасчетовСКлиентами, будут выводить аналитику именно по этому дочернему договору.
Если руководство захочет увидеть общую картину дебиторской задолженности по всему "холдингу" договоров (суммарно по основному и всем приложениям), типовой отчет этого не покажет. Нам потребуется:
Договор.РодительскийДоговор.ЕСТЬNULL(Договор.РодительскийДоговор, Договор), чтобы в одну группу попадали и сам родитель, и его потомки.Выясним, какие опасности таит в себе этот подход. 1С:ERP часто обменивается данными с 1С:Бухгалтерией (БП). В БП справочник договоров также плоский. При синхронизации дочерний договор из ERP попадет в БП как обычный договор. Если в ERP вы логически связываете их, то в БП эта связь пропадет, если не доработать правила обмена в Comodity или через Enterprise Data.
Рекомендации по реализации кода:
Для фильтрации выбора родительского договора, чтобы договор не мог стать родителем сам себе, используйте обработчик события НачалоВыбора в модуле формы:
&НаКлиенте
Процедура РодительскийДоговорНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Новый Структура("Партнер, Владелец, ПометкаУдаления", Объект.Партнер, Объект.Владелец, Ложь));
// Исключаем текущий договор из выбора
ПараметрыФормы.Вставить("ТекущаяСтрока", Объект.Ссылка);
ОткрытьФорму("Справочник.ДоговорыКонтрагентов.ФормаВыбора", ПараметрыФормы, Элемент);
КонецПроцедуры
Подводя итог, можно сказать, что реализация подчиненных договоров через дополнительный реквизит в расширении — это наиболее сбалансированный путь. Он сохраняет типовую логику взаиморасчетов "объект в объект", обеспечивает необходимую группировку и не создает проблем при обновлении конфигурации, в отличие от попыток включения системной иерархии.