Как определить документы поступления, из которых сформирован текущий остаток номенклатуры?

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

Когда в системе не ведется полноценный партионный учет, но для бизнес-задач (например, поиска брака, оценки срока хранения или определения себестоимости) требуется понять, какие именно приходы «лежат» в остатке, мы сталкиваемся с непростой задачей. Давайте разберем, как подойти к этому вопросу, используя возможности языка запросов 1С:Предприятие.

Понимание проблемы и ограничения

Основная сложность заключается в том, что в обычном регистре остатков ТоварыНаСкладах хранится только итоговое количество. Чтобы узнать «первоисточник» товара, нам нужно мысленно или программно восстановить историю списаний по методу FIFO (первым пришел — первым ушел). Попытка сделать это одним запросом на базе с десятилетней историей — задача нетривиальная, так как она требует выполнения тета-соединений, что на больших объемах данных может существенно замедлить работу системы.

Метод реализации через временные таблицы

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

  1. Получение текущих остатков: Сначала мы выбираем текущий остаток по интересующей нас номенклатуре на нужную дату.
  2. Выборка приходов: Выбираем все приходные движения из регистра за весь период (или с момента последней инвентаризации).
  3. Расчет накопленного итога: Используем тета-соединение приходов самих с собой, чтобы посчитать Сумму приходов, которые произошли ранее или одновременно с текущим документом. Это поможет нам понять, когда именно суммарное количество приходов покрывает наш остаток.
  4. Фильтрация данных: Выбираем те документы, чей накопленный итог наиболее близок к значению остатка.

Пример программной реализации

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


ВЫБРАТЬ
    ТоварыНаСкладахОстатки.Номенклатура КАК Номенклатура,
    ТоварыНаСкладахОстатки.ВНаличииОстаток КАК Остаток
ПОМЕСТИТЬ ВТ_Остатки
ИЗ
    РегистрНакопления.ТоварыНаСкладах.Остатки(&Момент, Номенклатура В (&СписокНоменклатуры)) КАК ТоварыНаСкладахОстатки
;

ВЫБРАТЬ
    ТоварыНаСкладах.Период КАК Период,
    ТоварыНаСкладах.Регистратор КАК Регистратор,
    ТоварыНаСкладах.Номенклатура КАК Номенклатура,
    ТоварыНаСкладах.ВНаличии КАК Приход
ПОМЕСТИТЬ ВТ_Приходы
ИЗ
    РегистрНакопления.ТоварыНаСкладах КАК ТоварыНаСкладах
ГДЕ
    ТоварыНаСкладах.Номенклатура В(&СписокНоменклатуры)
    И ТоварыНаСкладах.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
;

ВЫБРАТЬ
    ВТ_Приходы.Регистратор,
    ВТ_Приходы.Период,
    ВТ_Приходы.Номенклатура,
    СУММА(ВТ_Приходы1.Приход) КАК НакопленныйПриход
ПОМЕСТИТЬ ВТ_ФИФО
ИЗ
    ВТ_Приходы КАК ВТ_Приходы
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Приходы КАК ВТ_Приходы1
    ПО ВТ_Приходы.Номенклатура = ВТ_Приходы1.Номенклатура
    И ВТ_Приходы.Период >= ВТ_Приходы1.Период
СГРУППИРОВАТЬ ПО
    ВТ_Приходы.Регистратор,
    ВТ_Приходы.Период,
    ВТ_Приходы.Номенклатура

Рекомендации по оптимизации

Чтобы ваш отчет не «вешал» базу данных, важно соблюдать следующие правила:

Заключение

Задача определения поступлений по остаткам — это классическая проблема «квазипартионного учета». Мы с вами разобрали, что ее можно решить через накопленные итоги во временных таблицах, но это всегда компромисс между гибкостью отчета и нагрузкой на СУБД. Всегда начинайте с анализа объема данных и возможности использования типовых механизмов, прежде чем приступать к написанию сложных многоэтапных запросов.

← На главную