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