Почему возникают отрицательные остатки при программном проведении «Отчета производства за смену» и как это исправить?

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

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

Анализ проблемы конкуренции транзакций

Основная сложность заключается в том, что при программном создании и проведении документов в цикле все они могут получить одинаковую временную метку (дату и время с точностью до секунды). Когда система 1С обращается к регистрам остатков, она видит несколько документов, пытающихся списать один и тот же ресурс в один и тот же момент времени. В результате СУБД блокирует данные, и последующие документы в цикле «не видят» движений, которые были совершены предыдущими документами, что приводит к появлению отрицательных значений.

Решение проблемы: распределение временных меток

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

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

Пошаговое руководство по оптимизации программного проведения

  1. Инициализация времени: При старте цикла определим базовую дату и время.
  2. Инкремент времени: В каждой итерации цикла при создании нового документа будем увеличивать время на одну или несколько секунд, используя метод ДобавитьСекунду().
  3. Запись и проведение: Выполним запись документа с проведением, чтобы движения по регистрам были сформированы актуально.

Посмотрим на пример того, как это можно реализовать в вашем коде:


// Предположим, что у нас есть дата начала проведения
ТекущееВремя = ДатаНачала;

Для Каждого СтрокаДанных Из СписокДокументов Цикл
    НовыйДокумент = Документы.ОтчетПроизводстваЗаСмену.СоздатьДокумент();
    // ... заполнение реквизитов документа ...
    
    // Сдвигаем время на 1 секунду для следующего документа
    ТекущееВремя = ТекущееВремя + 1;
    НовыйДокумент.Дата = ТекущееВремя;
    
    НовыйДокумент.Записать(РежимЗаписиДокумента.Проведение);
КонецЦикла;

Почему это работает?

Когда мы присваиваем каждому документу уникальное время, мы фактически выстраиваем очередь в регистрах накопления. Даже если обработка длится значительное время (например, 3 часа), добавление приращения в одну секунду на документ практически не увеличивает общее время работы, но полностью исключает «гонку» за остатками и проблему «невидимости» движений.

Дополнительные рекомендации по оптимизации

Если документов очень много, помимо сдвига времени, мы рекомендуем обратить внимание на следующие аспекты:

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

← На главную