При программной работе с документами в 1С часто возникает задача не просто создать и заполнить документ, но и корректно применить все связанные с ним механизмы, такие как автоматические скидки и наценки. Особенно актуально это для конфигурации «Управление торговлей 11», где подсистема маркетинга и ценообразования является довольно сложной.
Проанализируем ситуацию: мы программно создаем документ ЧекККМ, заполняем его табличную часть «Товары». Если просто попытаться записать значение в колонку СуммаАвтоматическойСкидки, это не даст нужного результата. Система не пересчитает итоги, и скидка не будет корректно отражена, так как для этого должен быть запущен специальный механизм расчета. Давайте разберем, как правильно инициировать этот расчет и применить действующие скидки.
Это самый простой, надежный и рекомендуемый способ. Разработчики конфигурации предусмотрели специальный метод, который инкапсулирует (скрывает) в себе всю сложную логику вызова подсистемы скидок. Вам не нужно вникать во внутреннее устройство механизма, достаточно просто вызвать один метод для уже заполненного документа.
Разберем по шагам, как это работает:
ЧекККМ с помощью метода Документы.ЧекККМ.СоздатьДокумент().Организация, КассаККМ, Партнер и другие.Товары. Для каждой строки указываем Номенклатура, Характеристика (если используется), Количество и Цена. Важный момент: на этом этапе не нужно пытаться самостоятельно рассчитывать сумму или скидку. Просто заполняем основные данные.ЧекККМОбъект.ЗаполнитьСкидкиНаценки().Этот вызов запустит весь механизм: система проанализирует состав документа, дату, партнера, номенклатуру и применит все действующие на данный момент автоматические скидки. Поля, связанные со скидками (ПроцентАвтоматическойСкидки, СуммаАвтоматическойСкидки), а также итоговая Сумма в строках будут рассчитаны и заполнены автоматически.
Посмотрим на пример кода:
&НаСервере
Процедура СоздатьЧекСоСкидкой()
// 1. Создаем объект документа
ЧекККМОбъект = Документы.ЧекККМ.СоздатьДокумент();
// 2. Заполняем реквизиты шапки
ЧекККМОбъект.Дата = ТекущаяДата();
ЧекККМОбъект.Организация = Константы.ОсновнаяОрганизация.Получить();
ЧекККМОбъект.КассаККМ = Справочники.КассыККМ.НайтиПоНаименованию("Основная касса");
ЧекККМОбъект.Статус = Перечисления.СтатусыЧековККМ.Пробит;
// 3. Добавляем товары в табличную часть
НоваяСтрока = ЧекККМОбъект.Товары.Добавить();
НоваяСтрока.Номенклатура = Справочники.Номенклатура.НайтиПоНаименованию("Товар для скидки");
НоваяСтрока.Количество = 2;
НоваяСтрока.Цена = 1500;
НоваяСтрока.СтавкаНДС = Перечисления.СтавкиНДС.НДС20;
// Сумма рассчитается автоматически при изменении количества или цены
// РассчитатьСуммуНДСВТабличнойЧасти(НоваяСтрока, ЧекККМОбъект); // Вспомогательная процедура
// ... можно добавить другие товары ...
// 4. Вызываем расчет скидок
// Это ключевой шаг!
ЧекККМОбъект.ЗаполнитьСкидкиНаценки();
// После этого вызова строки в ЧекККМОбъект.Товары
// будут содержать рассчитанные суммы скидок.
// 5. Записываем и проводим документ
Попытка
ЧекККМОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Этот подход является предпочтительным, так как он использует встроенный API конфигурации. Это делает ваш код более устойчивым к будущим обновлениям 1С, ведь если разработчики изменят логику расчета скидок, они, скорее всего, обновят и метод ЗаполнитьСкидкиНаценки(), и ваш код продолжит работать корректно.
Этот способ является более "низкоуровневым" и сложным. Он может понадобиться в специфических случаях, например, когда нужно рассчитать скидку для одной конкретной строки, не затрагивая весь документ, или когда требуется получить данные о скидках до фактического создания объекта документа.
В этом случае нам придется напрямую обращаться к процедурам и функциям общих модулей, отвечающих за маркетинг. Ключевую роль здесь играют модули МенеджерСкидокНаценок и МаркетингСервер.
Основная логика заключается в следующем:
МаркетингСервер.ПолучитьУсловияПредоставленияСкидокНаценок(). Эта функция вернет структуру с действующими скидками и условиями их применения.МенеджерСкидокНаценок.РассчитатьСкидкиНаценкиДокумента(). Эта процедура выполнит сам расчет и изменит данные в переданном ей объекте документа.Посмотрим на примерный код, который иллюстрирует этот подход:
&НаСервере
Процедура СоздатьЧекНизкоуровнево()
// Предполагаем, что ЧекККМОбъект уже создан
// и его табличная часть "Товары" заполнена
ЧекККМОбъект = Документы.ЧекККМ.СоздатьДокумент();
// ... заполнение шапки и товаров, как в первом примере ...
// Для нового, еще не записанного документа, ссылка будет пустой.
// Механизм скидок может работать с уникальным идентификатором
// или временной ссылкой.
МассивОбъектовНазначения = Новый Массив;
МассивОбъектовНазначения.Добавить(ЧекККМОбъект);
// 1. Получаем условия предоставления скидок
УсловияПредоставления = МаркетингСервер.ПолучитьУсловияПредоставленияСкидокНаценок(
МассивОбъектовНазначения,
ЧекККМОбъект.Дата,
ЧекККМОбъект,
ЧекККМОбъект.Товары);
// 2. Вызываем процедуру расчета скидок
МенеджерСкидокНаценок.РассчитатьСкидкиНаценкиДокумента(
ЧекККМОбъект,
УсловияПредоставления);
// После выполнения этой процедуры данные в объекте ЧекККМОбъект
// будут изменены - скидки будут рассчитаны и применены.
// Далее можно записывать документ
ЧекККМОбъект.Записать(РежимЗаписиДокумента.Проведение);
КонецПроцедуры
Важно понимать: этот метод требует более глубокого знания архитектуры подсистемы маркетинга в УТ 11. Нужно правильно подготовить все параметры, понимать, какие данные ожидают процедуры на входе. Этот способ дает больше гибкости, но сопряжен с риском, что при обновлении конфигурации внутренние процедуры могут измениться, и ваш код перестанет работать. Используйте его только тогда, когда стандартный метод ЗаполнитьСкидкиНаценки() не решает вашу задачу.
Мы рассмотрели два основных способа программного применения скидок в документе «Чек ККМ».
Таким образом, для решения стандартной задачи программного создания чека с автоматическим расчетом скидок всегда начинайте с первого, более простого и безопасного метода.