Как правильно реализовать перезаполнение документов, созданных на основании, при изменении документа-основания в 1С?

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

При разработке учетных систем на платформе 1С:Предприятие часто возникает задача синхронизации данных между родительским документом (основанием) и ранее созданными на его основе подчиненными документами. На первый взгляд самым простым решением кажется вызов процедуры перезаполнения подчиненных объектов непосредственно в обработчиках событий ПриЗаписи или ОбработкаПроведения документа-основания. Однако такой подход влечет за собой серьезные технические и архитектурные проблемы.

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

Технические риски синхронного перезаполнения в событиях записи

Разберем основные проблемы, возникающие при попытке перезаписывать или перепроводить подчиненные документы прямо во время записи родительского документа:

  1. Длительные транзакции и блокировки данных. При проведении документа-основания платформа открывает явную транзакцию. Если у документа существует множество подчиненных объектов, синхронное проведение каждого из них существенно увеличивает время выполнения одной операции. В результате пользователи сталкиваются с длительными ожиданиями и тайм-аутами блокировок системных таблиц.
  2. Конфликты с датой запрета изменения. Документ-основание может редактироваться в открытом периоде, тогда как один из подчиненных документов уже попал в закрытый период. Попытка программного изменения или перепроведения закрытого документа вызовет ошибку проверки даты запрета, из-за чего отменится проведение и самого родительского документа.
  3. Ограничения прав доступа (RLS). У пользователя, изменяющего документ-основание, может не быть прав на редактирование или проведение конкретных видов подчиненных документов. Это приведет к исключению по причине недостатка прав.
  4. Циклическая рекурсия. Если логика подчиненного документа при его записи содержит обратное обращение или обновление данных документа-основания, возникает зацикливание вызовов Записать(), что приводит к переполнению стека или ошибкам транзакции.
  5. Ошибки оперативного и партионного учета. При автоматическом изменении количества или номенклатуры в подчиненных документах списывания/оприходования проведение может завершиться ошибкой из-за нехватки остатков на дату подчиненного документа.

Рекомендуемые архитектурные решения

Вместо прямой записи подчиненных документов из модуля объекта основания разберем проверенные и безопасные подходы к решению задачи.

Вариант 1. Использование АРМ (Автоматизированного рабочего места)

Наиболее надежным решением является отказ от автоматического фонового перепроведения в пользу специальной интерактивной обработки. Проанализируем схему работы такого инструмента:

Вариант 2. Асинхронная очередь изменений через регистр сведений

Если требуется автоматическое обновление без участия пользователя, применяют отложенную (асинхронную) обработку. Рассмотрим алгоритм реализации:

  1. В момент изменения ключевых реквизитов документа-основания (в событии ПриЗаписи или подписке на событие) в специальный регистр сведений ОчередьПерезаполненияДокументов записывается ссылка на измененный документ.
  2. Отдельное регламентное (фоновое) задание, выполняемое по расписанию под привилегированным сеансом, считывает записи из регистра.
  3. Фоновое задание поочередно открывает подчиненные документы, выполняет перезаполнение, проверку остатков и перепроведение в отдельных независимых транзакциях.

Для предотвращения лишних срабатываний перед добавлением записи в очередь проверяют, действительно ли изменились ключевые реквизиты. Посмотрим на пример кода считывания старых значений из базы данных:


// Сравнение текущих реквизитов объекта со значениями в базе данных
ЗначенияБД = Ссылка.ПолучитьОбъект();
Если ЗначенияБД <> Неопределено Тогда
    Если ЗначенияБД.СуммаДокумента <> ЭтотОбъект.СуммаДокумента 
        Или ЗначенияБД.Контрагент <> ЭтотОбъект.Контрагент Тогда
        
        // Фиксируем необходимость обновления подчиненных документов
        ЗафиксироватьНеобходимостьОбновления(Ссылка);
    КонецЕсли;
КонецЕсли;

Вариант 3. Интерактивные статусы рассогласования

При данном подходе платформенные данные подчиненных документов не меняются автоматически. При открытии формы подчиненного документа выполняются следующие действия:

  1. Система динамически сравнивает ключевые параметры (цены, количества, номенклатуру) с данными документа-основания.
  2. При обнаружении расхождений на форме отображается предупреждающий баннер или статус "Требуется актуализация".
  3. Пользователю предоставляется кнопка "Обновить по основанию", при нажатии на которую происходит перезаполнение табличных частей с контролем всех прав и дат запрета.

Для исключения повторной рекурсивной обработки при программной записи объектов рекомендуется передавать признак-флаг через свойство ДополнительныеСвойства:


// Установка флага для предотвращения повторной обработки в подписках
ДокументОбъект.ДополнительныеСвойства.Вставить("ОтключитьКонтрольЗаполнения", Истина);
ДокументОбъект.Записать(РежимЗаписиДокумента.Запись);

Подводя итог, при проектировании системы следует избегать жесткой связки каскадного перепроведения в синхронном режиме. Использование АРМ, регламентных заданий или статусных баннеров обеспечит стабильную работу базы данных и избавит пользователей от неожиданных ошибок блокировок.

← На главную