Как рассчитать среднюю цену товара в запросе 1С по данным бухгалтерского учета?

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

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

Как 1С хранит данные об остатках и стоимости

Прежде чем переходить к написанию кода, проанализируем ситуацию с хранением данных в системе. Многие начинающие разработчики задаются вопросом: хранятся ли остатки на каждый день в готовом виде или они вычисляются заново? В платформе 1С реализован гибридный механизм. Основным источником данных для бухгалтерских отчетов является РегистрБухгалтерии (обычно с именем Хозрасчетный).

Для оптимизации скорости работы платформа использует специальные таблицы итогов. В них хранятся рассчитанные значения остатков и оборотов в разрезе периодов (обычно — конец каждого месяца). Когда мы обращаемся к виртуальной таблице Остатки на произвольную дату, система не сканирует все документы с начала ведения учета. Она берет данные из итогов за последний закрытый месяц и добавляет к ним движения документов за текущий период до указанной даты. Это позволяет получать данные очень быстро, даже если в базе накоплены миллионы записей.

Базовая структура запроса для получения остатков

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


ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет КАК Счет,
    ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
    ХозрасчетныйОстатки.КоличествоОстатокДт КАК Количество,
    ХозрасчетныйОстатки.СуммаОстатокДт КАК Сумма
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки КАК ХозрасчетныйОстатки

В данном примере СуммаОстатокДт — это стоимость товаров без НДС (так как НДС в 1С обычно учитывается на 19 счете отдельно), а КоличествоОстатокДт — физический остаток на складах.

Проблема деления на ноль и расчет средней цены

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

Чтобы избежать этой ошибки, мы должны использовать конструкцию ВЫБОР. Разберем два подхода к решению этой задачи.

Способ 1: Использование условного оператора ВЫБОР

Это самый надежный и прозрачный метод. Мы проверяем, равно ли количество нулю. Если равно — выводим 0, если нет — производим деление. Посмотрим на пример кода:


ВЫБРАТЬ
    ХозрасчетныйОстатки.Счет КАК Счет,
    ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
    ХозрасчетныйОстатки.КоличествоОстатокДт КАК Количество,
    ХозрасчетныйОстатки.СуммаОстатокДт КАК Сумма,
    ВЫБОР
        КОГДА ХозрасчетныйОстатки.КоличествоОстатокДт = 0
            ТОГДА 0
        ИНАЧЕ ХозрасчетныйОстатки.СуммаОстатокДт / ХозрасчетныйОстатки.КоличествоОстатокДт
    КОНЕЦ КАК СредняяЦена
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки КАК ХозрасчетныйОстатки

Важный момент: использование функции ЕСТЬNULL также является хорошим тоном, особенно если вы используете левые соединения таблиц. Если данных в регистре нет, поле может содержать NULL, что приведет к ошибке при математических операциях.

Способ 2: Универсальная формула с защитой делителя

Рассмотрим более лаконичный вариант, который часто применяют опытные разработчики. Вместо того чтобы выводить 0, мы можем подставить единицу в делитель в случае нулевого остатка. Это не всегда корректно с точки зрения математики (цена станет равна сумме), но позволяет избежать прерывания запроса:


ЕСТЬNULL(ХозрасчетныйОстатки.СуммаОстатокДт, 0) / 
ВЫБОР 
    КОГДА ЕСТЬNULL(ХозрасчетныйОстатки.КоличествоОстатокДт, 0) = 0 
    ТОГДА 1 
    ИНАЧЕ ХозрасчетныйОстатки.КоличествоОстатокДт 
КОНЕЦ КАК СредняяЦена

Оптимизация: работа с параметрами виртуальных таблиц

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

Выясним, как это сделать правильно. Виртуальная таблица остатков имеет следующие параметры: (&Период, &УсловиеСчета, &Субконто, &Условие). Перепишем наш запрос с учетом оптимизации:


ВЫБРАТЬ
    ХозрасчетныйОстатки.Субконто1 КАК Номенклатура,
    ХозрасчетныйОстатки.КоличествоОстатокДт КАК Количество,
    ХозрасчетныйОстатки.СуммаОстатокДт КАК Сумма,
    ВЫБОР
        КОГДА ХозрасчетныйОстатки.КоличествоОстатокДт <> 0
            ТОГДА ХозрасчетныйОстатки.СуммаОстатокДт / ХозрасчетныйОстатки.КоличествоОстатокДт
        ИНАЧЕ 0
    КОНЕЦ КАК СредняяЦена
ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(&ДатаОстатков, Счет В ИЕРАРХИИ (&СписокСчетов), , ) КАК ХозрасчетныйОстатки
ГДЕ
    ХозрасчетныйОстатки.КоличествоОстатокДт <> 0

В данном случае мы добавили условие Счет В ИЕРАРХИИ (&СписокСчетов) внутрь параметров таблицы. Это заставляет СУБД отсекать ненужные данные еще на этапе формирования выборки, что существенно экономит ресурсы сервера.

Особенности учета: Сумма без количества

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

  1. Ошибки последовательности: Товар был списан по времени раньше, чем приходовался (в пределах одного дня).
  2. Регламентные операции: В конце месяца при расчете себестоимости по средней 1С делает корректирующие проводки, которые обнуляют количественный остаток, но могут оставить «хвосты» в несколько копеек на стоимостном остатке.
  3. Ручные операции: Бухгалтер мог вручную скорректировать только одно измерение (сумму), забыв про количество.

Поэтому в реальных отчетах рекомендуется добавлять условие ГДЕ КоличествоОстатокДт <> 0. Это позволит не выводить в отчет «мусорные» записи, которые только путают пользователя.

Выводы и рекомендации

Мы проанализировали процесс получения средней цены в 1С через запросы к регистру бухгалтерии. Подведем итоги нашей совместной работы:

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

← На главную