Как в запросе 1С получить стоимость начального остатка на складе

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

При разработке отчетов или обработок в конфигурациях, базирующихся на классической архитектуре (таких как «Управление торговлей для Казахстана» ред. 2.2 или «Управление торговлей» ред. 10.3), начинающие программисты часто сталкиваются с проблемой: в виртуальных таблицах регистра ТоварыНаСкладах отсутствуют поля для получения суммы или стоимости. Рассмотрим, почему это происходит и как правильно составить запрос для получения данных по beg_amount (стоимости начального остатка).

Разбор архитектуры регистров накопления

Для начала проанализируем ситуацию: в системе 1С разделяются понятия оперативного количественного учета и стоимостного (финансового) учета. Регистр накопления ТоварыНаСкладах является регистром остатков, но он предназначен исключительно для контроля физического наличия товара на конкретных складах. В его структуре есть измерения Номенклатура, Склад, ХарактеристикаНоменклатуры и ресурс Количество. Суммовых ресурсов здесь нет по определению, поэтому обращение к полю СуммаНачальныйОстаток вызывает ошибку "Поле не найдено".

Чтобы получить стоимость, нам необходимо обратиться к другим регистрам. В зависимости от настроек вашей учетной политики, это могут быть:

  1. Регистры партионного учета: ПартииТоваровНаСкладах (управленческий или бухгалтерский учет). Именно здесь хранится себестоимость каждой единицы товара в разрезе документов поступления.
  2. Регистр учета затрат: Если в базе включен режим расширенной аналитики учета затрат (РАУЗ), то все данные (и количество, и стоимость) хранятся в универсальном регистре УчетЗатрат.
  3. Регистры сведений: Если под «стоимостью» понимается оценка остатков в ценах номенклатуры (например, по прайс-листу), используется регистр ЦеныНоменклатуры.СрезПоследних.

Шаг 1: Получение себестоимости через регистр партий

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

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


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

Обратите внимание, что мы используем функцию СУММА и группировку. Это необходимо, так как регистр партий содержит дополнительное измерение — ДокументОприходования. Если мы не сгруппируем данные по номенклатуре, мы получим детальный разрез по каждой партии, что не требуется для общего отчета по остаткам.

Шаг 2: Объединение количественных и стоимостных данных

Теперь проанализируем, как объединить полученную стоимость с оборотами из основного регистра. В исходном коде автора использовалось ПОЛНОЕ СОЕДИНЕНИЕ, что не всегда оправдано и может замедлять работу базы. Рекомендуется использовать виртуальную таблицу ОстаткиИОбороты регистра ТоварыНаСкладах как основную, так как она уже содержит и приходы, и расходы, и остатки.

Выясним причину, по которой стоит использовать ЕСТЬNULL. При левом соединении с регистром партий для товаров, по которым нет записи о стоимости (например, они были оприходованы некорректно), в поле суммы придет NULL. Чтобы это не испортило расчеты в коде 1С, всегда оборачивайте стоимостные поля в ЕСТЬNULL(..., 0).


ВЫБРАТЬ
    &ОсновнаяОрганизацияКод КАК whcode,
    ТоварыОстатки.Номенклатура.Код КАК code,
    &ДатаНач КАК curr_date,
    ЕСТЬNULL(ТоварыОстатки.КоличествоНачальныйОстаток, 0) КАК beg_rest,
    ЕСТЬNULL(ТоварыОстатки.КоличествоПриход, 0) КАК in_qty,
    ЕСТЬNULL(ТоварыОстатки.КоличествоРасход, 0) КАК out_qty,
    ЕСТЬNULL(ТоварыОстатки.КоличествоКонечныйОстаток, 0) КАК end_rest,
    ЕСТЬNULL(Стоимость.beg_amount, 0) КАК beg_amount,
    &manfid КАК manfid
ИЗ
    РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&ДатаНач, &ДатаКон, Период, , 
        Номенклатура В ИЕРАРХИИ (&Номенклатура) И Склад В ИЕРАРХИИ (&Склады)) КАК ТоварыОстатки
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_СтоимостьОстатков КАК Стоимость
ПО ТоварыОстатки.Номенклатура = Стоимость.Номенклатура
    И ТоварыОстатки.Склад = Стоимость.Склад

Шаг 3: Особенности для РАУЗ (Расширенная аналитика)

Если ваша конфигурация использует РАУЗ, то разделение на «количественные» и «стоимостные» регистры исчезает. В этом случае мы работаем с регистром УчетЗатрат. Рассмотрим, как изменится подход: в данном регистре есть измерение АналитикаУчетаНоменклатуры, которое ссылается на специальный справочник, где «схлопнуты» номенклатура, склад и характеристики. Для работы с ним в запросах часто используются дополнительные соединения для получения понятных полей.

В параметрах виртуальной таблицы регистра УчетЗатрат необходимо указать фильтр по разделу учета (например, Товары), чтобы не получить данные по услугам или затратам на производство. Поле стоимости в таком регистре обычно называется Стоимость.

Важные рекомендации по оптимизации

Проанализируем несколько советов, которые помогут избежать ошибок при расчете стоимости:

Оценка остатков по типу цен (Альтернативный вариант)

Иногда пользователю не нужна фактическая себестоимость (которая зависит от даты закупки), а нужна оценка текущего остатка по фиксированной цене (например, розничной). В этом случае мы не используем регистры партий. Мы берем количество из ТоварыНаСкладах и умножаем его на актуальную цену из регистра сведений ЦеныНоменклатуры.СрезПоследних.

Посмотрим на пример такого расчета в поле запроса:


ЕСТЬNULL(ТоварыОстатки.КоличествоНачальныйОстаток, 0) * ЕСТЬNULL(Цены.Цена, 0) КАК beg_amount

В данном случае таблица Цены подключается левым соединением по номенклатуре (и характеристике), а в параметрах виртуальной таблицы цен передается дата начала периода и нужный тип цен.

Таким образом, решение задачи зависит от того, какую именно «стоимость» вы хотите увидеть в отчете. Для управленческой себестоимости используйте ПартииТоваровНаСкладах, для бухгалтерской — ПартииТоваровНаСкладах (налоговый учет), а для оценочной — регистр цен. Помните о правилах группировки и обязательной фильтрации по организации для получения корректных финансовых показателей.

← На главную