Почему документ закрытия заказов списывает лишние остатки и как это исправить?

Программист 1С v8.3 (Обычные формы) Управленческий учет Промышленность, строительство и АПК
← На главную

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

Понимаем природу проблемы «одной секунды»

Прежде чем переходить к коду, давайте проанализируем, почему это происходит. В платформе 1С документы с одинаковой датой и временем упорядочиваются по значению МоментВремени. Когда вы формируете запрос к виртуальной таблице ОстаткиИОбороты, платформа интерпретирует накопленные движения исходя из того, как именно мы передаем параметры периода. Если в одну секунду попадает и РеализацияТоваровУслуг, и ваш документ ЗакрытиеЗаказовПокупателей, система не всегда может однозначно определить, что было раньше, если мы не используем механизм Граница.

Ваша обработка через запрос видит корректные остатки, потому что запрос учитывает движения за период целиком. Однако сам документ, при проведении, может обращаться к остаткам «на дату», и если он видит ситуацию «до реализации» в рамках одной секунды, он пытается списать сумму, которую реализация уже «съела».

Решение №1: Использование механизма Границ

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

Рассмотрим, как это выглядит программно:


// Создаем момент времени на конец месяца
МоментВремени = Новый МоментВремени(КонецДня(ДатаМесяца), Неопределено);
// Формируем границу, включая документы в эту секунду
ГраницаПериода = Новый Граница(МоментВремени, ВидГраницы.Включая);

// Теперь в запросе используем эту границу для получения остатков
Запрос.Текст = "ВЫБРАТЬ
               |    ЗаказыОстатки.КоличествоОстаток,
               |    ЗаказыОстатки.СуммаОстаток
               |ИЗ
               |    РегистрНакопления.ЗаказыПокупателей.Остатки(&ГраницаПериода, ) КАК ЗаказыОстатки";
Запрос.УстановитьПараметр("ГраницаПериода", ГраницаПериода);

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

Решение №2: Управление хронологией и временем документов

Если программная реализация через границы кажется избыточной, давайте разберем административный подход, который часто применяют в УПП для разграничения операций:

  1. Смещение времени: Установите время для документов ЗакрытиеЗаказовПокупателей строго на 23:59:59, а для всех товарных операций (Реализаций) — на 23:59:58. Это гарантирует, что при стандартном последовательном проведении реализация всегда будет первой в очереди.
  2. Использование последовательностей: В УПП крайне важно использовать механизм Последовательности. Если вы перепроводите документы за месяц, убедитесь, что документ закрытия входит в последовательность и перепроводится после всех реализаций.
  3. Тестирование и исправление: Если вы уверены в коде, но остатки всё равно «гуляют», выполните процедуру «Тестирование и исправление» с пунктом «Пересчет итогов». В старых версиях платформы кэширование итогов в таблицах РегистрНакопления могло приводить к отображению некорректных данных до момента их физического пересчета.

Важные рекомендации при разработке

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

Также помните: при проведении документа закрытия лучше всего опираться на остатки по регистру на момент проведения, полученные через запрос к виртуальной таблице Остатки с использованием Граница, созданной на момент времени текущего документа. Это исключит возможность попадания в «серую зону» одной секунды.

Соблюдая эти простые правила работы с МоментВремени и Граница, вы навсегда забудете о проблемах с «отрицательными остатками» при закрытии заказов. Работайте с платформой последовательно, и она ответит вам корректными данными!

← На главную