Как правильно проверить остатки товара при проведении документа перемещения в 1С?

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

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

Анализ основных ошибок в запросе контроля остатков

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

  1. Некорректное обращение к табличной части документа. При обращении через точку вида ПеремещениеТовара.ТабличнаяЧасть1.(Номенклатура) запрос возвращает не отдельное поле, а вложенную результат-таблицу. Для корректной работы нужно обращаться непосредственно к табличной части документа как к самостоятельной таблице: Документ.ПеремещениеТовара.ТабличнаяЧасть1.
  2. Использование внутреннего соединения вместо левого. Использование соединения ВНУТРЕННЕЕ СОЕДИНЕНИЕ отсекает строки с номенклатурой, которой вообще нет в остатках на данном складе. В результате, если позиция на складе отсутствует полностью, условие соединения не выполнится, и запрос не вернет строку с ошибкой, допуская списание.
  3. Проверка некорректного условия остатка. Условие вида ОстаткиОстатки.КоличествоОстаток < 0 проверяет только уже существующий отрицательный остаток. Если на складе числится 1 единица товара, а перемещается 5 единиц, данный запрос не выявит нехватку, так как текущий остаток положительный (1 > 0). Проверять необходимо соотношение запрашиваемого количества и фактического остатка.
  4. Отсутствие сводной группировки по номенклатуре. В табличной части документа одна и та же номенклатура может встречаться несколькими строками. Если не сгруппировать строки перед проверкой остатков, то расчет суммарной потребности будет неверным.

Правильный алгоритм контроля остатков в 1С

Разберем по шагам корректную схему проверки остатков с использованием временных таблиц:

  1. Выбираем из табличной части проводимого документа номенклатуру и суммируем ее количество, фильтруя по текущему документу (по параметру &Ссылка). Помещаем эти данные во временную таблицу НоменклатураКСписанию.
  2. Связываем временную таблицу НоменклатураКСписанию с виртуальной таблицей РегистрНакопления.Остатки.Остатки с помощью конструкции ЛЕВОЕ СОЕДИНЕНИЕ.
  3. В параметрах виртуальной таблицы остатков передаем отбор по складу Склад = &СкладОткуда и списку номенклатуры из временной таблицы.
  4. С помощью функции ЕСТЬNULL обрабатываем случаи, когда товара на складе нет (значение NULL заменяем на 0).
  5. В секции ГДЕ устанавливаем условие: остаток товара на складе меньше, чем количество, указанное в документе.

Посмотрим на готовый пример текста запроса для контроля остатков:


ВЫБРАТЬ
    ПеремещениеТабличнаяЧасть1.Номенклатура КАК Номенклатура,
    СУММА(ПеремещениеТабличнаяЧасть1.Количество) КАК Количество
ПОМЕСТИТЬ НоменклатураКСписанию
ИЗ
    Документ.ПеремещениеТовара.ТабличнаяЧасть1 КАК ПеремещениеТабличнаяЧасть1
ГДЕ
    ПеремещениеТабличнаяЧасть1.Ссылка = &Ссылка
СГРУППИРОВАТЬ ПО
    ПеремещениеТабличнаяЧасть1.Номенклатура
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    НоменклатураКСписанию.Номенклатура КАК Номенклатура,
    НоменклатураКСписанию.Количество КАК Количество,
    ЕСТЬNULL(ОстаткиОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток,
    НоменклатураКСписанию.Количество - ЕСТЬNULL(ОстаткиОстатки.КоличествоОстаток, 0) КАК КоличествоНехватает
ИЗ
    НоменклатураКСписанию КАК НоменклатураКСписанию
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.Остатки.Остатки(
                &Период,
                Склад = &СкладОткуда
                    И Номенклатура В
                        (ВЫБРАТЬ
                            НоменклатураКСписанию.Номенклатура
                        ИЗ
                            НоменклатураКСписанию)) КАК ОстаткиОстатки
        ПО ОстаткиОстатки.Номенклатура = НоменклатураКСписанию.Номенклатура
ГДЕ
    ЕСТЬNULL(ОстаткиОстатки.КоличествоОстаток, 0) < НоменклатураКСписанию.Количество

Обработка результатов запроса в модуле документа

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


Запрос = Новый Запрос;
Запрос.Текст = "..."; // Текст запроса выше

Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.УстановитьПараметр("СкладОткуда", СкладОткуда);
Запрос.УстановитьПараметр("Период", МоментВремени());

Результат = Запрос.Выполнить();

Если НЕ Результат.Пустой() Тогда
    Выборка = Результат.Выбрать();
    Пока Выборка.Следующий() Цикл
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = СтрШаблон("Не хватает %1 ед. товара ""%2""", 
            Выборка.КоличествоНехватает, 
            Выборка.Номенклатура);
        Сообщение.Сообщить();
    КонецЦикла;
    
    Отказ = Истина;
КонецЕсли;

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

Для обеспечения стабильной и корректной работы системы при параллельном проведении документов обратите внимание на следующие стандарты:

← На главную