При работе с современными конфигурациями на платформе 1С:Предприятие 8.3, такими как 1С:ERP Управление предприятием, 1С:Комплексная автоматизация 2 или 1С:Управление торговлей 11, многие разработчики сталкиваются с «магическим» исчезновением явного формирования движений. В классических конфигурациях (например, УПП 1.3) мы привыкли видеть прямой перебор строк табличной части и заполнение коллекции Движения. В новых же системах при открытии модуля документа в процедуре ОбработкаПроведения мы видим, что коллекция движений пуста, а затем, после выполнения нескольких серверных процедур, она внезапно оказывается заполненной.
В этой статье мы подробно разберем, куда исчезли привычные строки кода, как работает современный механизм проведения и в какой именно момент данные попадают в регистры. Проанализируем ситуацию по шагам, чтобы понять внутреннюю архитектуру этих систем.
Начиная с версии УТ 11.1, компания «1С» внедрила архитектурный подход, разделяющий подготовку данных и их запись в регистры. Рассмотрим основные цели этого разделения:
Разберем, где именно зарождаются будущие движения. Если мы зайдем в процедуру ОбработкаПроведения любого документа в КА 2.4 или ERP, мы увидим вызов серверного метода, который обычно ведет к процедуре ИнициализироватьДанныеДокумента.
Проанализируем ситуацию: в этот момент Движения еще пусты. Магия начинается в модуле менеджера документа. Рассмотрим примерный алгоритм, который там выполняется:
МенеджерВременныхТаблиц.ДополнительныеСвойства объекта документа.В коде это выглядит примерно так:
// В модуле менеджера документа
Процедура ИнициализироватьДанныеДокумента(Ссылка, ДополнительныеСвойства) Экспорт
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
// Формирование текстов запросов для всех необходимых регистров
ТекстыЗапроса = "ВЫБРАТЬ ... ПОМЕСТИТЬ ТаблицаТовары ИЗ ... ;"
+ "ВЫБРАТЬ * ИЗ ТаблицаТовары;";
Запрос.Текст = ТекстыЗапроса;
РезультатыЗапроса = Запрос.ВыполнитьПакет();
// Результаты сохраняются в структуру ДополнительныеСвойства.ТаблицыДляДвижений
ДополнительныеСвойства.Вставить("ТаблицыДляДвижений", Новый Структура);
ДополнительныеСвойства.ТаблицыДляДвижений.Вставить("ТаблицаСвободныеОстатки", РезультатыЗапроса[1].Выгрузить());
КонецПроцедуры
После того как данные подготовлены и «упакованы» в ДополнительныеСвойства, управление возвращается в модуль объекта. Теперь наступает момент, когда таблицы значений должны превратиться в наборы записей регистров. Это происходит при вызове процедур из общих модулей, например ЗапасыСервер.ОтразитьСвободныеОстатки или ПроведениеСерверУТ.ОтразитьДвижения.
Выясним причину, почему разработчик часто не видит этого момента при отладке. Внутри этих процедур используется метод Загрузить() для наборов записей. Проанализируем упрощенный пример того, что происходит внутри универсальных механизмов отражения:
// В общем модуле (например, ЗапасыСервер)
Процедура ОтразитьСвободныеОстатки(ДополнительныеСвойства, Движения, Отказ) Экспорт
// Получаем ранее подготовленную таблицу из свойств
ТаблицаДвижений = ДополнительныеСвойства.ТаблицыДляДвижений.ТаблицаСвободныеОстатки;
// Обращаемся к набору записей в коллекции Движения
НаборЗаписей = Движения.СвободныеОстатки;
// Загружаем данные из таблицы значений в набор записей
НаборЗаписей.Загрузить(ТаблицаДвижений);
// Устанавливаем флаг, что этот регистр нужно записать при завершении транзакции
НаборЗаписей.Записывать = Истина;
КонецПроцедуры
Важный нюанс, который часто сбивает с толку: в коде ОбработкаПроведения вы практически никогда не встретите явного вызова метода Движения.Записать(). Рассмотрим, почему это работает.
Платформа 1С устроена так, что если в процедуре проведения у регистра в коллекции Движения установлено свойство Записывать = Истина, то по завершении кода этой процедуры (перед окончательным Commit транзакции) платформа самостоятельно и неявно выполняет запись этих наборов в базу данных.
Именно поэтому, когда вы проходите отладчиком по строкам процедуры ОбработкаПроведения, в какой-то момент (после вызова «Отразить...») вы видите, что коллекция Движения заполнилась строками, но физически в базе данных их еще нет — они запишутся автоматически в самом конце.
В конфигурациях КА 2.4 и ERP существует еще один уровень сложности, упомянутый в обсуждении — расчет себестоимости. Проанализируем ситуацию с регистрами накопления СебестоимостьТоваров и ВыручкаИПродажи.
В этих регистрах движения могут формироваться в два этапа:
Интересный факт: для ускорения этих расчетов современные версии 1С используют внешние библиотеки на C++, которые эффективно справляются с миллионами узлов графа затрат. Это объясняет, почему иногда движения по себестоимости в регистрах выглядят неполными или меняются после закрытия месяца.
Если вам необходимо изменить логику или понять, откуда в регистре берется конкретная цифра, рекомендуем следующий алгоритм работы:
...ПроведениеСервер....ОбработкаПроведения и изучите содержимое ЭтотОбъект.ДополнительныеСвойства.ТаблицыДляДвижений. Там вы увидите все таблицы значений, которые будут «залиты» в регистры.Переопределяемый, где разработчики внедряют специфические отраслевые изменения.Таким образом, «магия» проведения в КА 2.4 и ERP — это строго выверенная архитектурная схема. Понимание цепочки «Запрос в менеджере -> Таблица в ДополнительныхСвойствах -> Метод Загрузить() в наборе записей -> Автоматическая запись платформой» позволяет быстро и эффективно диагностировать любые проблемы с проведением документов в современных системах 1С. Для наглядного изучения взаимосвязи процедур и функций типового алгоритма подойдёт схема типового механизма проведения документов в ERP 2.5.