При построении отчетов в СКД на базе 1С:Управление торговлей 11 часто возникает задача вывода остатков по нескольким складам, для каждого из которых должен применяться свой собственный Вид цены. Если просто соединить таблицу остатков с таблицей цен по одной лишь номенклатуре, мы получим логическую ошибку: цены будут «перемешиваться», и для остатка на одном складе может подтянуться цена, актуальная для другого.
Давайте разберем, как избежать декартового произведения и настроить отчет так, чтобы для каждого склада подбирался именно тот Вид цены, который к нему относится.
Проблема заключается в том, что в стандартных запросах связь между РегистрНакопления.ТоварыНаСкладах и РегистрСведений.ЦеныНоменклатуры не имеет жесткого ограничения по складу. Когда мы запрашиваем остатки по списку складов, база данных пытается соединить каждый полученный результат с ценами. Если мы не указываем, что конкретная цена принадлежит конкретному складу, система подтягивает «первую попавшуюся» цену для выбранной номенклатуры из списка видов цен, что и приводит к неверным цифрам.
Самый правильный и надежный путь — воспользоваться штатной архитектурой 1С:Управление торговлей. В справочнике Склады (или Магазины) существует предопределенный реквизит Вид цены. Он предназначен именно для того, чтобы связать торговую точку с прайс-листом.
Чтобы реализовать этот подход в запросе, выполните следующие шаги:
Вид цены для каждого из них выбран соответствующий вид цен.Склады.Пример реализации в коде запроса:
ВЫБРАТЬ
ТоварыНаСкладахОстатки.Склад КАК Склад,
ТоварыНаСкладахОстатки.Номенклатура КАК Товар,
ТоварыНаСкладахОстатки.ВНаличииОстаток КАК Остаток,
Склады.ВидЦены КАК ВидЦены
ПОМЕСТИТЬ ОстаткиСЦенами
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата, ) КАК ТоварыНаСкладахОстатки
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Склады КАК Склады
ПО ТоварыНаСкладахОстатки.Склад = Склады.Ссылка
;
ВЫБРАТЬ
Остатки.Товар,
Остатки.Склад,
Остатки.Остаток,
Цены.Цена
ИЗ
ОстаткиСЦенами КАК Остатки
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, ) КАК Цены
ПО Остатки.Товар = Цены.Номенклатура
И Остатки.ВидЦены = Цены.ВидЦены
Этот метод гарантирует, что для каждого склада будет выбрана цена, соответствующая его специфике, так как мы добавили условие Остатки.ВидЦены = Цены.ВидЦены в блок ПО.
Если вы не хотите прописывать жесткие связи в тексте запроса, воспользуйтесь возможностями визуальной настройки СКД. Этот метод позволяет гибко управлять данными без необходимости переписывать код.
Разберем процесс по шагам:
НаборДанных1 (Остатки) и НаборДанных2 (Цены).НаборДанных1 обязательно выведите поле Склад и поле ВидЦены (через связь со справочником Склады).НаборДанных1 (Остатки).НаборДанных2 (Цены).Номенклатура = Номенклатура И ВидЦены = ВидЦены.Использование этого метода позволяет СКД самостоятельно обработать соединения, учитывая контекст каждого склада, что исключает ошибки при выводе данных.
В процессе работы не забывайте про следующие технические нюансы:
Использование функции ЕСТЬNULL: Так как цена не всегда может быть установлена для номенклатуры, при левом соединении ЦеныНоменклатуры вы можете получить NULL. Чтобы в отчете вместо пустых полей видеть 0, используйте конструкцию ЕСТЬNULL(Цены.Цена, 0).
Оптимизация производительности: Старайтесь не соединять таблицы «всех со всеми». Если видов цен очень много, используйте в виртуальной таблице СрезПоследних параметр &ВидЦены, передавая туда только список необходимых видов цен, которые были выбраны в отчете. Это значительно сократит время формирования данных.
Проверка актуальности цен: Помните, что СрезПоследних возвращает значение на указанную дату. Если данные кажутся «неверными», проверьте, была ли установлена цена на нужный момент времени. Иногда проблема кроется не в коде, а в отсутствии записи в регистре на выбранную дату &ДатаЦен.
Применяя эти подходы, вы сможете добиться корректного отображения оценки складов, даже если каждый из них имеет свою уникальную ценовую политику.