В какой момент и как формируются движения при проведении документов в 1С:ERP, КА 2 и УТ 11?

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

При работе с современными конфигурациями на платформе 1С:Предприятие 8.3, такими как 1С:ERP Управление предприятием, 1С:Комплексная автоматизация 2 или 1С:Управление торговлей 11, многие разработчики сталкиваются с «магическим» исчезновением явного формирования движений. В классических конфигурациях (например, УПП 1.3) мы привыкли видеть прямой перебор строк табличной части и заполнение коллекции Движения. В новых же системах при открытии модуля документа в процедуре ОбработкаПроведения мы видим, что коллекция движений пуста, а затем, после выполнения нескольких серверных процедур, она внезапно оказывается заполненной.

В этой статье мы подробно разберем, куда исчезли привычные строки кода, как работает современный механизм проведения и в какой именно момент данные попадают в регистры. Проанализируем ситуацию по шагам, чтобы понять внутреннюю архитектуру этих систем.

1. Смена парадигмы: Новый механизм проведения

Начиная с версии УТ 11.1, компания «1С» внедрила архитектурный подход, разделяющий подготовку данных и их запись в регистры. Рассмотрим основные цели этого разделения:

  1. Оптимизация производительности: Вместо множества мелких запросов к базе данных в цикле, система выполняет один мощный пакетный запрос в модуле менеджера.
  2. Унификация кода: Логика формирования данных выносится в модуль менеджера, что позволяет использовать её повторно (например, при групповом перепроведении или вводе на основании).
  3. Минимизация блокировок: Подготовка данных происходит максимально быстро, а транзакция записи сокращается по времени.

2. Первый этап: Подготовка данных в модуле менеджера

Разберем, где именно зарождаются будущие движения. Если мы зайдем в процедуру ОбработкаПроведения любого документа в КА 2.4 или ERP, мы увидим вызов серверного метода, который обычно ведет к процедуре ИнициализироватьДанныеДокумента.

Проанализируем ситуацию: в этот момент Движения еще пусты. Магия начинается в модуле менеджера документа. Рассмотрим примерный алгоритм, который там выполняется:

  1. Система создает МенеджерВременныхТаблиц.
  2. Формируется текст масштабного запроса, который собирает данные из табличных частей документа, учитывает настройки учетной политики, текущие остатки и аналитики.
  3. Результаты выполнения запросов выгружаются не в регистры, а в таблицы значений, которые помещаются в специальную структуру — ДополнительныеСвойства объекта документа.

В коде это выглядит примерно так:


// В модуле менеджера документа
Процедура ИнициализироватьДанныеДокумента(Ссылка, ДополнительныеСвойства) Экспорт
    
    Запрос = Новый Запрос;
    Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
    
    // Формирование текстов запросов для всех необходимых регистров
    ТекстыЗапроса = "ВЫБРАТЬ ... ПОМЕСТИТЬ ТаблицаТовары ИЗ ... ;"
                  + "ВЫБРАТЬ * ИЗ ТаблицаТовары;";
    
    Запрос.Текст = ТекстыЗапроса;
    РезультатыЗапроса = Запрос.ВыполнитьПакет();
    
    // Результаты сохраняются в структуру ДополнительныеСвойства.ТаблицыДляДвижений
    ДополнительныеСвойства.Вставить("ТаблицыДляДвижений", Новый Структура);
    ДополнительныеСвойства.ТаблицыДляДвижений.Вставить("ТаблицаСвободныеОстатки", РезультатыЗапроса[1].Выгрузить());
    
КонецПроцедуры

3. Второй этап: Отражение данных в коллекцию «Движения»

После того как данные подготовлены и «упакованы» в ДополнительныеСвойства, управление возвращается в модуль объекта. Теперь наступает момент, когда таблицы значений должны превратиться в наборы записей регистров. Это происходит при вызове процедур из общих модулей, например ЗапасыСервер.ОтразитьСвободныеОстатки или ПроведениеСерверУТ.ОтразитьДвижения.

Выясним причину, почему разработчик часто не видит этого момента при отладке. Внутри этих процедур используется метод Загрузить() для наборов записей. Проанализируем упрощенный пример того, что происходит внутри универсальных механизмов отражения:


// В общем модуле (например, ЗапасыСервер)
Процедура ОтразитьСвободныеОстатки(ДополнительныеСвойства, Движения, Отказ) Экспорт
    
    // Получаем ранее подготовленную таблицу из свойств
    ТаблицаДвижений = ДополнительныеСвойства.ТаблицыДляДвижений.ТаблицаСвободныеОстатки;
    
    // Обращаемся к набору записей в коллекции Движения
    НаборЗаписей = Движения.СвободныеОстатки;
    
    // Загружаем данные из таблицы значений в набор записей
    НаборЗаписей.Загрузить(ТаблицаДвижений);
    
    // Устанавливаем флаг, что этот регистр нужно записать при завершении транзакции
    НаборЗаписей.Записывать = Истина;
    
КонецПроцедуры

4. Третий этап: Автоматическая запись платформой

Важный нюанс, который часто сбивает с толку: в коде ОбработкаПроведения вы практически никогда не встретите явного вызова метода Движения.Записать(). Рассмотрим, почему это работает.

Платформа 1С устроена так, что если в процедуре проведения у регистра в коллекции Движения установлено свойство Записывать = Истина, то по завершении кода этой процедуры (перед окончательным Commit транзакции) платформа самостоятельно и неявно выполняет запись этих наборов в базу данных.

Именно поэтому, когда вы проходите отладчиком по строкам процедуры ОбработкаПроведения, в какой-то момент (после вызова «Отразить...») вы видите, что коллекция Движения заполнилась строками, но физически в базе данных их еще нет — они запишутся автоматически в самом конце.

5. Особенности для Себестоимости и Партионного учета

В конфигурациях КА 2.4 и ERP существует еще один уровень сложности, упомянутый в обсуждении — расчет себестоимости. Проанализируем ситуацию с регистрами накопления СебестоимостьТоваров и ВыручкаИПродажи.

В этих регистрах движения могут формироваться в два этапа:

  1. Оперативный этап: В момент проведения документа фиксируются только количественные изменения и предварительная стоимость (если включены соответствующие настройки).
  2. Регламентный этап: При выполнении обработки «Закрытие месяца» происходит окончательный расчет себестоимости. Для этого используется сложный математический аппарат — решение систем линейных алгебраических уравнений (СЛАУ).

Интересный факт: для ускорения этих расчетов современные версии 1С используют внешние библиотеки на C++, которые эффективно справляются с миллионами узлов графа затрат. Это объясняет, почему иногда движения по себестоимости в регистрах выглядят неполными или меняются после закрытия месяца.

6. Как эффективно искать логику формирования движений?

Если вам необходимо изменить логику или понять, откуда в регистре берется конкретная цифра, рекомендуем следующий алгоритм работы:

  1. Используйте замер производительности: Запустите замер, проведите документ и посмотрите, в каких процедурах тратится больше всего времени. Обычно это будут методы в модуле менеджера или общие модули с названиями ...ПроведениеСервер....
  2. Ищите процедуру «ИнициализироватьДанныеДокумента»: В 90% случаев в ERP-системах именно там находится текст запроса, формирующий данные.
  3. Проверяйте ДополнительныеСвойства: Поставьте точку останова в конце ОбработкаПроведения и изучите содержимое ЭтотОбъект.ДополнительныеСвойства.ТаблицыДляДвижений. Там вы увидите все таблицы значений, которые будут «залиты» в регистры.
  4. Обратите внимание на «Переопределяемые» модули: Если вы не находите логику в основном коде, возможно, она вынесена в общие модули с суффиксом Переопределяемый, где разработчики внедряют специфические отраслевые изменения.

Таким образом, «магия» проведения в КА 2.4 и ERP — это строго выверенная архитектурная схема. Понимание цепочки «Запрос в менеджере -> Таблица в ДополнительныхСвойствах -> Метод Загрузить() в наборе записей -> Автоматическая запись платформой» позволяет быстро и эффективно диагностировать любые проблемы с проведением документов в современных системах 1С. Для наглядного изучения взаимосвязи процедур и функций типового алгоритма подойдёт схема типового механизма проведения документов в ERP 2.5.

← На главную