В практике разработки на платформе 1С:Предприятие 8.3 часто возникают задачи, когда стандартного получения остатков на определенную дату недостаточно. Типичный пример: компания торгует товарами с ограниченным сроком реализации (продукты питания, алкоголь, фармакология), и нам необходимо не просто увидеть остаток, а отсечь те позиции, которые «зависли» на складе дольше определенного периода (например, более 30 дней). В этой статье мы подробно разберем, как технически реализовать получение таких «очищенных» остатков, проанализируем вопросы производительности и рассмотрим методологические нюансы учета.
Прежде чем приступать к написанию кода, давайте разберем, что именно может скрываться за фразой «получить остатки за последний месяц». Проанализируем два принципиально разных подхода, которые часто путают начинающие разработчики:
ДатаНач и ДатаКон.Рассмотрим подробнее каждый из этих вариантов и выберем наиболее эффективные инструменты реализации.
Если ваша задача — понять, сколько товара осталось от поступившего именно в этом месяце (игнорируя старые запасы), самым простым и логичным решением будет использование виртуальной таблицы Обороты регистра накопления. Посмотрим на пример запроса:
ВЫБРАТЬ
РегистрОбороты.Номенклатура,
РегистрОбороты.КоличествоПриход - РегистрОбороты.КоличествоРасход КАК ЧистыйОстатокЗаПериод
ИЗ
РегистрНакопления.ТоварыНаСкладах.Обороты(&ДатаНач, &ДатаКон, , ) КАК РегистрОбороты
Проанализируем этот подход. Метод эффективен, если нам нужно получить разницу между приходом и расходом. Однако, как верно подмечено в обсуждении, если расход в этом периоде превысил приход (за счет остатков прошлых периодов), мы получим отрицательное число. Если бизнес-логика подразумевает, что на ДатаНач остаток «условно ноль», то отрицательный результат будет корректным отражением того, что со склада ушло больше, чем пришло в этом месяце.
Альтернативный вариант для этой же задачи — использование таблицы ОстаткиИОбороты. Мы можем вычислить разницу между конечным и начальным остатком. Однако, с точки зрения производительности 1С, таблица Обороты всегда будет работать быстрее, так как системе не требуется обращаться к таблице итогов для расчета остатков на две разные точки времени.
Это более сложная и часто встречающаяся задача. Допустим, мы реализуем механизм автоматического подбора партий в документе отгрузки. Система должна работать по принципу FIFO (First In, First Out), но с жестким ограничением: нельзя отгружать товар из партий, которые поступили более 30 дней назад. Такие товары считаются просроченными или требующими специальной обработки (переработки, списания).
Рассмотрим, как правильно составить запрос к виртуальной таблице Остатки. Для этого нам необходимо, чтобы в регистре накопления в качестве одного из измерений выступала Партия (обычно это документ поступления).
ВЫБРАТЬ
ТоварыНаСкладахОстатки.Номенклатура,
ТоварыНаСкладахОстатки.Партия,
ТоварыНаСкладахОстатки.КоличествоОстаток
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(
&Период,
Партия.Дата >= ДОБАВИТЬКДАТЕ(&Период, ДЕНЬ, -30)
) КАК ТоварыНаСкладахОстатки
Важный технический нюанс: Обратите внимание, что условие фильтрации мы накладываем не в секции ГДЕ, а непосредственно в параметрах виртуальной таблицы (второй параметр — Условие). Проанализируем ситуацию: если мы напишем условие в ГДЕ, система сначала выберет все остатки по всем партиям из базы данных, а потом начнет их фильтровать. Если же условие передано в параметры виртуальной таблицы, СУБД выполнит фильтрацию на этапе формирования выборки, что значительно сэкономит ресурсы сервера.
Рассмотрим подробнее вопрос производительности. Обращение к реквизиту через точку (Партия.Дата) внутри запроса заставляет СУБД выполнять неявное соединение таблиц (JOIN). Если в регистре миллионы записей, это может замедлить проведение документа. Чтобы ускорить работу, воспользуемся следующими рекомендациями:
Дата.В процессе обсуждения задачи выяснилось, что ограничение в 30 дней связано с порчей товара. Проанализируем ситуацию: дата поступления партии (FIFO) не всегда напрямую коррелирует со сроком годности. Товар, пришедший вчера, может иметь меньший запас срока годности, чем товар, пришедший неделю назад. В таких случаях профессиональным стандартом является использование алгоритма FEFO (First Expired, First Out) — «первым истекает — первым выходит».
Для реализации FEFO в структуру регистра накопления добавляется измерение Серия или СрокГодности. Запрос при этом остается похожим, но сортировка и фильтрация производятся не по дате документа, а по конкретной дате годности товара.
Реализуя фильтрацию в запросе, мы фактически скрываем часть товаров от пользователя или алгоритма проведения. Но эти товары по-прежнему числятся на остатках в базе данных. Проанализируем последствия: бухгалтер видит в отчетах одну сумму, а менеджер по продажам при подборе — другую. Это создает почву для ошибок и инвентаризационных разрывов.
Для правильного решения этой проблемы рекомендуется внедрить один из следующих механизмов:
Подведем итог нашему разбору. Получение остатков «за период» в 1С требует четкого понимания цели. Если нам нужны обороты — используем таблицу Обороты. Если нам нужны актуальные остатки по свежим поступлениям — используем таблицу Остатки с фильтрацией по дате партии в параметрах таблицы. Помните об индексах и о том, что просто скрыть данные в запросе недостаточно — необходимо продумать бизнес-процесс работы с просроченным товаром.