Протестировано на релизе Управление торговлей, редакция 11.4.8.92.
В моей организации отдел маркетинга поставил следующую задачу: необходимо организовать установку цен в соответствии с заданным в настройках процентом для сегмента либо определенной позиции номенклатуры.
Хочу поделиться тем, каким образом данная задача была решена.
Сразу хочу оговориться, что в нашей системе есть справочник так называемых «Собственных констант», куда мы заносим различные предопределенные элементы и другие настройки.
Знаю, что может быть критика насчет доработки конфигурации и т.д. Но иногда без этого не обойтись. И честно говоря ничего критичного в этом не вижу, если доработки сделаны таким образом, чтобы типовые объекты не изменялись и код в объектах системы не корректировался.
Для реализации данного функционала мы добавили в конфигурацию два объекта: Определяемый тип «ОС_СобственныеКонстанты» (в нем задали составной тип, указав справочники «Номенклатура» и «Сегменты номенклатуры») и справочник «ОС_СобственныеКонстанты» с реквизитами Значение и ДополнительноеЗначение (у обоих реквизитов определяемый тип: ОС_СобственныеКонстанты). Так-же добавили табличную часть с аналогичными реквизитами (префикс добавлен чтобы видно было собственные доработки и при обновлении не возник конфликт имен).
Таким образом в данном справочнике можно задавать любые значения, используя их в различных задачах.
Добавим в справочник элемент "Наценка на инструмент". В табличной части зададим сегмент номенклатуры "Инструмент" с наценкой 30% и выделим отдельно позицию "Вентилятор настольный", наценка 25%:
Если позиция номенклатуры есть в сегменте, но помимо этого выделена отдельно, приоритетом будет процент, установленный на позицию отдельно.
Теперь создаем вид цены "Наценка на инструмент", где установим способ задания цены "Произвольный запрос к данным ИБ". При чем для корректной работы нашей создаваемой СКД необходимо установить значение "Произвольный". Если корректировать типовую СКД, то система будет отрабатывать по своим правилам и велика вероятность ошибки.
За основу можно взять любую подходящую СКД.
Логика запроса следующая:
- Т.к. наценка будет устанавливаться на базовый вид цены, формируем выборку по регистру сведений "Цены номенклатуры" срез последних, где в условии задаем базовый вид цены;
- Выбираем из табличной части справочника "Собственные константы" элементы номенклатуры. В условии задаем ссылку на элемент этого справочника, чтобы для любого вида цены можно было задать свои различные варианты наценок.
- Аналогично формируем выборку из нашего справочника по сегментам (при соединении таблиц будет установлен приоритет на элемент).
- Соединяем и группируем данные (в моем случае в группировке средняя цена).
- И в итоговой таблице считаем цену позиций с учетом полученного процента.
Таблицы запроса:
Часть запроса СКД выложу в виде текста. Вы сможете по этим данным сами соединить таблицы и сформировать итоговый расчет. Готовая СКД есть в прикреплении. Можете ее скачать и просто загрузить в настройках вида цены:
ВЫБРАТЬ РАЗЛИЧНЫЕ
Сегменты.Номенклатура КАК Номенклатура,
Сегменты.Характеристика КАК Характеристика,
ИСТИНА КАК ИспользуетсяОтборПоСегментуНоменклатуры
ПОМЕСТИТЬ ОтборПоСегментуНоменклатуры
ИЗ
РегистрСведений.НоменклатураСегмента КАК Сегменты
{ГДЕ
Сегменты.Сегмент.* КАК СегментНоменклатуры,
Сегменты.Номенклатура.* КАК Номенклатура,
Сегменты.Характеристика.* КАК Характеристика}
ИНДЕКСИРОВАТЬ ПО
Сегменты.Номенклатура,
Сегменты.Характеристика,
ИспользуетсяОтборПоСегментуНоменклатуры
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ЦеныНоменклатурыСрезПоследних.Номенклатура КАК Номенклатура,
ЦеныНоменклатурыСрезПоследних.Характеристика КАК Характеристика,
ЦеныНоменклатурыСрезПоследних.Упаковка КАК Упаковка,
&Валюта КАК Валюта,
1 КАК Коэффициент,
(ВЫРАЗИТЬ(ВЫБОР
КОГДА ВидыЦен.ЦенаВключаетНДС
И ЦеныНоменклатурыСрезПоследних.ВидЦены.ЦенаВключаетНДС
ИЛИ НЕ ВидыЦен.ЦенаВключаетНДС
И НЕ ЦеныНоменклатурыСрезПоследних.ВидЦены.ЦенаВключаетНДС
ТОГДА ЦеныНоменклатурыСрезПоследних.Цена
КОГДА ВидыЦен.ЦенаВключаетНДС
И НЕ ЦеныНоменклатурыСрезПоследних.ВидЦены.ЦенаВключаетНДС
ТОГДА ЦеныНоменклатурыСрезПоследних.Цена + ЦеныНоменклатурыСрезПоследних.Цена * ВЫБОР
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20)
ТОГДА 0.2
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС18)
ТОГДА 0.18
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС10)
ТОГДА 0.1
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС0)
ТОГДА 0
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.БезНДС)
ТОГДА 0
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20_120)
ТОГДА 0.2
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС18_118)
ТОГДА 0.18
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС10_110)
ТОГДА 0.1
ИНАЧЕ 0
КОНЕЦ
КОГДА НЕ ВидыЦен.ЦенаВключаетНДС
И ЦеныНоменклатурыСрезПоследних.ВидЦены.ЦенаВключаетНДС
ТОГДА ЦеныНоменклатурыСрезПоследних.Цена - ЦеныНоменклатурыСрезПоследних.Цена * ВЫБОР
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20)
ТОГДА 20 / 120
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС18)
ТОГДА 18 / 118
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС10)
ТОГДА 10 / 110
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС0)
ТОГДА 0
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.БезНДС)
ТОГДА 0
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20_120)
ТОГДА 20 / 120
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС18_118)
ТОГДА 18 / 118
КОГДА ЦеныНоменклатурыСрезПоследних.Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС10_110)
ТОГДА 10 / 110
ИНАЧЕ 0
КОНЕЦ
КОНЕЦ КАК ЧИСЛО(15, 2))) * ВЫБОР
КОГДА &Валюта <> ЦеныНоменклатурыСрезПоследних.Валюта
ТОГДА ВЫБОР
КОГДА ЕСТЬNULL(КурсыВалютыЦены.Кратность, 0) > 0
И ЕСТЬNULL(КурсыВалютыЦены.Курс, 0) > 0
И ЕСТЬNULL(КурсыВалюты.Кратность, 0) > 0
И ЕСТЬNULL(КурсыВалюты.Курс, 0) > 0
ТОГДА КурсыВалютыЦены.Курс * КурсыВалюты.Кратность / (КурсыВалюты.Курс * КурсыВалютыЦены.Кратность)
ИНАЧЕ 0
КОНЕЦ
ИНАЧЕ 1
КОНЕЦ КАК Цена
ПОМЕСТИТЬ ЦеныНоменклатурыПоБазовомуВиду
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних({(КОНЕЦПЕРИОДА(&ДатаДокумента, ДЕНЬ))}, ВидЦены = &БазовыйВидЦены {((Номенклатура, Характеристика) В
(ВЫБРАТЬ
ОтборПоСегментуНоменклатуры.Номенклатура,
ОтборПоСегментуНоменклатуры.Характеристика
ИЗ
ОтборПоСегментуНоменклатуры
ГДЕ
ОтборПоСегментуНоменклатуры.ИспользуетсяОтборПоСегментуНоменклатуры = &ИспользуетсяОтборПоСегментуНоменклатуры))}) КАК ЦеныНоменклатурыСрезПоследних
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних({(КОНЕЦПЕРИОДА(&ДатаДокумента, ДЕНЬ))}, ) КАК КурсыВалютыЦены
ПО ЦеныНоменклатурыСрезПоследних.Валюта = КурсыВалютыЦены.Валюта
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют.СрезПоследних({(КОНЕЦПЕРИОДА(&ДатаДокумента, ДЕНЬ))}, Валюта = &Валюта) КАК КурсыВалюты
ПО (ИСТИНА)
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыЦен КАК ВидыЦен
ПО (ВидыЦен.Ссылка = &ВидЦены)
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ОС_СобственныеКонстантыДанные.Значение КАК Номенклатура,
ВЫРАЗИТЬ(ЕСТЬNULL(ОС_СобственныеКонстантыДанные.ДополнительноеЗначение, 0) КАК ЧИСЛО(15, 2)) КАК ПроцентПоНоменклатуре
ПОМЕСТИТЬ ПроцентыПоНоменклатуре
ИЗ
Справочник.ОС_СобственныеКонстанты.Данные КАК ОС_СобственныеКонстантыДанные
ГДЕ
НЕ ОС_СобственныеКонстантыДанные.Значение ССЫЛКА Справочник.СегментыНоменклатуры
И ОС_СобственныеКонстантыДанные.Ссылка = &Наценка
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ОС_СобственныеКонстантыДанные.Значение КАК НоменклатураСегмент,
ВЫРАЗИТЬ(ЕСТЬNULL(ОС_СобственныеКонстантыДанные.ДополнительноеЗначение, 0) КАК ЧИСЛО(15, 2)) КАК ПроцентПоСегменту
ПОМЕСТИТЬ ПроцентыПоСегментам
ИЗ
Справочник.ОС_СобственныеКонстанты.Данные КАК ОС_СобственныеКонстантыДанные
ГДЕ
ОС_СобственныеКонстантыДанные.Значение ССЫЛКА Справочник.СегментыНоменклатуры
И ОС_СобственныеКонстантыДанные.Ссылка = &Наценка
;
В параметрах зададим базовый вид цены "Себестоимость" и нашу наценку:
Для простоты примера установил себестоимость вручную для 3-х элементов сегмента и рассчитал данные:
При формировании цен расчет автоматически не выполняется (не могу сказать почему) и для пересчета необходимо выбрать пункт меню "Рассчитать вычисляемые (по данным ИБ и формулам)":
Все три позиции есть в сегменте. Однако 1-й Вентилятор рассчитался исходя из установленной наценки в 25, а не 30%, т.к. он был в справочнике выделен отдельно.
Статья очень помогла. Спасибо!
Сначала хотел сделать аналогично, но используя доп реквизиты номенклатуры и сегмента, задавая в них процент наценки. Однако в этом случае не получилось бы при расчете нескольких видов цен для одной и той-же позиции либо сегмента номенклатуры задать различные проценты наценок. А так — все универсальненько. И типовые объекты не задеты. Да и справочник «Собственные константы» думаю еще не раз пригодиться. В том числе и при разработке обменов.
(1) Рад что пригодилась! У нас кстати данный справочник так-же принимает участие в различных обменах между системами.