Как реализовать акционные цены с периодом действия в 1С:УПП 1.3?

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

В типовой конфигурации 1С:Управление производственным предприятием (УПП) редакции 1.3 ценообразование построено на базе периодического регистра сведений ЦеныНоменклатуры. Этот регистр не имеет реквизита или измерения для указания даты окончания действия цены. Логика системы опирается на принцип «среза последних»: цена, установленная документом УстановкаЦенНоменклатуры, действует неограниченно долго, пока не будет введена новая цена.

Если в компании часто проводятся маркетинговые акции, пользователям приходится вручную создавать два документа установки цен: первый — для ввода акционной цены на дату начала распродажи, второй — для возврата к базовым ценам после окончания акции. Это приводит к колоссальным трудозатратам и высокой вероятности ошибок. Разберем, как автоматизировать этот процесс, сохранив жесткую привязку к определенному Типу цен и не повредив при этом структуру метаданных старой legacy-системы.

Почему не подходит документ «Установка скидок номенклатуры»?

Типовой документ УстановкаСкидокНоменклатуры поддерживает указание периода действия скидки («Скидка с... по...»). Однако у этого механизма есть существенные ограничения:

  1. Скидка рассчитывается как процент или фиксированная сумма вычитания из базовой цены. В УПП 1.3 нельзя напрямую переопределить конкретный Тип цен на ограниченный период времени через механизм скидок.
  2. Для розничных продаж или при сложных схемах дистрибуции критически важно использовать именно жестко заданный тип цен в документе продажи, а не рассчитывать скидки «на лету» в табличной части.

Ниже мы подробно рассмотрим три варианта решения этой задачи, начиная от самого безопасного для обновления и заканчивая наиболее изящным программным решением.

---

Вариант 1. Разработка кастомного документа «Установка временных цен» (Рекомендуемый)

Этот метод основан на идее автоматического создания пары стандартных документов УстановкаЦенНоменклатуры (открывающего и закрывающего акцию). Мы не меняем логику проведения документов и структуру регистров, что гарантирует полную безопасность для последующих обновлений (если они планируются) и стабильность базы данных.

Рассмотрим алгоритм реализации:

  1. Создаем новый документ в конфигурации, назовем его ВременнаяУстановкаЦен.
  2. В шапке документа добавляем реквизиты: ДатаНачала (Дата), ДатаОкончания (Дата), ТипЦен (СправочникСсылка.ТипыЦенНоменклатуры).
  3. В табличной части «Товары» добавляем реквизиты: Номенклатура, АкционнаяЦена, БазоваяЦена (цена, которая вернется по окончании акции), Валюта, ЕдиницаИзмерения.
  4. При проведении этого документа система должна программно генерировать и проводить два стандартных документа УстановкаЦенНоменклатуры.

Проанализируем программный код, который можно разместить в обработчике проведения нового документа:


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	
	// 1. Создаем и заполняем документ на начало акции
	ДокНачало = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();
	ДокНачало.Дата = ЭтотОбъект.ДатаНачала;
	ДокНачало.Комментарий = "Акция (Начало). Сформирован автоматически документом " + ЭтотОбъект.Ссылка;
	
	Для Каждого СтрокаТЧ Из ЭтотОбъект.Товары Цикл
		НоваяСтрока = ДокНачало.Товары.Добавить();
		НоваяСтрока.Номенклатура = СтрокаТЧ.Номенклатура;
		НоваяСтрока.ТипЦен = ЭтотОбъект.ТипЦен;
		НоваяСтрока.Цена = СтрокаТЧ.АкционнаяЦена;
		НоваяСтрока.Валюта = СтрокаТЧ.Валюта;
		НоваяСтрока.ЕдиницаИзмерения = СтрокаТЧ.ЕдиницаИзмерения;
		НоваяСтрока.СпособРасчетаЦены = Перечисления.СпособыРасчетаЦен.ПоВладельцуТипаЦен;
	КонецЦикла;
	
	Попытка
		ДокНачало.Записать(РежимЗаписиДокумента.Проведение);
	Исключение
		ЗаписьЖурналаРегистрации("Акция", УровеньЖурналаРегистрации.Ошибка, , , 
			"Ошибка создания стартового документа цен: " + ОписаниеОшибки());
		Отказ = Истина;
		Возврат;
	КонецПопытки;
	
	// 2. Создаем и заполняем документ на окончание акции (возврат базовых цен)
	ДокКонец = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();
	ДокКонец.Дата = ЭтотОбъект.ДатаОкончания + 1; // Устанавливаем цену со следующего дня после окончания акции
	ДокКонец.Комментарий = "Акция (Завершение). Сформирован автоматически документом " + ЭтотОбъект.Ссылка;
	
	Для Каждого СтрокаТЧ Из ЭтотОбъект.Товары Цикл
		НоваяСтрока = ДокКонец.Товары.Добавить();
		НоваяСтрока.Номенклатура = СтрокаТЧ.Номенклатура;
		НоваяСтрока.ТипЦен = ЭтотОбъект.ТипЦен;
		НоваяСтрока.Цена = СтрокаТЧ.БазоваяЦена;
		НоваяСтрока.Валюта = СтрокаТЧ.Валюта;
		НоваяСтрока.ЕдиницаИзмерения = СтрокаТЧ.ЕдиницаИзмерения;
		НоваяСтрока.СпособРасчетаЦены = Перечисления.СпособыРасчетаЦен.ПоВладельцуТипаЦен;
	КонецЦикла;
	
	Попытка
		ДокКонец.Записать(РежимЗаписиДокумента.Проведение);
	Исключение
		ЗаписьЖурналаРегистрации("Акция", УровеньЖурналаРегистрации.Ошибка, , , 
			"Ошибка создания финишного документа цен: " + ОписаниеОшибки());
		Отказ = Истина;
	КонецПопытки;

КонецПроцедуры

Важный нюанс: Чтобы пользователи не запутались, в модуле кастомного документа при отмене проведения необходимо обязательно предусмотреть программную отмену проведения или удаление созданных ранее документов УстановкаЦенНоменклатуры.

---

Вариант 2. Использование регламентного задания для динамического возврата цен

В первом варианте есть один недостаток: если во время акции регулярная базовая цена на товар изменится в системе (например, поставщик поднял цены на закупку, и менеджер пересчитал розницу), то закрывающий документ акции по ее окончании жестко перезапишет цену на ту, которая была актуальна на момент запуска акции. Мы вернемся к устаревшей базовой цене.

Чтобы избежать этой проблемы, применим подход с отложенной генерацией документов:

  1. Кастомный документ при проведении регистрирует параметры акции (номенклатуру, цены и даты действия) в новом независимом регистре сведений АкцииНоменклатуры (структура: Номенклатура, ТипЦен — измерения; Цена, ДатаНачала, ДатаОкончания, Обработано — реквизиты).
  2. Документ при проведении создает только один стартовый документ установки цен.
  3. Разрабатывается регламентное задание, которое запускается ежедневно в полночь. Оно находит все записи акций, дата окончания которых равна вчерашнему дню, и анализирует актуальные цены до начала акции или другие базовые цены. На основании этой аналитики регламентное задание формирует один общий закрывающий документ установки цен по актуальным на текущий момент прайсам.

---

Вариант 3. Использование нового регистра сведений и доработка общего модуля (Без лишних документов)

Если плодить сотни документов УстановкаЦенНоменклатуры не хочется, можно использовать более изящный способ, который часто применяется в современных конфигурациях ERP-класса. Для этого нам потребуется создать свой регистр временных цен и перенаправить туда стандартные запросы системы.

Рассмотрим этот вариант по шагам:

Шаг 1. Создание регистра сведений
Создаем новый независимый регистр сведений ВременныеЦеныНоменклатуры со следующей структурой:

Шаг 2. Корректировка получения цен в общем модуле
В конфигурации УПП 1.3 за получение цен номенклатуры отвечает общий модуль Ценообразование (функция ПолучитьЦеныНоменклатуры или аналогичные функции получения цен для документов продаж). Нам нужно точечно модифицировать этот функционал.

Проанализируем пример функции перехвата:


Функция ПолучитьАкционнуюЦену(АктуальнаяНоменклатура, АктуальныйТипЦен, ДатаСделки) Экспорт
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
		"ВЫБРАТЬ
		|	ВременныеЦены.Цена КАК Цена
		|ИЗ
		|	РегистрСведений.ВременныеЦеныНоменклатуры КАК ВременныеЦены
		|ГДЕ
		|	ВременныеЦены.Номенклатура = &Номенклатура
		|	И ВременныеЦены.ТипЦен = &ТипЦен
		|	И &ДатаСделки МЕЖДУ ВременныеЦены.ДатаНачала И ВременныеЦены.ДатаОкончания";
		
	Запрос.УстановитьПараметр("Номенклатура", АктуальнаяНоменклатура);
	Запрос.УстановитьПараметр("ТипЦен", АктуальныйТипЦен);
	Запрос.УстановитьПараметр("ДатаСделки", ДатаСделки);
	
	РезультатЗапроса = Запрос.Выполнить();
	Если Не РезультатЗапроса.Пустой() Тогда
		Выборка = РезультатЗапроса.Выбрать();
		Выборка.Следующий();
		Возврат Выборка.Цена;
	КонецЕсли;
	
	Возврат Неопределено;
	
КонецФункции

Затем в типовой функции получения цены (например, в обработке заполнения табличных частей документов продаж или при расчете цен в заказах) мы делаем вставку:


// ВСТАВКА ДОРАБОТКИ
АкционнаяЦена = Ценообразование.ПолучитьАкционнуюЦену(СтрокаТовара.Номенклатура, ТекТипЦен, ДатаДокумента);
Если АкционнаяЦена <> Неопределено Тогда
    СтрокаТовара.Цена = АкционнаяЦена;
Иначе
    // Тут отрабатывает стандартный типовой запрос к регистру ЦеныНоменклатуры
КонецЕсли;

Плюс метода: Абсолютная чистота в базе данных. Не плодятся лишние документы установки цен «туда-обратно», не засоряется стандартный регистр. Цены действуют строго в указанный интервал времени.

---

Резюме и рекомендации

Выбор конкретного метода зависит от того, насколько глубоко вы готовы дорабатывать конфигурацию УПП 1.3:

← На главную