В оптовой и розничной торговле нередко возникает ситуация, когда компания работает с десятками или сотнями поставщиков, причем каждый из них диктует собственные правила: один требует продавать товар строго по рекомендованным розничным ценам (РРЦ) с наценкой от закупки, второй контролирует минимальную розничную цену (МРЦ), третий дает базовую розничную цену и фиксированную входящую скидку. При этом на выходе компании требуется поддерживать компактную и прозрачную сетку из четырех собственных цен: Закупка, Крупный опт, Мелкий опт и Розница, которые синхронизируются с интернет-магазином.
Разберем, почему стандартные средства конфигурации «1С:Управление торговлей 10.3» не подходят под эту задачу в лоб и как выстроить масштабируемую архитектуру ценообразования без перегрузки справочников и регистров.
Проанализируем типовую модель расчета цен. В справочнике ТипыЦенНоменклатуры предусмотрен способ расчета по наценке на базовый тип цены. Однако это правило является строго глобальным: процент наценки и базовый тип фиксируются для всего типа цены в целом. Если настроить «Розница = Закупка + 40%», это правило будет применяться ко всей номенклатуре базы. Типовой механизм не позволяет задать внутри одного типа цены расчет: для Поставщика №1 — «Закупка + 40%», а для Поставщика №2 — «Закупка + 30%».
Попытка создать отдельные типы цен под каждого контрагента (например, «Розница Поставщик 1», «Розница Поставщик 2») приводит к катастрофическим последствиям:
ЦеныНоменклатуры имеет периодичность «День». При объемах каталога свыше 100 000 позиций расчет среза последних по сотням типов цен вызовет критическое замедление запросов.Выясним правильную архитектуру движения цен. В системе должны быть четко разделены две сущности:
УстановкаЦенНоменклатурыКонтрагентов и хранятся в периодическом регистре сведений ЦеныНоменклатурыКонтрагентов. Сюда загружаются «сырые» данные из входящих файлов (закупочные прайсы, РРЦ, МРЦ).УстановкаЦенНоменклатуры и хранятся в регистре сведений ЦеныНоменклатуры. В этом регистре остаются ровно 4 предопределенных типа цен.Так как каждый товар поставляется только одним контрагентом, в карточке номенклатуры обязательно заполняется реквизит ОсновнойПоставщик. Это позволяет алгоритмам однозначно определять, чья тарифная сетка должна применяться к позиции.
Рассмотрим варианты, где и как хранить формулы и проценты наценок для каждого контрагента.
Вариант 1. Отдельный непериодический регистр сведений (рекомендуемый)
Создадим новый регистр сведений ПравилаЦенообразованияПоставщиков со следующей структурой:
Поставщик (справочник Контрагенты), ЦеноваяГруппа (справочник ЦеновыеГруппы, необязательно — для детальной грануляции внутри прайса поставщика).СпособРасчетаРозницы (перечисление: ОтЗакупки, ОтРРЦ, Фиксированный);НаценкаРозница (число 5.2);СпособРасчетаМелкийОпт (перечисление: ОтЗакупки, ОтРозницы, ОтКрупногоОпта);НаценкаМелкийОпт (число 5.2);СпособРасчетаКрупныйОпт (перечисление: ОтЗакупки, ОтРозницы, ПоМРЦ);НаценкаКрупныйОпт (число 5.2);КонтролироватьМРЦ (булево).Вариант 2. Использование типового механизма свойств (без доработки конфигурации)
Если конфигурацию запрещено снимать с поддержки, используем план видов характеристик СвойстваОбъектов. Для справочника Контрагенты создаются дополнительные свойства: «СкидкаРозница», «СкидкаМелкийОпт», «СкидкаКрупныйОпт», «ТипБазовойЦены». Внешняя обработка загрузки прайсов считывает эти значения через регистр сведений ЗначенияСвойствОбъектов.
Посмотрим на пример логики пересчета, которую должна выполнять внешняя обработка загрузки прайсов или регламентное задание. Рассмотрим расчет цен для конкретного товара:
// Определяем входящие параметры товара
БазоваяЗакупка = СтрокаПрайса.Закупка;
ВходящаяРРЦ = СтрокаПрайса.РРЦ;
ВходящаяМРЦ = СтрокаПрайса.МРЦ;
// 1. Расчет Розничной цены
Если Правило.СпособРасчетаРозницы = Перечисления.СпособыРасчета.ОтРРЦ Тогда
ЦенаРозница = ВходящаяРРЦ;
ИначеЕсли Правило.СпособРасчетаРозницы = Перечисления.СпособыРасчета.ОтЗакупки Тогда
ЦенаРозница = БазоваяЗакупка * (1 + Правило.НаценкаРозница / 100);
КонецЕсли;
// 2. Расчет Крупного опта с контролем МРЦ
Если Правило.СпособРасчетаКрупныйОпт = Перечисления.СпособыРасчета.ПоМРЦ Тогда
ЦенаКрупныйОпт = ВходящаяМРЦ;
ИначеЕсли Правило.СпособРасчетаКрупныйОпт = Перечисления.СпособыРасчета.ОтРозницы Тогда
ЦенаКрупныйОпт = ЦенаРозница * (1 - Правило.НаценкаКрупныйОпт / 100);
ИначеЕсли Правило.СпособРасчетаКрупныйОпт = Перечисления.СпособыРасчета.ОтЗакупки Тогда
ЦенаКрупныйОпт = БазоваяЗакупка * (1 + Правило.НаценкаКрупныйОпт / 100);
КонецЕсли;
// Проверяем соблюдение условия минимальной разрешенной цены
Если Правило.КонтролироватьМРЦ И ВходящаяМРЦ > 0 Тогда
Если ЦенаКрупныйОпт < ВходящаяМРЦ Тогда
ЦенаКрупныйОпт = ВходящаяМРЦ;
КонецЕсли;
КонецЕсли;
// 3. Расчет Мелкого опта
Если Правило.СпособРасчетаМелкийОпт = Перечисления.СпособыРасчета.ОтРозницы Тогда
ЦенаМелкийОпт = ЦенаРозница * (1 - Правило.НаценкаМелкийОпт / 100);
ИначеЕсли Правило.СпособРасчетаМелкийОпт = Перечисления.СпособыРасчета.ОтКрупногоОпта Тогда
ЦенаМелкийОпт = ЦенаКрупныйОпт * (1 + Правило.НаценкаМелкийОпт / 100);
КонецЕсли;
Обработка прайсов такого объема требует внимания к производительности системы. Разберем ключевые технические правила реализации:
УстановкаЦенНоменклатуры на 150 000 строк вызовет блокировку транзакций и переполнение памяти. Необходимо программно разбивать переоценку на пакеты по 2 000 – 5 000 строк либо создавать отдельный документ под каждого поставщика.COMОбъект("Excel.Application") на больших файлах приводит к утечкам памяти и зависаниям процесса. Для чтения файлов формата .xlsx следует использовать загрузку в табличный документ через ТабличныйДокумент.Прочитать() или парсинг XML-структуры архива книги.Такой подход позволяет сохранить информационную базу компактной, полностью исключить ручные ошибки менеджеров при пересчете формул в сторонних редакторах и гарантировать 100% актуальность выгружаемых на сайт данных.