Как получить остатки по регистру накопления за последний месяц или по свежим партиям

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

В практике разработки на платформе 1С:Предприятие 8.3 часто возникают задачи, когда стандартного получения остатков на определенную дату недостаточно. Типичный пример: компания торгует товарами с ограниченным сроком реализации (продукты питания, алкоголь, фармакология), и нам необходимо не просто увидеть остаток, а отсечь те позиции, которые «зависли» на складе дольше определенного периода (например, более 30 дней). В этой статье мы подробно разберем, как технически реализовать получение таких «очищенных» остатков, проанализируем вопросы производительности и рассмотрим методологические нюансы учета.

Анализ постановки задачи: остаток или оборот?

Прежде чем приступать к написанию кода, давайте разберем, что именно может скрываться за фразой «получить остатки за последний месяц». Проанализируем два принципиально разных подхода, которые часто путают начинающие разработчики:

  1. Математический остаток за период: Нам нужно узнать, как изменилось состояние склада исключительно в рамках выбранного диапазона дат. В этом случае мы условно принимаем начальный остаток за ноль и смотрим только на движения (приходы и расходы), произошедшие между ДатаНач и ДатаКон.
  2. Остатки по «свежим» партиям: Нам нужны реальные остатки на текущий момент, но только по тем партиям (документам поступления), которые были созданы не ранее, чем за 30 дней до даты документа.

Рассмотрим подробнее каждый из этих вариантов и выберем наиболее эффективные инструменты реализации.

Вариант 1: Получение чистого оборота за период

Если ваша задача — понять, сколько товара осталось от поступившего именно в этом месяце (игнорируя старые запасы), самым простым и логичным решением будет использование виртуальной таблицы Обороты регистра накопления. Посмотрим на пример запроса:


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

Проанализируем этот подход. Метод эффективен, если нам нужно получить разницу между приходом и расходом. Однако, как верно подмечено в обсуждении, если расход в этом периоде превысил приход (за счет остатков прошлых периодов), мы получим отрицательное число. Если бизнес-логика подразумевает, что на ДатаНач остаток «условно ноль», то отрицательный результат будет корректным отражением того, что со склада ушло больше, чем пришло в этом месяце.

Альтернативный вариант для этой же задачи — использование таблицы ОстаткиИОбороты. Мы можем вычислить разницу между конечным и начальным остатком. Однако, с точки зрения производительности 1С, таблица Обороты всегда будет работать быстрее, так как системе не требуется обращаться к таблице итогов для расчета остатков на две разные точки времени.

Вариант 2: Остатки с фильтром по дате партии (FIFO с ограничением)

Это более сложная и часто встречающаяся задача. Допустим, мы реализуем механизм автоматического подбора партий в документе отгрузки. Система должна работать по принципу FIFO (First In, First Out), но с жестким ограничением: нельзя отгружать товар из партий, которые поступили более 30 дней назад. Такие товары считаются просроченными или требующими специальной обработки (переработки, списания).

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


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

Важный технический нюанс: Обратите внимание, что условие фильтрации мы накладываем не в секции ГДЕ, а непосредственно в параметрах виртуальной таблицы (второй параметр — Условие). Проанализируем ситуацию: если мы напишем условие в ГДЕ, система сначала выберет все остатки по всем партиям из базы данных, а потом начнет их фильтровать. Если же условие передано в параметры виртуальной таблицы, СУБД выполнит фильтрацию на этапе формирования выборки, что значительно сэкономит ресурсы сервера.

Оптимизация производительности при работе с датами партий

Рассмотрим подробнее вопрос производительности. Обращение к реквизиту через точку (Партия.Дата) внутри запроса заставляет СУБД выполнять неявное соединение таблиц (JOIN). Если в регистре миллионы записей, это может замедлить проведение документа. Чтобы ускорить работу, воспользуемся следующими рекомендациями:

  1. Индексирование: Убедитесь, что у документа-регистратора (который является партией) проиндексировано поле Дата.
  2. Использование дополнительных реквизитов: Если вы используете характеристики или серии, дату окончания срока годности (или дату поступления) лучше хранить как отдельный реквизит серии и индексировать его.
  3. Предварительный расчет даты: Всегда вычисляйте граничную дату в коде 1С перед передачей в запрос, а не внутри самого запроса функциями SQL, чтобы планировщик запросов СУБД мог построить оптимальный план.

Методология учета: FEFO вместо FIFO

В процессе обсуждения задачи выяснилось, что ограничение в 30 дней связано с порчей товара. Проанализируем ситуацию: дата поступления партии (FIFO) не всегда напрямую коррелирует со сроком годности. Товар, пришедший вчера, может иметь меньший запас срока годности, чем товар, пришедший неделю назад. В таких случаях профессиональным стандартом является использование алгоритма FEFO (First Expired, First Out) — «первым истекает — первым выходит».

Для реализации FEFO в структуру регистра накопления добавляется измерение Серия или СрокГодности. Запрос при этом остается похожим, но сортировка и фильтрация производятся не по дате документа, а по конкретной дате годности товара.

Что делать с «невидимыми» остатками?

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

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

Итоги

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

← На главную