← Назад к вопросам
Настройка ценообразования по типам цен
2.0 Middle🔥 221 комментариев
#Конфигурации и типовые
Условие
Реализуйте систему ценообразования с разными типами цен.
Требования:
- Справочник "ТипыЦен" (Закупочная, Оптовая, Розничная и т.д.)
- Регистр сведений "ЦеныНоменклатуры" (Номенклатура, ТипЦен → Цена)
- Документ установки цен (массовое изменение цен)
- Возможность установки цен на основании документа поступления
- Отчёт "Прайс-лист" по выбранному типу цен
Дополнительно
При выборе типа цены в документе продажи автоматически подставлять соответствующую цену в табличную часть.
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение
Система ценообразования с типами цен
Рассмотрим реализацию многоуровневой системы управления ценами с автоматической подстановкой в документы.
Справочник "ТипыЦен"
Справочник ТипыЦен
Номер: строка (уникальный)
Наименование: строка
Описание: строка
ПриоритетОтбора: число (для определения цены по умолчанию)
ПометкаУдаления: булево
КонецСправочника
Стандартные типы цен:
- 01 - Закупочная
- 02 - Оптовая
- 03 - Розничная
- 04 - СПО (Специальная оптовая)
- 05 - Контрактная
Регистр сведений "ЦеныНоменклатуры"
РегистрСведений ЦеныНоменклатуры
Период: дата // для истории изменения цен
// Измерения
Измерение: Номенклатура (ссылка на Номенклатуру)
Измерение: ТипЦены (ссылка на ТипыЦен)
Измерение: ЕдиницаИзмерения (ссылка на ЕдиницыИзмерения)
// Ресурсы
Ресурс: Цена (число) // в валюте организации
Ресурс: НижнийПредел (число) // мин. скидка при кол-ве
Ресурс: ДатаНачала (дата) // начало действия цены
Ресурс: ДатаОконча (дата) // конец действия цены
КонецРегистраСведений
Документ "УстановкаЦен"
Для массового изменения цен:
Документ УстановкаЦен
Реквизит: Номер (строка)
Реквизит: Дата (дата)
Реквизит: ТипЦены (ссылка на ТипыЦен)
Реквизит: ДатаНачала (дата)
Реквизит: ДатаОконча (дата)
Табличная часть: ЦеныТовары
Колонка: Номенклатура (ссылка на Номенклатуру)
Колонка: ЕдиницаИзмерения (ссылка на ЕдиницыИзмерения)
Колонка: ОтклонениеПроцент (число) // % изменения от текущей
Колонка: НоваяЦена (число)
Колонка: НижнийПредел (число) // кол-во для скидки
Колонка: СкидкаПроцент (число)
КонецДокумента
Реализация документа УстановкаЦен
// Процедура проведения документа
Процедура ПроведениеДокумента(Отмена, РежимПроведения)
Попытка
// Очищаем регистр
Движения.ЦеныНоменклатуры.Очистить();
Для Каждого ЦенаСтрока Из ЭтотОбъект.ЦеныТовары Цикл
// Валидация
Если НЕ ЗначениеЗаполнено(ЦенаСтрока.Номенклатура) Тогда
ВызватьОшибку("Не указана номенклатура");
КонецЕсли;
Если ЦенаСтрока.НоваяЦена <= 0 Тогда
ВызватьОшибку("Цена должна быть больше нуля");
КонецЕсли;
// Создаём запись в регистре
Движение = Движения.ЦеныНоменклатуры.Добавить();
Движение.Период = ЭтотОбъект.Дата;
Движение.Номенклатура = ЦенаСтрока.Номенклатура;
Движение.ТипЦены = ЭтотОбъект.ТипЦены;
Движение.ЕдиницаИзмерения = ЦенаСтрока.ЕдиницаИзмерения;
Движение.Цена = ЦенаСтрока.НоваяЦена;
Движение.НижнийПредел = ЦенаСтрока.НижнийПредел;
Движение.ДатаНачала = ЭтотОбъект.ДатаНачала;
Движение.ДатаОконча = ЭтотОбъект.ДатаОконча;
КонецЦикла;
ЗаписатьВЖурнал("Установка цен", "Установлены цены по типу: " + ЭтотОбъект.ТипЦены.Наименование);
Исключение
ВызватьОшибку("Ошибка при проведении: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
// Процедура заполнения цен на основании поступления
Процедура ЗаполнитьНаОснованииПоступления(Команда)
Диалог = Новый ДиалогВыбораИБ();
Диалог.ПолеВыбора = "Documents.ПриходТоваров";
Если Диалог.Выбрать() Тогда
ПриходТоваров = Диалог.ВыбранныхЗначений[0];
ЭтотОбъект.ЦеныТовары.Очистить();
Для Каждого СтрокаПриход Из ПриходТоваров.Товары Цикл
НоваяСтрока = ЭтотОбъект.ЦеныТовары.Добавить();
НоваяСтрока.Номенклатура = СтрокаПриход.Номенклатура;
НоваяСтрока.ЕдиницаИзмерения = СтрокаПриход.ЕдиницаИзмерения;
НоваяСтрока.НоваяЦена = СтрокаПриход.Цена;
КонецЦикла;
Сообщение("Цены заполнены из документа поступления");
КонецЕсли;
КонецПроцедуры
// Процедура пересчёта цен с применением отклонения
Процедура ПересчитатьЦены(Команда)
Для Каждого ЦенаСтрока Из ЭтотОбъект.ЦеныТовары Цикл
Если ЦенаСтрока.ОтклонениеПроцент <> 0 Тогда
// Получаем текущую цену
ТекущаяЦена = ПолучитьТекущуюЦену(ЦенаСтрока.Номенклатура, ЭтотОбъект.ТипЦены);
// Применяем отклонение
ЦенаСтрока.НоваяЦена = ТекущаяЦена * (1 + ЦенаСтрока.ОтклонениеПроцент / 100);
КонецЕсли;
КонецЦикла;
Сообщение("Цены пересчитаны");
КонецПроцедуры
// Функция получения текущей цены
Функция ПолучитьТекущуюЦену(Номенклатура, ТипЦены)
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Цены
|ГДЕ
| Цены.Номенклатура = @Номенклатура
| И Цены.ТипЦены = @ТипЦены
| И Цены.Период <= @ТекущаяДата
| И (Цены.ДатаОконча > @ТекущаяДата ИЛИ Цены.ДатаОконча = '00010101')
|УПОРЯДОЧИТЬ ПО
| Цены.Период УБЫВ";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("ТипЦены", ТипЦены);
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());
Результат = Запрос.Выполнить();
Если НЕ Результат.Пусто() Тогда
Выборка = Результат.Выбрать();
Выборка.Следующий();
Возврат Выборка.Цена;
КонецЕсли;
Возврат 0;
КонецФункции
Функция автоматической подстановки цены в документ продажи
// Процедура при заполнении номенклатуры в табличной части
Процедура ТаблицаПродажиНоменклатураПриИзменении(Элемент)
ТекущаяСтрока = Элемент.ТекущиеДанные;
// Получаем выбранный тип цены
ТипЦены = ЭтаФорма.ОбъектДанных.ТипЦены;
Если НЕ ЗначениеЗаполнено(ТипЦены) Тогда
Сообщение("Сначала выберите тип цены");
Возврат;
КонецЕсли;
// Получаем цену для номенклатуры и типа
Цена = ПолучитьЦенуДляДокумента(
ТекущаяСтрока.Номенклатура,
ТипЦены,
ТекущаяСтрока.Количество
);
Если ЗначениеЗаполнено(Цена) Тогда
ТекущаяСтрока.Цена = Цена;
ТекущаяСтрока.Сумма = ТекущаяСтрока.Количество * ТекущаяСтрока.Цена;
Иначе
Сообщение("Цена не установлена для выбранной номенклатуры");
КонецЕсли;
КонецПроцедуры
// Функция для получения цены с учётом скидок
Функция ПолучитьЦенуДляДокумента(Номенклатура, ТипЦены, Количество)
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| Цены.Цена,
| Цены.НижнийПредел
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Цены
|ГДЕ
| Цены.Номенклатура = @Номенклатура
| И Цены.ТипЦены = @ТипЦены
| И Цены.Период <= @ТекущаяДата
| И (Цены.ДатаОконча > @ТекущаяДата ИЛИ Цены.ДатаОконча = '00010101')
|УПОРЯДОЧИТЬ ПО
| Цены.Период УБЫВ";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("ТипЦены", ТипЦены);
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДата());
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Если Выборка.Следующий() Тогда
Цена = Выборка.Цена;
// Применяем скидку если превышен нижний предел
Если Количество >= Выборка.НижнийПредел И Выборка.НижнийПредел > 0 Тогда
// Можно применить скидку здесь
КонецЕсли;
Возврат Цена;
КонецЕсли;
Возврат 0;
КонецФункции
Отчёт "Прайс-лист"
// Функция для получения прайс-листа
Функция ПолучитьПрайсЛист(ТипЦены, НаДату = Неопределено)
Если НаДату = Неопределено Тогда
НаДату = ТекущаяДата();
КонецЕсли;
Таблица = Новый ТаблицаЗначений();
Таблица.Колонки.Добавить("Код", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("ЕдиницаИзмерения", Новый ОписаниеТипов("Строка"));
Таблица.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
Таблица.Колонки.Добавить("НижнийПредел", Новый ОписаниеТипов("Число"));
Таблица.Колонки.Добавить("ДатаНачала", Новый ОписаниеТипов("Дата"));
Таблица.Колонки.Добавить("ДатаОконча", Новый ОписаниеТипов("Дата"));
Запрос = Новый Запрос();
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Номер КАК Код,
| Номенклатура.Наименование КАК Номенклатура,
| ЕдиницыИзмерения.Наименование КАК ЕдиницаИзмерения,
| Цены.Цена,
| Цены.НижнийПредел,
| Цены.ДатаНачала,
| Цены.ДатаОконча
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК Цены
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
| ПО Цены.Номенклатура = Номенклатура.Ссылка
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения
| ПО Цены.ЕдиницаИзмерения = ЕдиницыИзмерения.Ссылка
|ГДЕ
| Цены.ТипЦены = @ТипЦены
| И Цены.Период <= @НаДату
| И (Цены.ДатаОконча > @НаДату ИЛИ Цены.ДатаОконча = '00010101')
| И НЕ Номенклатура.ПометкаУдаления = Истина
|УПОРЯДОЧИТЬ ПО
| Номенклатура.Номер,
| Номенклатура.Наименование";
Запрос.УстановитьПараметр("ТипЦены", ТипЦены);
Запрос.УстановитьПараметр("НаДату", НаДату);
Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
НоваяСтрока = Таблица.Добавить();
НоваяСтрока.Код = Выборка.Код;
НоваяСтрока.Номенклатура = Выборка.Номенклатура;
НоваяСтрока.ЕдиницаИзмерения = Выборка.ЕдиницаИзмерения;
НоваяСтрока.Цена = Выборка.Цена;
НоваяСтрока.НижнийПредел = Выборка.НижнийПредел;
НоваяСтрока.ДатаНачала = Выборка.ДатаНачала;
НоваяСтрока.ДатаОконча = Выборка.ДатаОконча;
КонецЦикла;
Возврат Таблица;
КонецФункции
Архитектурные решения
1. История изменения цен:
- Регистр с Периодом позволяет хранить историю
- Можно откатиться на любую дату
2. Гибкое управление:
- Документ УстановкаЦен для массовых изменений
- Возможность автоматизации из поступлений
3. Автоматизация в документах:
- События табличной части подставляют цену
- Скидки и пределы рассчитываются автоматически
4. Безопасность:
- Валидация цен
- Логирование изменений
- История для аудита
Эта система обеспечивает гибкое и удобное управление ценами в конфигурации 1С:Предприятие.