Почему в подписке на проведение пуст регистр ПродажиСебестоимость и как это исправить

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

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

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

Архитектурная причина: почему движения не видны в контексте документа

Проанализируем, как формируются записи в типовой конфигурации. Формирование движений по регистру сведений и накопления себестоимости и партий товаров вынесено в отдельный общий механизм партионного учета. Этот механизм проектировался разработчиками фирмы «1С» универсальным, чтобы алгоритм списания мог запускаться в двух различных режимах:

  1. Оперативно «на лету» в момент проведения документа пользователем.
  2. Регламентно в фоновом режиме через обработку «Проведение по партиям» (восстановление партионной последовательности).

Чтобы модуль партионного учета мог одинаково функционировать как в контексте проведения объекта, так и абсолютно автономно по ссылке на документ, формирование и сохранение движений по регистру ПродажиСебестоимость выполняется не через стандартную коллекцию ЭтотОбъект.Движения, а через создание независимого набора записей:


НаборЗаписей = РегистрыНакопления.ПродажиСебестоимость.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Ссылка);
// Заполнение набора...
НаборЗаписей.Записать();

Когда управление передается в подписку на событие ОбработкаПроведения, в базе данных внутри текущей транзакции эти строки уже физически сохранены. Однако экземпляр объекта документа, переданный в подписку в параметре Источник, ничего не знает о стороннем наборе записей. В оперативной памяти его коллекция Источник.Движения.ПродажиСебестоимость остается несинхронизированной и пустой.

Главная опасность: случайная перезапись и потеря движений

Внимательно отнесемся к работе с флагом записи набора. Если разработчик в коде подписки попытается принудительно выставить:

Источник.Движения.ПродажиСебестоимость.Записывать = Истина;

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

Также важно помнить о настройках учетной политики: если в параметрах учета снят флаг «Списывать партии при проведении документов», регистр ПродажиСебестоимость при проведении документов вообще не заполняется. В этом случае расчет себестоимости откладывается до запуска регламентной обработки восстановления последовательности, и чтение регистра в момент проведения закономерно вернет пустой результат.

Решение проблемы: синхронизация набора через метод Прочитать()

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

Посмотрим на практический пример реализации процедуры подписки на проведение:


Процедура ОбработкаПроведенияПослеПартий(Источник, Отказ, РежимПроведения) Экспорт

    // 1. Считываем из базы данных движения, созданные модулем партионного учета
    Источник.Движения.ПродажиСебестоимость.Прочитать();

    // 2. Если движений нет (например, партии не списываются оперативно), выходим
    Если Источник.Движения.ПродажиСебестоимость.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;

    // 3. Обходим строки набора записей и вносим необходимые корректировки
    Для Каждого Движение Из Источник.Движения.ПродажиСебестоимость Цикл
        // Пример: увеличиваем себестоимость по определенному условию
        Движение.Стоимость = Движение.Стоимость * 1.1;
    КонецЦикла;

    // 4. Указываем платформе, что измененный набор должен быть сохранен
    Источник.Движения.ПродажиСебестоимость.Записывать = Истина;

КонецПроцедуры

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

Ограничения механизма подписок на события платформы 1С

Разберем важный платформенный нюанс. Платформа 1С гарантирует, что любые подписки на событие ОбработкаПроведения выполняются строго после завершения процедуры ОбработкаПроведения модуля самого документа. Однако если в конфигурации создано несколько подписок на одно и то же событие для одного объекта, порядок их взаимного вызова не регламентирован и не зависит от алфавитного порядка их наименований.

Поэтому не следует разделять логику на несколько зависимых друг от друга подписок (когда одна подписка формирует данные, а вторая пытается их перехватить). Логику модификации движений надежнее всего консолидировать в единой процедуре.

Методологические риски и альтернативные подходы

Перед внесением изменений в регистр ПродажиСебестоимость проанализируем влияние такой доработки на целостность управленческого учета:

  1. Рассинхронизация с партионным учетом: Регистр ПродажиСебестоимость является оборотным и используется для формирования отчетов по валовой прибыли. Списание же физической стоимости товара со складов фиксируется в регистре остатков ПартииТоваровНаСкладах. Если скорректировать стоимость только в продажах, но не затронуть регистр партий, возникнет расхождение между фактическими складскими остатками по себестоимости и финансовым результатом от продаж.
  2. Встраивание в механизм партионного учета: Если необходимо системно изменить себестоимость при списании, более корректно вмешаться в подготовку исходных данных непосредственно в модуле проведения документа перед передачей управления в общий модуль партионного учета.
  3. Использование документа «Корректировка записей регистров»: Любые ручные правки в движениях первичного документа продажи будут перезаписаны при первом же групповом перепроведении документов или штатном восстановлении партионной последовательности. Использование отдельного документа КорректировкаЗаписейРегистров позволяет зафиксировать управленческие корректировки отдельной операцией, защищенной от автоматического пересчета.
← На главную