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