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