Вводные
- Управление торговлей 11.4, код общих модулей в 11.5 немного изменен
- Обработка округления по строке //infostart.ru/public/1012492/
- Доработка через расширение
Варианты применения
- Нужно сочетать примененные ручные скидки с автоматическими (максимум, округление по строке)
- Нужно изолировать скидку, полученную от внешнего сервиса системы бонусов.
Ограничение
- Скидки считаю только для док. Заказ клиента, для остального на данный момент не требуется
- Статья рассчитана на программистов, которые в состоянии встроить наработки, cfe/epf не будет, т.к. код выделен из большей подсистемы.
Реализация
Из вводных сделал вывод, что нужно выделить скидки от внешних сервисов в отдельные реквизиты ТЧ Товары, для того чтобы данные не пересекались с вводом пользователей.
В расширении в ТЧ Товары док. ЗаказКлиента добавил реквизиты
- мб_опт_ПроцентСкидкиНаценки (Число 10,2)
- мб_опт_СуммаСкидки (Число 10,2)
В форме документа добавил колонки программно
ЭлементФормы = Элементы.Добавить("мб_опт_ПроцентСкидкиНаценки", Тип("ПолеФормы"), Элементы.Товары);
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
ЭлементФормы.ТолькоПросмотр = Истина;
ЭлементФормы.Заголовок = "% мен.";
ЭлементФормы.ПутьКДанным = "Объект.Товары.мб_опт_ПроцентСкидкиНаценки";
ЭлементФормы.Ширина = 7;
Элементы.Переместить(ЭлементФормы, Элементы.Товары, Элементы.ТоварыСумма);
ЭлементФормы = Элементы.Добавить("мб_опт_СуммаСкидки", Тип("ПолеФормы"), Элементы.Товары);
ЭлементФормы.Вид = ВидПоляФормы.ПолеВвода;
ЭлементФормы.ТолькоПросмотр = Истина;
ЭлементФормы.Заголовок = "Сумма мен.";
ЭлементФормы.ПутьКДанным = "Объект.Товары.мб_опт_СуммаСкидки";
ЭлементФормы.Ширина = 7;
Элементы.Переместить(ЭлементФормы, Элементы.Товары, Элементы.ТоварыСумма);
Расчет через автоматические скидки
Создал внешнюю обработку расчета скидки
Функция СведенияОВнешнейОбработке() Экспорт
Возврат СкидкиНаценкиСервер.ПараметрыРегистрацииВнешнейОбработкиСкидкиНаценки(
НСтр("ru = 'Скидка (наценка) из ручной скидки'"),
НСтр("ru = 'Скидка (наценка) из ручной скидки'"));
КонецФункции
Функция СпособПрименения() Экспорт
КонецФункции
Функция Рассчитать(СкидкаНаценка, Настройки, Товары, ПараметрыРасчета) Экспорт
РезультатРасчета = СкидкиНаценкиСервер.ПустаяТаблицаСкидокСРасшифровкой();
Если ПараметрыРасчета.Свойство("Регистратор")
И ТипЗнч(ПараметрыРасчета.Регистратор) = Тип("ДокументСсылка.ЗаказКлиента")
Тогда
Для Каждого СтрТовар из Товары Цикл
СкидкиНаценкиСервер.ПрименитьЗначениеСкидкиКТовару(СкидкаНаценка, СтрТовар.мб_опт_СуммаСкидки, СтрТовар, РезультатРасчета, ПараметрыРасчета);
КонецЦикла;
КонецЕсли;
Возврат РезультатРасчета;
КонецФункции
Функция ИмяФормыНастроек() Экспорт
КонецФункции
Функция ОписаниеДействия(Настройки) Экспорт
КонецФункции
Функция Автонаименование(Настройки) Экспорт
КонецФункции
Проблема в том что в обработку передается не ТЧ а ТЗ из запроса дополнения наборами, поэтому изменил общий модуль, добавив в выборку добавленные реквизиты ТЧ.
&ИзменениеИКонтроль("РассчитатьПоЗаказуКлиента")
Функция мб_опт_РассчитатьПоЗаказуКлиента(Объект, ВходныеПараметры) Экспорт
УстановитьПривилегированныйРежим(Истина);
ЗаполнитьКлючиСвязиВТабличнойЧастиТовары(Объект, "Товары");
ИспользоватьНаборы = ПолучитьФункциональнуюОпцию("ИспользоватьНаборы");
// Обработка табличной части "Товары".
ТекстЗапроса =
"ВЫБРАТЬ
| Товары.КлючСвязи КАК КлючСвязи,
| %ПоляНабора%
| Товары.Номенклатура КАК Номенклатура,
| Товары.Характеристика КАК Характеристика,
| Товары.Упаковка КАК Упаковка,
| Товары.Серия КАК Серия,
| Товары.Склад КАК Склад,
| Товары.ВидЦены КАК ВидЦены,
| Товары.Количество КАК Количество,
#Вставка
| Товары.мб_опт_ПроцентСкидкиНаценки КАК мб_опт_ПроцентСкидкиНаценки,
| Товары.мб_опт_СуммаСкидки КАК мб_опт_СуммаСкидки,
#КонецВставки
| Товары.КоличествоУпаковок КАК КоличествоУпаковок,
| Товары.Цена КАК Цена,
| Товары.Цена * Товары.КоличествоУпаковок КАК Сумма
|ПОМЕСТИТЬ ВТТовары
|ИЗ
| &Товары КАК Товары
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Таблица.КлючСвязи,
| %Поля%
| Таблица.Номенклатура,
| Таблица.Характеристика,
| Таблица.Упаковка,
| Таблица.Серия,
| Таблица.Склад,
| Таблица.ВидЦены,
| СправочникНоменклатура.ЦеноваяГруппа КАК ЦеноваяГруппа,
| Таблица.Количество,
#Вставка
| Таблица.мб_опт_ПроцентСкидкиНаценки,
| Таблица.мб_опт_СуммаСкидки,
#КонецВставки
| Таблица.КоличествоУпаковок,
| Таблица.Цена,
| Таблица.Сумма
|%ИмяВременнойТаблицы%
|ИЗ
| ВТТовары КАК Таблица
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура
| ПО СправочникНоменклатура.Ссылка = Таблица.Номенклатура
| %Соединение%
|ГДЕ
| ВЫБОР
| КОГДА &ВозвратТары ТОГДА
| Таблица.Номенклатура.ТипНоменклатуры <> ЗНАЧЕНИЕ(Перечисление.ТипыНоменклатуры.МногооборотнаяТара)
| ИНАЧЕ
| ИСТИНА
| КОНЕЦ
|%ЗапросНаборы%
|";
ТаблицаТовары = Объект.Товары.Выгрузить();
ПараметрыЗапроса = Новый Структура;
ПараметрыЗапроса.Вставить("Товары", ТаблицаТовары);
ПараметрыЗапроса.Вставить("ВозвратТары", Объект.ВернутьМногооборотнуюТару);
#Удаление
ДанныеПоТоварамИНаборам = ДанныеПоТоварамИНаборам(ТекстЗапроса, ПараметрыЗапроса, ИспользоватьНаборы);
#КонецУдаления
#Вставка
ДанныеПоТоварамИНаборам = мб_опт_ДанныеПоТоварамИНаборам(ТекстЗапроса, ПараметрыЗапроса, ИспользоватьНаборы);
#КонецВставки
СкидкиНаценки = СкидкиНаценкиДляОптовойТорговли(
Объект.Дата,
Объект.Склад,
Объект.Соглашение,
Объект.КартаЛояльности);
ПараметрыРасчета = ПараметрыРасчета();
ПараметрыРасчета.СкидкиНаценки = СкидкиНаценки;
ПараметрыРасчета.Партнер = Объект.Партнер;
ПараметрыРасчета.Соглашение = Объект.Соглашение;
ПараметрыРасчета.Регистратор = Объект.Ссылка;
// Для скидки "За форму оплаты".
ПараметрыРасчета.ФормаОплаты = Объект.ФормаОплаты;
// Для скидки "За время продажи".
ПараметрыРасчета.ДеньНедели = Перечисления.ДниНедели.Получить(ДеньНедели(Объект.Дата) - 1);
ПараметрыРасчета.ТекущееВремя = ПолучитьТекущееВремяОбъекта(Объект);
ПараметрыРасчета.ТекущаяДата = ПолучитьТекущуюДатуОбъекта(Объект);
// Для скидки "За соблюдение графика оплаты".
ПараметрыРасчета.ГрафикОплаты = Объект.ГрафикОплаты;
// Карты лояльности
ПараметрыРасчета.КартаЛояльности = Объект.КартаЛояльности;
ПараметрыРасчета.Товары = ДанныеПоТоварамИНаборам.Товары;
ПараметрыРасчета.ВалютаДокумента = Объект.Валюта;
ПараметрыРасчета.ВалютаУправленческогоУчета = Константы.ВалютаУправленческогоУчета.Получить();
ПараметрыРасчета.Пользователь = Объект.Менеджер;
ПараметрыРасчета.Объект = Объект;
ПодготовитьДанныеОВыбранныхУправляемыхСкидках(Объект, ПараметрыРасчета, ВходныеПараметры);
ПримененныеСкидкиНаценки = РассчитатьДеревоСкидокНаценок(ПараметрыРасчета, ВходныеПараметры);
Если ИспользоватьНаборы И НЕ ВходныеПараметры.ТолькоПредварительныйРасчет Тогда
РаспределитьСкидкиНабораПоКомплектующим(ПримененныеСкидкиНаценки, ДанныеПоТоварамИНаборам.СоответствиеКлючей, ТаблицаТовары);
КонецЕсли;
Если ВходныеПараметры.ПрименятьКОбъекту Тогда
ПрименитьРезультатРасчетаКЗаказуКлиента(Объект, ПримененныеСкидкиНаценки);
КонецЕсли;
Возврат ПримененныеСкидкиНаценки;
КонецФункции
Функция мб_опт_ДанныеПоТоварамИНаборам(ТекстЗапроса, ПараметрыЗапроса, ИспользоватьНаборы)
ПоляНабора =
" Товары.НоменклатураНабора КАК НоменклатураНабора,
| Товары.ХарактеристикаНабора КАК ХарактеристикаНабора,
|";
Поля =
" ВариантыКомплектацииНоменклатуры.Ссылка КАК ВариантКомплектацииНоменклатуры,
| ВариантыКомплектацииНоменклатуры.ВариантПредставленияНабораВПечатныхФормах КАК ВариантПредставленияНабораВПечатныхФормах,
| ВариантыКомплектацииНоменклатуры.ВариантРасчетаЦеныНабора КАК ВариантРасчетаЦеныНабора,
| Таблица.НоменклатураНабора КАК НоменклатураНабора,
| Таблица.ХарактеристикаНабора КАК ХарактеристикаНабора,
|";
Соединение =
" ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВариантыКомплектацииНоменклатуры КАК ВариантыКомплектацииНоменклатуры
| ПО ВариантыКомплектацииНоменклатуры.Владелец = Таблица.НоменклатураНабора
| И ВариантыКомплектацииНоменклатуры.Характеристика = Таблица.ХарактеристикаНабора
| И ВариантыКомплектацииНоменклатуры.Основной
|";
ЗапросНаборы =
";
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Таблица.НоменклатураНабора КАК НоменклатураНабора,
| Таблица.ХарактеристикаНабора КАК ХарактеристикаНабора,
//#Вставка
| Таблица.мб_опт_ПроцентСкидкиНаценки КАК мб_опт_ПроцентСкидкиНаценки,
| Таблица.мб_опт_СуммаСкидки КАК мб_опт_СуммаСкидки,
//#КонецВставки
| МИНИМУМ(Таблица.КлючСвязи) КАК КлючСвязи,
| СУММА(Таблица.Цена * Таблица.КоличествоУпаковок) КАК Сумма
|ПОМЕСТИТЬ ВременнаяТаблицаНаборыПодготовка
|ИЗ
| Товары КАК Таблица
|
|ГДЕ
| Таблица.НоменклатураНабора <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| И Таблица.ВариантРасчетаЦеныНабора В (ЗНАЧЕНИЕ(Перечисление.ВариантыРасчетаЦенНаборов.ЦенаЗадаетсяЗаНаборРаспределяетсяПоЦенам),
| ЗНАЧЕНИЕ(Перечисление.ВариантыРасчетаЦенНаборов.ЦенаЗадаетсяЗаНаборРаспределяетсяПоДолям))
|
|СГРУППИРОВАТЬ ПО
| Таблица.НоменклатураНабора,
//#Вставка
| Таблица.мб_опт_ПроцентСкидкиНаценки,
| Таблица.мб_опт_СуммаСкидки,
//#КонецВставки
| Таблица.ХарактеристикаНабора
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Товары.НоменклатураНабора,
| Товары.ХарактеристикаНабора,
| Товары.Номенклатура,
| Товары.Характеристика,
| ВЫБОР КОГДА Товары.ВариантКомплектацииНоменклатуры.НоменклатураОсновногоКомпонента = Товары.Номенклатура
| И Товары.ВариантКомплектацииНоменклатуры.ХарактеристикаОсновногоКомпонента = Товары.Характеристика ТОГДА
| ИСТИНА
| ИНАЧЕ
| ЛОЖЬ
| КОНЕЦ КАК ОсновнаяКомплектующая,
| 0 КАК КоличествоПоУмолчанию,
| Товары.Количество КАК Количество
|ПОМЕСТИТЬ ВременнаяТаблицаНаборыДополнительноЧастьПервая
|ИЗ
| Товары КАК Товары
|
|ГДЕ
| Товары.НоменклатураНабора <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ВариантыКомплектацииНоменклатурыТовары.Ссылка.Владелец КАК НоменклатураНабора,
| ВариантыКомплектацииНоменклатурыТовары.Ссылка.Характеристика КАК ХарактеристикаНабора,
| ВариантыКомплектацииНоменклатурыТовары.Номенклатура КАК Номенклатура,
| ВариантыКомплектацииНоменклатурыТовары.Характеристика КАК Характеристика,
| ЛОЖЬ КАК ОсновнаяКомплектующая,
| СУММА(ВариантыКомплектацииНоменклатурыТовары.Количество) КАК КоличествоПоУмолчанию,
| 0 КАК Количество
|ИЗ
| Справочник.ВариантыКомплектацииНоменклатуры.Товары КАК ВариантыКомплектацииНоменклатурыТовары
|ГДЕ
| ВариантыКомплектацииНоменклатурыТовары.Ссылка В (ВЫБРАТЬ РАЗЛИЧНЫЕ Т.ВариантКомплектацииНоменклатуры ИЗ Товары КАК Т)
|
|СГРУППИРОВАТЬ ПО
| ВариантыКомплектацииНоменклатурыТовары.Ссылка.Владелец,
| ВариантыКомплектацииНоменклатурыТовары.Ссылка.Характеристика,
| ВариантыКомплектацииНоменклатурыТовары.Номенклатура,
| ВариантыКомплектацииНоменклатурыТовары.Характеристика,
| ЛОЖЬ
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Таблица.НоменклатураНабора,
| Таблица.ХарактеристикаНабора,
| Таблица.Номенклатура,
| Таблица.Характеристика,
| МАКСИМУМ(Таблица.ОсновнаяКомплектующая) КАК ОсновнаяКомплектующая,
| СУММА(Таблица.КоличествоПоУмолчанию) КАК КоличествоПоУмолчанию,
| СУММА(Таблица.Количество) КАК Количество
|ПОМЕСТИТЬ ВременнаяТаблицаНаборыДополнительноЧастьВторая
|ИЗ
| ВременнаяТаблицаНаборыДополнительноЧастьПервая КАК Таблица
|
|СГРУППИРОВАТЬ ПО
| Таблица.НоменклатураНабора,
| Таблица.ХарактеристикаНабора,
| Таблица.Номенклатура,
| Таблица.Характеристика
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Результат.НоменклатураНабора,
| Результат.ХарактеристикаНабора,
| ВЫРАЗИТЬ(МИНИМУМ(ВЫБОР
| КОГДА Результат.КоличествоПоУмолчанию <> 0 И Результат.ОсновнаяКомплектующая
| ТОГДА Результат.Количество / Результат.КоличествоПоУмолчанию
| ИНАЧЕ null
| КОНЕЦ) + 0.5 КАК Число(10,0)) - 1 КАК Количество
|ПОМЕСТИТЬ ВременнаяТаблицаНаборыДополнительно
|ИЗ
| ВременнаяТаблицаНаборыДополнительноЧастьВторая КАК Результат
|СГРУППИРОВАТЬ ПО
| Результат.НоменклатураНабора,
| Результат.ХарактеристикаНабора
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Таблица.НоменклатураНабора КАК НоменклатураНабора,
| Таблица.ХарактеристикаНабора КАК ХарактеристикаНабора,
| Таблица.КлючСвязи КАК КлючСвязи,
| ЕСТЬNULL(ВременнаяТаблицаНаборыДополнительно.Количество, 1) КАК КоличествоУпаковок,
| ЕСТЬNULL(ВременнаяТаблицаНаборыДополнительно.Количество, 1) КАК Количество,
//#Вставка
| Таблица.мб_опт_ПроцентСкидкиНаценки,
| Таблица.мб_опт_СуммаСкидки,
//#КонецВставки
| Таблица.Сумма КАК Сумма
|ПОМЕСТИТЬ ВременнаяТаблицаНаборы
|ИЗ
| ВременнаяТаблицаНаборыПодготовка КАК Таблица
| ЛЕВОЕ СОЕДИНЕНИЕ ВременнаяТаблицаНаборыДополнительно КАК ВременнаяТаблицаНаборыДополнительно
| ПО Таблица.НоменклатураНабора = ВременнаяТаблицаНаборыДополнительно.НоменклатураНабора
| И Таблица.ХарактеристикаНабора = ВременнаяТаблицаНаборыДополнительно.ХарактеристикаНабора
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Таблица.КлючСвязи,
| Таблица.НоменклатураНабора КАК Номенклатура,
| Таблица.ХарактеристикаНабора КАК Характеристика,
| ЗНАЧЕНИЕ(Справочник.УпаковкиЕдиницыИзмерения.ПустаяСсылка) КАК Упаковка,
| ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка) КАК Серия,
| ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка) КАК Склад,
| ЗНАЧЕНИЕ(Справочник.ВидыЦен.ПустаяСсылка) КАК ВидЦены,
| Таблица.НоменклатураНабора.ЦеноваяГруппа КАК ЦеноваяГруппа,
| Таблица.Количество,
| Таблица.КоличествоУпаковок,
//#Вставка
| Таблица.мб_опт_ПроцентСкидкиНаценки,
| Таблица.мб_опт_СуммаСкидки,
//#КонецВставки
| ВЫБОР КОГДА Таблица.КоличествоУпаковок <> 0 ТОГДА
| Таблица.Сумма / Таблица.КоличествоУпаковок
| ИНАЧЕ
| 0
| КОНЕЦ КАК Цена,
| Таблица.Сумма
|ИЗ
| ВременнаяТаблицаНаборы КАК Таблица
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Таблица.КлючСвязи,
| Таблица.Номенклатура,
| Таблица.Характеристика,
| Таблица.Упаковка,
| Таблица.Серия,
| Таблица.Склад,
| Таблица.ВидЦены,
| Таблица.ЦеноваяГруппа,
| Таблица.Количество,
| Таблица.КоличествоУпаковок,
//#Вставка
| Таблица.мб_опт_ПроцентСкидкиНаценки,
| Таблица.мб_опт_СуммаСкидки,
//#КонецВставки
| Таблица.Цена,
| Таблица.Сумма
|ИЗ
| Товары КАК Таблица
|ГДЕ
| Таблица.НоменклатураНабора = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| ИЛИ (Таблица.НоменклатураНабора <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| И Таблица.ВариантРасчетаЦеныНабора = ЗНАЧЕНИЕ(Перечисление.ВариантыРасчетаЦенНаборов.РассчитываетсяИзЦенКомплектующих))
|;
|
|ВЫБРАТЬ
| Таблица.КлючСвязи КАК КлючСвязиКомплектующих,
| ВременнаяТаблицаНаборы.КлючСвязи КАК КлючСвязиНабора
|ИЗ
| Товары КАК Таблица
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВременнаяТаблицаНаборы КАК ВременнаяТаблицаНаборы
| ПО ВременнаяТаблицаНаборы.НоменклатураНабора = Таблица.НоменклатураНабора
| И ВременнаяТаблицаНаборы.ХарактеристикаНабора = Таблица.ХарактеристикаНабора
|ГДЕ
| Таблица.НоменклатураНабора <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| И Таблица.ВариантРасчетаЦеныНабора В (ЗНАЧЕНИЕ(Перечисление.ВариантыРасчетаЦенНаборов.ЦенаЗадаетсяЗаНаборРаспределяетсяПоЦенам),
| ЗНАЧЕНИЕ(Перечисление.ВариантыРасчетаЦенНаборов.ЦенаЗадаетсяЗаНаборРаспределяетсяПоДолям))
|ИТОГИ ПО
| ВременнаяТаблицаНаборы.КлючСвязи
|";
Если ИспользоватьНаборы Тогда
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%ИмяВременнойТаблицы%", "ПОМЕСТИТЬ Товары");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%ПоляНабора%", ПоляНабора);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%Поля%", Поля);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%Соединение%", Соединение);
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%ЗапросНаборы%", ЗапросНаборы);
Иначе
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%ИмяВременнойТаблицы%", "");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%ПоляНабора%", "");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%Поля%", "");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%Соединение%", "");
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "%ЗапросНаборы%", "");
КонецЕсли;
Запрос = Новый Запрос(ТекстЗапроса);
Для Каждого КлючЗначение Из ПараметрыЗапроса Цикл
Запрос.УстановитьПараметр(КлючЗначение.Ключ, КлючЗначение.Значение);
КонецЦикла;
ВозвращаемоеЗначение = Новый Структура;
ВозвращаемоеЗначение.Вставить("Товары");
ВозвращаемоеЗначение.Вставить("СоответствиеКлючей");
Если ИспользоватьНаборы Тогда
РезультатЗапроса = Запрос.ВыполнитьПакет();
ВозвращаемоеЗначение.Товары = РезультатЗапроса[РезультатЗапроса.Количество() - 2].Выгрузить();
ВозвращаемоеЗначение.СоответствиеКлючей = РезультатЗапроса[РезультатЗапроса.Количество() - 1].Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);
Иначе
ВозвращаемоеЗначение.Товары = Запрос.Выполнить().Выгрузить();
КонецЕсли;
Возврат ВозвращаемоеЗначение;
КонецФункции
Функция "ДанныеПоТоварамИНаборам" не заменяется, потому что она используется и для других типов документов.
Заполнение реквизитов ТЧ из обработки "Назначение ручной скидки"
При загрузке баллов из сервиса помещаю их в типовой реквизит а менеджер при необходимости может изменять доп. реквизит ТЧ через типовую обработку. Обработка не знает о контексте документа, сделал изменения функций входящих и исходящих данных обработки.
&ИзменениеИКонтроль("НазначитьРучнуюСкидку")
Процедура мб_опт_НазначитьРучнуюСкидку(Объект, ИмяТЧ, СуммаСкидкиКРаспределению, ВходныеПараметры)
ПараметрыСкидки = Новый Структура();
ПараметрыСкидки.Вставить("ИспользуютсяАвтоматическиеСкидки", Ложь);
ПараметрыСкидки.Вставить("ТолькоДляАктивныхСтрок", Ложь);
ПараметрыСкидки.Вставить("РассчитыватьСуммуСНДС", Ложь);
ПараметрыСкидки.Вставить("РассчитыватьСуммуВзаиморасчетов", Ложь);
ПараметрыСкидки.Вставить("ВыделенныеСтроки", Неопределено);
ПараметрыСкидки.Вставить("АдресВоВременномХранилище", Неопределено);
ПараметрыСкидки.Вставить("РеализацияСверхЗаказа", Ложь);
ЗаполнитьЗначенияСвойств(ПараметрыСкидки, ВходныеПараметры);
Если ИмяТЧ = "Услуги" Тогда
ИмяКоличества = "Количество";
Иначе
ИмяКоличества = "КоличествоУпаковок";
КонецЕсли;
Если ПараметрыСкидки.ВыделенныеСтроки <> Неопределено Тогда
СтрокиТабличнойЧасти = Новый Массив();
Для Каждого ТекСтрока Из ПараметрыСкидки.ВыделенныеСтроки Цикл
НайденнаяСтрока = Объект[ИмяТЧ].НайтиПоИдентификатору(ТекСтрока);
Если ?(ПараметрыСкидки.РеализацияСверхЗаказа, НайденнаяСтрока.КодСтроки = 0, Истина) Тогда
СтрокиТабличнойЧасти.Добавить(НайденнаяСтрока);
КонецЕсли;
КонецЦикла;
Иначе
Если ПараметрыСкидки.ТолькоДляАктивныхСтрок Тогда
СтрокиТабличнойЧасти = Объект[ИмяТЧ].НайтиСтроки(Новый Структура("Активность", Истина));
ИначеЕсли ПараметрыСкидки.РеализацияСверхЗаказа Тогда
СтрокиТабличнойЧасти = Объект[ИмяТЧ].НайтиСтроки(Новый Структура("КодСтроки", 0));
Иначе
СтрокиТабличнойЧасти = Объект[ИмяТЧ];
КонецЕсли;
КонецЕсли;
Данные = ПолучитьИзВременногоХранилища(ПараметрыСкидки.АдресВоВременномХранилище);
Данные.Ограничения.Колонки.Добавить("СуммаСкидкиКРаспределению", Новый ОписаниеТипов("Число"));
Режим0Суммы = Ложь;
Если СуммаСкидкиКРаспределению >=0 Тогда
МаксимальнаяСуммаСкидкиНаценки = Данные.Ограничения.Итог("МаксимальнаяСуммаРучнойСкидки");
Иначе
МаксимальнаяСуммаСкидкиНаценки = Данные.Ограничения.Итог("МаксимальнаяСуммаРучнойНаценки");
КонецЕсли;
Если МаксимальнаяСуммаСкидкиНаценки = 0 Тогда
Режим0Суммы = Истина;
КонецЕсли;
Если Режим0Суммы Тогда
МаксимальнаяСуммаСкидкиНаценки = Данные.Ограничения.Итог("СуммаБезСкидки");
КонецЕсли;
Если Не ЗначениеЗаполнено(МаксимальнаяСуммаСкидкиНаценки) Тогда
МаксимальнаяСуммаСкидкиНаценки = 0;
КонецЕсли;
мСуммаСкидкиКРаспределению = СуммаСкидкиКРаспределению;
Для Каждого Ограничение Из Данные.Ограничения Цикл
Если мСуммаСкидкиКРаспределению >=0 Тогда
МаксимальнаяСуммаСкидкиНаценкиОграничения = Ограничение.МаксимальнаяСуммаРучнойСкидки;
Иначе
МаксимальнаяСуммаСкидкиНаценкиОграничения = Ограничение.МаксимальнаяСуммаРучнойНаценки;
КонецЕсли;
Если Режим0Суммы Тогда
МаксимальнаяСуммаСкидкиНаценкиОграничения = Ограничение.СуммаБезСкидки;
КонецЕсли;
Если Не ЗначениеЗаполнено(МаксимальнаяСуммаСкидкиНаценкиОграничения) Тогда
МаксимальнаяСуммаСкидкиНаценкиОграничения = 0;
КонецЕсли;
Если МаксимальнаяСуммаСкидкиНаценки <> 0 Тогда
Ограничение.СуммаСкидкиКРаспределению = мСуммаСкидкиКРаспределению * (МаксимальнаяСуммаСкидкиНаценкиОграничения / МаксимальнаяСуммаСкидкиНаценки);
мСуммаСкидкиКРаспределению = мСуммаСкидкиКРаспределению - Ограничение.СуммаСкидкиКРаспределению;
МаксимальнаяСуммаСкидкиНаценки = МаксимальнаяСуммаСкидкиНаценки - МаксимальнаяСуммаСкидкиНаценкиОграничения;
КонецЕсли;
КонецЦикла;
Для каждого СтрокаТЧ Из СтрокиТабличнойЧасти Цикл
ДанныеНоменклатуры = Данные.Товары.Найти(СтрокаТЧ.Номенклатура, "Номенклатура");
Для Каждого Ограничение Из Данные.Ограничения Цикл
Если НЕ (ДанныеНоменклатуры.ЦеноваяГруппа = Ограничение.ЦеноваяГруппа
ИЛИ (Данные.Ограничения.Найти(ДанныеНоменклатуры.ЦеноваяГруппа, "ЦеноваяГруппа") = Неопределено
И Ограничение.ЦеноваяГруппа = Справочники.ЦеновыеГруппы.ПустаяСсылка())) Тогда
Продолжить;
КонецЕсли;
СуммаБезСкидки = СтрокаТЧ[ИмяКоличества] * СтрокаТЧ.Цена;
СуммаАвтоматическойСкидки = ?(ПараметрыСкидки.ИспользуютсяАвтоматическиеСкидки, СтрокаТЧ.СуммаАвтоматическойСкидки, 0);
Если Ограничение.СуммаБезСкидки <> 0 Тогда
#Удаление
СтрокаТЧ.СуммаРучнойСкидки = (СуммаБезСкидки) * (Ограничение.СуммаСкидкиКРаспределению / Ограничение.СуммаБезСкидки);
#КонецУдаления
#Вставка
СтрокаТЧ.мб_опт_СуммаСкидки = (СуммаБезСкидки) * (Ограничение.СуммаСкидкиКРаспределению / Ограничение.СуммаБезСкидки);
#КонецВставки
Иначе
#Удаление
СтрокаТЧ.СуммаРучнойСкидки = 0;
#КонецУдаления
#Вставка
СтрокаТЧ.мб_опт_СуммаСкидки = 0;
#КонецВставки
КонецЕсли;
#Удаление
Ограничение.СуммаСкидкиКРаспределению = Ограничение.СуммаСкидкиКРаспределению - СтрокаТЧ.СуммаРучнойСкидки;
#КонецУдаления
#Вставка
Ограничение.СуммаСкидкиКРаспределению = Ограничение.СуммаСкидкиКРаспределению - СтрокаТЧ.мб_опт_СуммаСкидки;
#КонецВставки
Ограничение.СуммаБезСкидки = Ограничение.СуммаБезСкидки - СуммаБезСкидки;
Если СуммаБезСкидки <> 0 Тогда
#Удаление
СтрокаТЧ.ПроцентРучнойСкидки = 100 * СтрокаТЧ.СуммаРучнойСкидки / СуммаБезСкидки;
#КонецУдаления
#Вставка
СтрокаТЧ.мб_опт_ПроцентСкидкиНаценки = 100 * СтрокаТЧ.мб_опт_СуммаСкидки / СуммаБезСкидки;
#КонецВставки
Иначе
#Удаление
СтрокаТЧ.ПроцентРучнойСкидки = 0;
#КонецУдаления
#Вставка
СтрокаТЧ.мб_опт_ПроцентСкидкиНаценки = 0;
#КонецВставки
КонецЕсли;
#Удаление
СуммаСкидки = СуммаАвтоматическойСкидки + СтрокаТЧ.СуммаРучнойСкидки;
#КонецУдаления
#Вставка
СуммаСкидки = СуммаАвтоматическойСкидки + СтрокаТЧ.мб_опт_СуммаСкидки;
#КонецВставки
Если ПараметрыСкидки.ИспользуютсяАвтоматическиеСкидки Тогда
Если СуммаБезСкидки <> 0 Тогда
СтрокаТЧ.ПроцентАвтоматическойСкидки = ?(СуммаБезСкидки = 0, 0 , 100 * СуммаАвтоматическойСкидки / СуммаБезСкидки);
Иначе
СтрокаТЧ.ПроцентАвтоматическойСкидки = 0;
КонецЕсли;
КонецЕсли;
СтрокаТЧ.Сумма = СуммаБезСкидки - ?(СуммаСкидки > СуммаБезСкидки, СуммаБезСкидки, СуммаСкидки);
СтрокаТЧ.СуммаНДС = РассчитатьСуммуНДС(СтрокаТЧ.Сумма, СтрокаТЧ.СтавкаНДС, Объект);
Если ПараметрыСкидки.РассчитыватьСуммуСНДС Тогда
СтрокаТЧ.СуммаСНДС = СтрокаТЧ.Сумма + ?(Объект.ЦенаВключаетНДС, 0, СтрокаТЧ.СуммаНДС);
КонецЕсли;
Если ПараметрыСкидки.РассчитыватьСуммуВзаиморасчетов Тогда
СтрокаТЧ.СуммаВзаиморасчетов = 0;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Объект.СуммаДокумента = ЦенообразованиеКлиентСервер.ПолучитьСуммуДокумента(Объект[ИмяТЧ], Объект.ЦенаВключаетНДС);
КонецПроцедуры
&ИзменениеИКонтроль("АдресДанныхДляРасчетаРучныхСкидокВоВременномХранилище")
Функция мб_опт_АдресДанныхДляРасчетаРучныхСкидокВоВременномХранилище(Форма, ИмяТаблицы, УникальныйИдентификатор, ТолькоДляВыделенныхСтрок, ИмяТаблицыВыделенныхСтрок, ТолькоАктивныеСтроки, ИспользоватьОграничения, РеализацияСверхЗаказа)
СоглашениеСКлиентом = Неопределено;
Если ОбщегоНазначенияУТКлиентСервер.ЕстьРеквизитОбъекта(Форма.Объект, "Соглашение") Тогда
СоглашениеСКлиентом = Форма.Объект.Соглашение;
КонецЕсли;
ИспользоватьРучныеСкидки = ПолучитьФункциональнуюОпцию("ИспользоватьРучныеСкидкиВПродажах");
ИспользоватьОграниченияРучныхСкидокВПродажах = ПолучитьФункциональнуюОпцию("ИспользоватьОграниченияРучныхСкидокВПродажахПоПользователям");
Если ЗначениеЗаполнено(СоглашениеСКлиентом) Тогда
ИспользоватьОграниченияПоСоглашениям = ПолучитьФункциональнуюОпцию("ИспользоватьОграниченияРучныхСкидокВПродажахПоСоглашениям");
Иначе
ИспользоватьОграниченияПоСоглашениям = Ложь;
КонецЕсли;
ИспользоватьОграниченияРучныхСкидок = ИспользоватьОграничения И ИспользоватьРучныеСкидки И (ИспользоватьОграниченияРучныхСкидокВПродажах ИЛИ ИспользоватьОграниченияПоСоглашениям);
Если ИмяТаблицы = "Услуги" Тогда
ИмяКоличества = "Количество";
Иначе
ИмяКоличества = "КоличествоУпаковок";
КонецЕсли;
Товары = Новый ТаблицаЗначений;
Товары.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Товары.Колонки.Добавить(ИмяКоличества, Новый ОписаниеТипов("Число",,,Новый КвалификаторыЧисла(15,3)));
Товары.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число",,,Новый КвалификаторыЧисла(15,2)));
Товары.Колонки.Добавить("СуммаАвтоматическойСкидки", Новый ОписаниеТипов("Число"));
Товары.Колонки.Добавить("СуммаРучнойСкидки", Новый ОписаниеТипов("Число"));
#Вставка
Товары.Колонки.Добавить("мб_опт_СуммаСкидки", Новый ОписаниеТипов("Число"));
#КонецВставки
Если ТолькоДляВыделенныхСтрок Тогда
Для Каждого ТекСтрока Из Форма.Элементы[?(ИмяТаблицыВыделенныхСтрок = Неопределено, ИмяТаблицы, ИмяТаблицыВыделенныхСтрок)].ВыделенныеСтроки Цикл
СтрокаКоллекции = Форма.Объект[ИмяТаблицы].НайтиПоИдентификатору(ТекСтрока);
Если ?(РеализацияСверхЗаказа, СтрокаКоллекции = Неопределено ИЛИ СтрокаКоллекции.КодСтроки > 0, СтрокаКоллекции = Неопределено) Тогда
Продолжить;
КонецЕсли;
НоваяСтрока = Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаКоллекции);
КонецЦикла;
Иначе
Если РеализацияСверхЗаказа Тогда
НайденныеСтроки = Форма.Объект[ИмяТаблицы].НайтиСтроки(Новый Структура("КодСтроки", 0));
Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
НоваяСтрока = Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ);
КонецЦикла;
ИначеЕсли ТолькоАктивныеСтроки Тогда
НайденныеСтроки =Форма.Объект[ИмяТаблицы].НайтиСтроки(Новый Структура("Активность", Истина));
Для Каждого СтрокаТЧ Из НайденныеСтроки Цикл
НоваяСтрока = Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ);
КонецЦикла;
Иначе
Для Каждого СтрокаТЧ Из Форма.Объект[ИмяТаблицы] Цикл
НоваяСтрока = Товары.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЧ);
КонецЦикла;
КонецЕсли;
КонецЕсли;
Если ИспользоватьОграниченияРучныхСкидок Тогда
ОграниченияРучныхСкидок = НастройкиПродажДляПользователейСервер.ОграниченияСкидокНаценок(СоглашениеСКлиентом, Пользователи.ТекущийПользователь());
ЦеновыеГруппы = ОграниченияРучныхСкидок.ВыгрузитьКолонку("ЦеноваяГруппа");
Иначе
ОграниченияРучныхСкидок = Новый ТаблицаЗначений;
ОграниченияРучныхСкидок.Колонки.Добавить("ЦеноваяГруппа", Новый ОписаниеТипов("СправочникСсылка.ЦеновыеГруппы"));
ОграниченияРучныхСкидок.Колонки.Добавить("МаксимальныйПроцентРучнойСкидки", Новый ОписаниеТипов("Число",,,Новый КвалификаторыЧисла(15,2)));
ОграниченияРучныхСкидок.Колонки.Добавить("МаксимальныйПроцентРучнойНаценки", Новый ОписаниеТипов("Число",,,Новый КвалификаторыЧисла(15,2)));
Ограничение = ОграниченияРучныхСкидок.Добавить();
Ограничение.ЦеноваяГруппа = Справочники.ЦеновыеГруппы.ПустаяСсылка();
Ограничение.МаксимальныйПроцентРучнойСкидки = 999.99;
Ограничение.МаксимальныйПроцентРучнойНаценки = 999.99;
КонецЕсли;
ТекстЗапроса =
"ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| Товары." + ИмяКоличества + " " + "КАК КоличествоУпаковок,
| Товары.Цена КАК ЦенаЗаУпаковку,
| Товары.СуммаАвтоматическойСкидки КАК СуммаАвтоматическойСкидки,
#Вставка
| Товары.мб_опт_СуммаСкидки КАК мб_опт_СуммаСкидки,
#КонецВставки
| Товары.СуммаРучнойСкидки КАК СуммаРучнойСкидки
|ПОМЕСТИТЬ ВременнаяТаблица
|ИЗ
| &Товары КАК Товары
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Товары.Номенклатура КАК Номенклатура,
| СправочникНоменклатура.ЦеноваяГруппа КАК ЦеноваяГруппа,
| Товары.КоличествоУпаковок КАК КоличествоУпаковок,
| Товары.ЦенаЗаУпаковку КАК ЦенаЗаУпаковку,
| Товары.СуммаАвтоматическойСкидки КАК СуммаАвтоматическойСкидки,
#Вставка
| Товары.мб_опт_СуммаСкидки КАК мб_опт_СуммаСкидки,
#КонецВставки
| Товары.СуммаРучнойСкидки КАК СуммаРучнойСкидки
|ПОМЕСТИТЬ ВременнаяТаблицаТовары
|ИЗ
| ВременнаяТаблица КАК Товары
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК СправочникНоменклатура
| ПО (СправочникНоменклатура.Ссылка = Товары.Номенклатура)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ОграниченияРучныхСкидок.ЦеноваяГруппа КАК ЦеноваяГруппа,
| ОграниченияРучныхСкидок.МаксимальныйПроцентРучнойСкидки КАК МаксимальныйПроцентРучнойСкидки,
| ОграниченияРучныхСкидок.МаксимальныйПроцентРучнойНаценки КАК МаксимальныйПроцентРучнойНаценки
|ПОМЕСТИТЬ ОграниченияРучныхСкидок
|ИЗ
| &ОграниченияРучныхСкидок КАК ОграниченияРучныхСкидок
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Т.ЦеноваяГруппа КАК ЦеноваяГруппа,
| Т.СуммаБезСкидки КАК СуммаБезСкидки,
| Т.СуммаАвтоматическойСкидки КАК СуммаАвтоматическойСкидки,
#Вставка
| Т.мб_опт_СуммаСкидки КАК мб_опт_СуммаСкидки,
#КонецВставки
| Т.СуммаРучнойСкидки КАК СуммаРучнойСкидки,
| ОграниченияРучныхСкидок.МаксимальныйПроцентРучнойСкидки КАК МаксимальныйПроцентРучнойСкидки,
| ОграниченияРучныхСкидок.МаксимальныйПроцентРучнойНаценки КАК МаксимальныйПроцентРучнойНаценки,
| ВЫРАЗИТЬ(ОграниченияРучныхСкидок.МаксимальныйПроцентРучнойСкидки / 100 * Т.СуммаБезСкидки КАК ЧИСЛО(31,2)) КАК МаксимальнаяСуммаРучнойСкидки,
| ВЫРАЗИТЬ(ОграниченияРучныхСкидок.МаксимальныйПроцентРучнойНаценки / 100 * Т.СуммаБезСкидки КАК ЧИСЛО(31,2)) КАК МаксимальнаяСуммаРучнойНаценки
|ИЗ
| (ВЫБРАТЬ
| ВЫБОР
| КОГДА ВременнаяТаблицаТовары.ЦеноваяГруппа В (&ЦеновыеГруппы)
| ТОГДА ВременнаяТаблицаТовары.ЦеноваяГруппа
| ИНАЧЕ ЗНАЧЕНИЕ(Справочник.ЦеновыеГруппы.ПустаяСсылка)
| КОНЕЦ КАК ЦеноваяГруппа,
| СУММА(ВЫРАЗИТЬ(ВременнаяТаблицаТовары.КоличествоУпаковок * ВременнаяТаблицаТовары.ЦенаЗаУпаковку КАК ЧИСЛО(31,2))) КАК СуммаБезСкидки,
| СУММА(ВременнаяТаблицаТовары.СуммаАвтоматическойСкидки) КАК СуммаАвтоматическойСкидки,
#Вставка
| СУММА(ВременнаяТаблицаТовары.мб_опт_СуммаСкидки) КАК мб_опт_СуммаСкидки,
#КонецВставки
| СУММА(ВременнаяТаблицаТовары.СуммаРучнойСкидки) КАК СуммаРучнойСкидки
| ИЗ
| ВременнаяТаблицаТовары КАК ВременнаяТаблицаТовары
|
| СГРУППИРОВАТЬ ПО
| ВЫБОР
| КОГДА ВременнаяТаблицаТовары.ЦеноваяГруппа В (&ЦеновыеГруппы)
| ТОГДА ВременнаяТаблицаТовары.ЦеноваяГруппа
| ИНАЧЕ ЗНАЧЕНИЕ(Справочник.ЦеновыеГруппы.ПустаяСсылка)
| КОНЕЦ) КАК Т
| ЛЕВОЕ СОЕДИНЕНИЕ ОграниченияРучныхСкидок КАК ОграниченияРучныхСкидок
| ПО (ОграниченияРучныхСкидок.ЦеноваяГруппа = Т.ЦеноваяГруппа)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ РАЗЛИЧНЫЕ
| ВременнаяТаблицаТовары.Номенклатура КАК Номенклатура,
| ВременнаяТаблицаТовары.ЦеноваяГруппа КАК ЦеноваяГруппа
|ИЗ
| ВременнаяТаблицаТовары КАК ВременнаяТаблицаТовары";
Запрос = Новый Запрос(ТекстЗапроса);
Запрос.Параметры.Вставить("Товары", Товары);
Запрос.Параметры.Вставить("ОграниченияРучныхСкидок", ОграниченияРучныхСкидок);
Запрос.Параметры.Вставить("ЦеновыеГруппы", ЦеновыеГруппы);
Результат = Запрос.ВыполнитьПакет();
Ограничения = Результат[3].Выгрузить();
Ограничения.Индексы.Добавить("ЦеноваяГруппа");
Товары = Результат[4].Выгрузить();
Товары.Индексы.Добавить("Номенклатура");
#Вставка
Попытка
Если ТипЗнч(Форма.Объект.Ссылка) = Тип("ДокументСсылка.ЗаказКлиента") Тогда
Для каждого СтрО Из Ограничения Цикл
СтрО.СуммаРучнойСкидки = СтрО.мб_опт_СуммаСкидки;
КонецЦикла;
КонецЕсли;
Исключение
//ОписаниеОшибки()
КонецПопытки;
#КонецВставки
Возврат ПоместитьВоВременноеХранилище(Новый Структура("Ограничения, Товары, ИспользоватьОграниченияРучныхСкидок", Ограничения, Товары, ИспользоватьОграниченияРучныхСкидок), УникальныйИдентификатор);
КонецФункции
"Попытка" применена потому что функция вызывается в том числе при редактировании номенклатуры назначения в форме элемента скидки.
Итог
Получилась специализированная доработка идею которой можно переиспользовать для схожих задач.
Буду раз конструктивной критике и предложениям по оптимизации или универсализации.
Пока делал тестовый пример, нашел проблему, что в группе скидок с вариантом "Умножение" порядок вложенной группы ниже, чем элемента округления.
Благодарю за внимание.