Разберем распространенную ситуацию при сдаче экзаменов «1С:Специалист» или решении задач оперативного учета: в процедуре ОбработкаПроведения расходного документа (например, Расходная Накладная) выявляется нехватка остатков товара на складе точки продаж. Программа автоматически создает и проводит документ Перемещение, чтобы восполнить дефицит, после чего расходный документ формирует свои движения. Однако при повторном запросе остатков или проверке движений выясняется, что приход от перемещения оказывается хронологически позже расхода либо запрос получает некорректные данные.
Выясним причину такого поведения платформы 1С:Предприятие 8 и рассмотрим, как правильно организовать работу с временной осью и архитектурой проведения.
Проанализируем, почему возникает смещение движений на оси времени:
Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Оперативный), платформа присваивает создаваемому документу текущую оперативную отметку времени. Она чаще всего оказывается строго больше даты и времени документа-инициатора, проводимого неоперативно.МоментВремени() виртуальная таблица считывает состояние регистра до момента проведения текущего документа. Чтобы учесть движения, записанные в той же транзакции с аналогичной датой, требуется явное переформирование границы времени.Если условие учебной задачи требует непременного формирования подчиненных документов перемещения в момент проведения, необходимо принудительно смещать дату создаваемого документа назад и задействовать неоперативный режим проведения.
Рассмотрим пошаговый алгоритм решения:
Перемещение на 1 секунду раньше даты основного документа (Дата - 1).Пример программного создания и проведения документа перемещения:
// Внутри процедуры ОбработкаПроведения расходного документа
ДокПеремещение = Документы.ПеремещениеТоваров.СоздатьДокумент();
ДокПеремещение.Дата = Дата - 1; // Сдвигаем время на 1 секунду назад
ДокПеремещение.СкладОтправитель = СкладЗакупок;
ДокПеремещение.СкладПолучатель = СкладПродаж;
// Заполнение табличной части необходимым количеством
СтрТаб = ДокПеремещение.Товары.Добавить();
СтрТаб.Номенклатура = ТекущаяНоменклатура;
СтрТаб.Количество = НеобходимоеКоличество;
ДокПеремещение.Записать(РежимЗаписиДокумента.Проведение, РежимПроведенияДокумента.Неоперативный);
За счет сдвига даты на Дата - 1 движения перемещения попадут на ось времени раньше движений расходной накладной, и расчет себестоимости и остатков пройдет корректно.
С точки зрения стандартов разработки 1С и реальной эксплуатации систем, «рождать» документы прямо внутри процедуры ОбработкаПроведения не рекомендуется. При перепроведении расходной накладной система будет регулярно плодить дублирующие документы перемещения либо приведёт к коллизиям и блокировкам данных в транзакции.
Рассмотрим правильную организацию бизнес-логики:
НачнитеТранзакцию();
Попытка
// 1. Создаем и проводим необходимые перемещения
СоздатьИПровестиПеремещения();
// 2. Проводим основной документ
ЭтотОбъект.Записать(РежимЗаписиДокумента.Проведение);
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
Разберем вариант с применением новой методики проведения, которая предотвращает лишние запросы к остаткам до записи движений:
Резюме: Чтобы движения подчиненного документа гарантированно предшествовали движениям документа-инициатора, используйте неоперативное проведение со сдвигом даты на секунду назад (Дата - 1). В реальных проектах переносите логику генерации документов из процедуры ОбработкаПроведения в обработчики формы или специальные модули до начала проведения основного документа.