При разработке, доработке или отладке механизмов проведения документов в платформе 1С:Предприятие 8 разработчики часто сталкиваются с неочевидным поведением отладчика. Типичный сценарий: в процедуре ОбработкаПроведения формируются таблицы движений, затем управление передается в различные подписки (например, проверку даты запрета редактирования), а после этого отладчик сразу «вываливается» в клиентское событие формы ПослеЗаписи. При этом физическая запись в регистре накопления уже существует, хотя явного вызова метода Записать() в коде проведения не было.
В этой статье мы подробно разберем внутренние механизмы платформы «1С:Предприятие 8», управляющие записью движений, выясним, почему так происходит, и научимся безошибочно находить точный момент физической записи в базу данных.
Основная особенность проведения документов в 1С заключается в том, что физическая запись движений в СУБД по умолчанию происходит неявно самой платформой после успешного завершения процедуры ОбработкаПроведения в модуле объекта документа.
Рассмотрим пошагово, как выглядит этот процесс «под капотом» системы:
ОбработкаПроведения (или во вспомогательных процедурах общих модулей, таких как УправлениеДенежнымиСредствами.ПровестиПоступлениеДенежныхСредствУпр) формирует таблицы движений и заполняет коллекцию Движения.
Движения.РасчетыСКонтрагентами.Записывать = Истина;
Обратите внимание, что сам метод Записать() для набора записей при этом не вызывается.ОбработкаПроведения успешно завершает свою работу.Движения и автоматически инициирует запись в базу данных тех наборов записей, у которых свойство Записывать установлено в значение Истина.ПередЗаписью и ПриЗаписи в модуле набора записей.ПередЗаписьюРегистраНакопленияДатаЗапретаРедактирования, которая перенаправляет вызов в общий модуль НастройкаПравДоступа.ПередЗаписьюРегистраНакопленийПроверкаДоступностиПериода). Сама подписка выполняет только валидацию данных и не производит запись физически. Запись производит платформа сразу после успешного завершения обработчиков подписок.ПослеЗаписи на клиенте.Из-за того, что запись выполняется платформой автоматически на шаге 4–6, разработчику кажется, что запись происходит «внезапно» между завершением подписок и открытием формы.
То, как именно платформа решает, какие регистры нужно записать в конце транзакции проведения, регулируется свойством метаданных документа «Запись движений при проведении». Проанализируем два основных режима работы этого свойства:
Движения.ИмяРегистра.Записывать = Истина;. Сам метод Записать() вызывать не нужно — платформа выполнит эту операцию автоматически в конце транзакции.Чтобы увидеть физический момент записи набора в СУБД и точно определить инициатора (платформа это делает автоматически или в коде все же есть принудительный вызов), выполним следующие действия:
Откроем конфигуратор, найдем регистр накопления РасчетыСКонтрагентами (или любой другой интересующий нас регистр). Щелкнем по нему правой кнопкой мыши, выберем пункт «Открыть модуль набора записей».
Если в модуле набора записей отсутствуют стандартные обработчики событий, нам необходимо их создать. Напишем следующий код:
Процедура ПередЗаписью(Отказ, Замещение)
// Сюда устанавливаем точку останова
ПредупреждениеОтладка = Истина;
КонецПроцедуры
Процедура ПриЗаписи(Отказ, Замещение)
// Сюда также можно установить точку останова
ПредупреждениеОтладка = Истина;
КонецПроцедуры
Поскольку проведение документов и запись движений в клиент-серверных базах всегда выполняются на стороне сервера, убедимся, что у нас включена серверная отладка:
-debug.Запустим сеанс «1С:Предприятие» в режиме отладки, откроем нужный документ Приходный кассовый ордер (ПКО) и выполним его проведение. Когда отладчик остановится на точке останова в процедуре ПередЗаписью модуля набора записей регистра:
Ctrl + Alt + C).ПередЗаписью нет строк кода конфигурации (сразу отображается системный вызов платформы), значит, запись выполняется неявно самой платформой после выхода из процедуры ОбработкаПроведения модуля документа.Движения.РасчетыСКонтрагентами.Записать(), значит, в конфигурации отрабатывает явная запись из кода.В зависимости от того, на какой архитектуре построена ваша конфигурация, логика формирования и записи движений может существенно отличаться:
Используется классическая схема проведения. При проведении ПКО управление передается в специализированный общий модуль, например, в функцию УправлениеДенежнымиСредствами.ПровестиПоступлениеДенежныхСредствУпр. Там происходит расчет остатков, заполняются таблицы движений, взводится флаг Записывать = Истина, но физическую запись система доверяет платформе, которая осуществляет ее в конце транзакции.
Применяется оптимизированный механизм проведения. Вместо записи «на лету» в модуле менеджера или объекта документа сначала подготавливаются временные таблицы с движениями. Затем централизованно вызывается метод долгого действия (например, процедура общего модуля ПроведениеСервер.ЗаписатьНаборыЗаписей()), который выполняет явный вызов метода Записать() для всех подготовленных регистров. Это сделано для минимизации времени блокировок таблиц СУБД и повышения параллельности работы пользователей.
Понимая эти тонкости работы платформы «1С:Предприятие 8» и умея пользоваться модулем набора записей совместно со стеком вызовов, вы всегда сможете быстро локализовать, в какой именно момент и под воздействием какого алгоритма данные попадают в регистры накопления.