При разработке отчетов или обработок в конфигурациях, базирующихся на классической архитектуре (таких как «Управление торговлей для Казахстана» ред. 2.2 или «Управление торговлей» ред. 10.3), начинающие программисты часто сталкиваются с проблемой: в виртуальных таблицах регистра ТоварыНаСкладах отсутствуют поля для получения суммы или стоимости. Рассмотрим, почему это происходит и как правильно составить запрос для получения данных по beg_amount (стоимости начального остатка).
Для начала проанализируем ситуацию: в системе 1С разделяются понятия оперативного количественного учета и стоимостного (финансового) учета. Регистр накопления ТоварыНаСкладах является регистром остатков, но он предназначен исключительно для контроля физического наличия товара на конкретных складах. В его структуре есть измерения Номенклатура, Склад, ХарактеристикаНоменклатуры и ресурс Количество. Суммовых ресурсов здесь нет по определению, поэтому обращение к полю СуммаНачальныйОстаток вызывает ошибку "Поле не найдено".
Чтобы получить стоимость, нам необходимо обратиться к другим регистрам. В зависимости от настроек вашей учетной политики, это могут быть:
ПартииТоваровНаСкладах (управленческий или бухгалтерский учет). Именно здесь хранится себестоимость каждой единицы товара в разрезе документов поступления.УчетЗатрат.ЦеныНоменклатуры.СрезПоследних.Разберем самый распространенный вариант, когда в базе ведется классический партионный учет. Для получения начальной стоимости нам понадобится виртуальная таблица ОстаткиИОбороты регистра ПартииТоваровНаСкладах. Посмотрим, как изменить исходный запрос, чтобы добавить в него данные о стоимости.
Важно помнить, что соединение количественного регистра со стоимостным должно происходить по всем ключевым измерениям: Номенклатура, Склад и Характеристика (если она используется). Рассмотрим пример структуры запроса с использованием временных таблиц для оптимизации производительности:
ВЫБРАТЬ
Партии.Номенклатура КАК Номенклатура,
Партии.Склад КАК Склад,
СУММА(Партии.КоличествоНачальныйОстаток) КАК КоличествоНач,
СУММА(Партии.СтоимостьНачальныйОстаток) КАК beg_amount
ПОМЕСТИТЬ ВТ_СтоимостьОстатков
ИЗ
РегистрНакопления.ПартииТоваровНаСкладах.ОстаткиИОбороты(&ДатаНач, &ДатаКон, , ,
Номенклатура В ИЕРАРХИИ (&Номенклатура) И Склад В ИЕРАРХИИ (&Склады)) КАК Партии
СГРУППИРОВАТЬ ПО
Партии.Номенклатура,
Партии.Склад;
Обратите внимание, что мы используем функцию СУММА и группировку. Это необходимо, так как регистр партий содержит дополнительное измерение — ДокументОприходования. Если мы не сгруппируем данные по номенклатуре, мы получим детальный разрез по каждой партии, что не требуется для общего отчета по остаткам.
Теперь проанализируем, как объединить полученную стоимость с оборотами из основного регистра. В исходном коде автора использовалось ПОЛНОЕ СОЕДИНЕНИЕ, что не всегда оправдано и может замедлять работу базы. Рекомендуется использовать виртуальную таблицу ОстаткиИОбороты регистра ТоварыНаСкладах как основную, так как она уже содержит и приходы, и расходы, и остатки.
Выясним причину, по которой стоит использовать ЕСТЬ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
ИЗ
РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&ДатаНач, &ДатаКон, Период, ,
Номенклатура В ИЕРАРХИИ (&Номенклатура) И Склад В ИЕРАРХИИ (&Склады)) КАК ТоварыОстатки
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_СтоимостьОстатков КАК Стоимость
ПО ТоварыОстатки.Номенклатура = Стоимость.Номенклатура
И ТоварыОстатки.Склад = Стоимость.Склад
Если ваша конфигурация использует РАУЗ, то разделение на «количественные» и «стоимостные» регистры исчезает. В этом случае мы работаем с регистром УчетЗатрат. Рассмотрим, как изменится подход: в данном регистре есть измерение АналитикаУчетаНоменклатуры, которое ссылается на специальный справочник, где «схлопнуты» номенклатура, склад и характеристики. Для работы с ним в запросах часто используются дополнительные соединения для получения понятных полей.
В параметрах виртуальной таблицы регистра УчетЗатрат необходимо указать фильтр по разделу учета (например, Товары), чтобы не получить данные по услугам или затратам на производство. Поле стоимости в таком регистре обычно называется Стоимость.
Проанализируем несколько советов, которые помогут избежать ошибок при расчете стоимости:
ТоварыНаСкладах ведется без разреза по организациям. Стоимостной же учет (в партиях) всегда привязан к конкретной организации. Если вы хотите, чтобы beg_rest * Цена = beg_amount, в параметрах регистра партий обязательно добавьте фильтр Организация = &Организация.ХарактеристикаНоменклатуры в условия связи таблиц.ОстаткиИОбороты используйте периодичность Период или Авто, если вам нужна детальная информация по датам, или Период, если нужны только итоговые значения за интервал.Иногда пользователю не нужна фактическая себестоимость (которая зависит от даты закупки), а нужна оценка текущего остатка по фиксированной цене (например, розничной). В этом случае мы не используем регистры партий. Мы берем количество из ТоварыНаСкладах и умножаем его на актуальную цену из регистра сведений ЦеныНоменклатуры.СрезПоследних.
Посмотрим на пример такого расчета в поле запроса:
ЕСТЬNULL(ТоварыОстатки.КоличествоНачальныйОстаток, 0) * ЕСТЬNULL(Цены.Цена, 0) КАК beg_amount
В данном случае таблица Цены подключается левым соединением по номенклатуре (и характеристике), а в параметрах виртуальной таблицы цен передается дата начала периода и нужный тип цен.
Таким образом, решение задачи зависит от того, какую именно «стоимость» вы хотите увидеть в отчете. Для управленческой себестоимости используйте ПартииТоваровНаСкладах, для бухгалтерской — ПартииТоваровНаСкладах (налоговый учет), а для оценочной — регистр цен. Помните о правилах группировки и обязательной фильтрации по организации для получения корректных финансовых показателей.