Определение количества дней, когда товар фактически присутствовал на складе, — это одна из важнейших задач при расчете товарооборачиваемости и анализе эффективности работы отдела закупок. Стандартные отчеты не всегда дают прозрачную картину, особенно если товар часто поступает и продается «с колес» или имеет значительные периоды отсутствия. В этой статье мы подробно разберем, как реализовать этот расчет с помощью механизмов системы компоновки данных и языка запросов 1С.
Существует два основных методологических подхода к решению этой задачи: анализ временных интервалов (разрывов) и использование таблицы дат (календаря). Проанализируем каждый из них, разберем их преимущества и приведем примеры программного кода.
Этот метод считается наиболее производительным и точным, так как он не требует перебора всех дней месяца. Мы находим только те моменты времени, когда остаток товара становился нулевым, и вычитаем длительность этих «дыр» из общей продолжительности анализируемого периода. Рассмотрим пошагово, как построить такой запрос.
Для начала нам необходимо получить все движения товара с периодичностью Секунда. Мы будем использовать виртуальную таблицу ОстаткиИОбороты регистра накопления ТоварыНаСкладах.
ВЫБРАТЬ
Движения.Склад,
Движения.Номенклатура,
Движения.Период,
Движения.КоличествоНачальныйОстаток,
Движения.КоличествоКонечныйОстаток
ПОМЕСТИТЬ Движения
ИЗ
РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Секунда, , ) КАК Движения
;
Обратите внимание: чтобы корректно обработать ситуации, когда товара не было на начало или на конец периода, нам нужно искусственно добавить записи-заглушки. Это позволит запросу «увидеть» отсутствие товара, если последняя продажа была до начала месяца или если товар так и не поступил до конца месяца.
ВЫБРАТЬ
Движения.Склад,
Движения.Номенклатура,
Движения.Период,
Движения.КоличествоНачальныйОстаток,
Движения.КоличествоКонечныйОстаток
ПОМЕСТИТЬ ДополненныеДвижения
ИЗ
Движения КАК Движения
ОБЪЕДИНИТЬ
ВЫБРАТЬ РАЗЛИЧНЫЕ
НачальныеНули.Склад,
НачальныеНули.Номенклатура,
&НачалоПериода,
0,
0
ИЗ
Движения КАК НачальныеНули
ОБЪЕДИНИТЬ
ВЫБРАТЬ РАЗЛИЧНЫЕ
КонечныеНули.Склад,
КонечныеНули.Номенклатура,
&КонецПериода,
0,
0
ИЗ
Движения КАК КонечныеНули
;
Затем мы находим интервалы, где КоличествоНачальныйОстаток и КоличествоКонечныйОстаток равны нулю. Разница между началом такого интервала и его концом — это время отсутствия товара. Суммируя эти интервалы и вычитая их из общего количества секунд в периоде, мы получаем чистый остаток времени наличия.
ВЫБРАТЬ
Интервалы.Склад,
Интервалы.Номенклатура,
СУММА(РАЗНОСТЬДАТ(Интервалы.Период, Интервалы.НачалоОтсутствия, СЕКУНДА)) / 86400 КАК ДнейНаличия
ИЗ
Интервалы КАК Интервалы
СГРУППИРОВАТЬ ПО
Интервалы.Склад,
Интервалы.Номенклатура
Преимущество данного подхода в том, что он учитывает даже те случаи, когда товар поступил и был продан внутри одного дня. Если вы будете оперировать только остатками на начало дня, такие движения будут потеряны.
Если задача стоит проще — посчитать количество календарных дней, на начало которых товар был в наличии, — удобнее использовать соединение со справочником дат или регистром сведений РегламентированныйПроизводственныйКалендарь. Разберем этот алгоритм.
Пример запроса для реализации такой логики (адаптировано под конфигурации типа УТ 10.3 или старые редакции БП):
ВЫБРАТЬ
Календарь.ДатаКалендаря ПОМЕСТИТЬ ТабДат
ИЗ
РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК Календарь
ГДЕ
Календарь.ДатаКалендаря МЕЖДУ &ДатаНачала И &ДатаОкончания;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Остатки.Номенклатура,
КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ТабДат.ДатаКалендаря) КАК КоличествоДнейВНаличии
ИЗ
ТабДат КАК ТабДат
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаНачала, ) КАК Остатки
ПО (ИСТИНА)
ГДЕ
Остатки.КоличествоОстаток > 0
СГРУППИРОВАТЬ ПО
Остатки.Номенклатура
Важный нюанс: при использовании этого метода нужно четко понимать требования бизнеса. Если товар пришел в 10 утра и был продан в 16 часов того же дня, то остаток на начало дня был равен 0. В этом случае день не будет засчитан как «день наличия», хотя фактически товар на складе был и продажи по нему могли осуществляться.
Проанализируем ситуацию, когда расчет дней наличия нужен исключительно для формулы оборачиваемости. В классической экономике часто используется метод средней хронологической. Он позволяет нивелировать резкие скачки остатков. Формула выглядит так:
СреднийОстаток = (Остаток_Т1/2 + Остаток_Т2 + Остаток_Т3 + ... + Остаток_Тн/2) / (n - 1)
Где n — количество точек замера (например, дней). В 1С это реализуется через СКД (Систему компоновки данных), где можно настроить расчет ресурсов по периодам. Однако, если ваша цель — именно число дней, когда полка не была пустой, лучше вернуться к Метод 1.
Выясним причину, почему иногда расчет по регистру ТоварыНаСкладах может быть бесполезен для бизнеса. Представьте ситуацию: на складе лежит 100 единиц товара, но все они зарезервированы под конкретный заказ клиента. Для нового покупателя этого товара нет в наличии.
В таких случаях при расчете дней наличия необходимо использовать регистры, учитывающие резервы (например, ТоварыВРезервеНаСкладах или виртуальные таблицы СвободныеОстатки в УТ 11/ERP). Логика запроса при этом остается прежней, но в качестве источника данных выступает разность:
ДоступныйОстаток = ОстатокНаСкладе - Резерв
Секунда. Для долго оборачиваемых товаров (стройматериалы, оборудование) достаточно периодичности День.Подводя итог, можно сказать: наиболее универсальным решением для программиста 1С является интервальный метод. Он сложнее в написании, но гарантирует корректность данных при любых внутридневных операциях, что критически важно для качественного управленческого учета.