Как реализовать контроль месячных лимитов продаж номенклатуры и автоматическую смену договора в 1С?

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

В торговых компаниях часто возникает задача ограничить объем продаж определенных товаров для менеджеров. Например, в рамках одного спецпредложения (Договор 2) менеджер может продать не более 30 единиц конкретной номенклатуры в месяц. Если лимит исчерпан, программа должна автоматически переключить условия продажи на стандартные (Договор 1). Рассмотрим, как правильно спроектировать архитектуру такого решения, какие объекты 1С использовать и каких ошибок стоит избегать.

Архитектура хранения данных: Лимиты и Обороты

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

1. Настройка лимитов (Регистр сведений)

Для хранения информации о том, какому менеджеру и на какую номенклатуру установлен лимит, лучше всего использовать непериодический или периодический (в зависимости от частоты смены правил) РегистрСведений. Назовем его, например, ЛимитыПродажМенеджеров.

Рекомендуемая структура регистра:

Такая структура позволит гибко задавать лимиты на каждый месяц. Если запись для менеджера отсутствует, мы можем считать, что лимит не ограничен или равен нулю, в зависимости от бизнес-логики.

2. Учет фактических продаж (Регистр накопления)

Хотя на форумах часто предлагают делать запрос напрямую к документам, этот путь тупиковый для высоконагруженных систем. Рассмотрим подробнее, почему стоит выбрать РегистрНакопления с видом «Обороты».

Использование регистра оборотов позволяет системе мгновенно получать данные о накопленных продажах за период, не пересчитывая тысячи документов. Назовем его ПродажиПоЛимитируемымДоговорам.

Структура регистра оборотов:

Алгоритм проверки и автоматической смены договора

Разберем по шагам, как должна работать система при выборе товара в заказе или при его проведении.

Проанализируем ситуацию: менеджер добавляет строку в «Заказ клиента». В этот момент нам нужно оперативно подсказать ему, проходит ли товар по «Договору 2» или лимит уже исчерпан. Для этого в обработчике события ПриИзменении номенклатуры или количества на форме документа мы должны выполнить запрос.

Пример логики запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   ЕСТЬNULL(Лимиты.КоличествоЛимит, 0) КАК Лимит,
    |   ЕСТЬNULL(ПродажиОбороты.КоличествоОборот, 0) КАК Продано
    |ИЗ
    |   РегистрСведений.ЛимитыПродажМенеджеров КАК Лимиты
    |       ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ПродажиПоЛимитируемымДоговорам.Обороты(&НачалоПериода, &КонецПериода, , Менеджер = &Менеджер И Номенклатура = &Номенклатура И Договор = &Договор2) КАК ПродажиОбороты
    |       ПО Лимиты.Менеджер = &Менеджер И Лимиты.Номенклатура = &Номенклатура";

Если Продано + ТекущееКоличество > Лимит, то система должна программно подставить Договор 1. Однако здесь кроется важный нюанс: в 1С договор чаще всего указывается в шапке документа. Если в одном заказе часть товаров укладывается в лимит, а часть — нет, документ придется либо разделять на два, либо выводить менеджеру предупреждение о необходимости создать второй заказ.

Проблема границы периода и даты отгрузки

Выясним причину частых ошибок при планировании отгрузок на стыке месяцев. Если менеджер оформляет заказ 25-го числа, а отгрузка планируется на 10-е число следующего месяца, то лимит должен расходоваться из квоты следующего месяца.

Для корректной работы системы необходимо ориентироваться не на Дата документа, а на реквизит ДатаОтгрузки. В движения регистра накопления данные должны попадать именно на дату планируемой отгрузки. Это позволит системе «видеть» будущие расходы лимита и не допускать перепродаж.

Обеспечение целостности данных: Блокировки

Рассмотрим ситуацию: два менеджера одновременно продают последнюю единицу товара по лимиту. Если проверка идет только визуально на форме, оба документа будут проведены, и возникнет превышение. Чтобы этого избежать, обязателен контроль в транзакции проведения.

В модуле объекта в обработчике ОбработкаПроведения необходимо реализовать жесткий контроль с использованием механизма БлокировкаДанных. Мы должны заблокировать комбинацию «Менеджер + Номенклатура + Период», чтобы другие сеансы не могли изменить данные, пока мы проверяем остаток и записываем свои движения.

Пример установки блокировки:


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ПродажиПоЛимитируемымДоговорам");
ЭлементБлокировки.УстановитьПараметр("Менеджер", Менеджер);
ЭлементБлокировки.УстановитьПараметр("Номенклатура", Номенклатура);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();

Обработка возвратов и корректировок

Важно помнить, что управленческий учет — это не только продажи, но и возвраты. Если клиент вернул товар, лимит менеджера должен восстановиться. При использовании регистра накопления (Обороты) это решается автоматически: документ «Возврат товаров от клиента» делает запись с отрицательным значением расхода («сторно»), что увеличивает доступный остаток лимита при расчете запросом.

Использование расширений для реализации

Чтобы сохранить конфигурацию на поддержке и не вносить изменения в типовые объекты (например, если вы работаете с 1С:УНФ или 1С:УТ), всю логику лимитирования лучше вынести в Расширение.

  1. Создаем в расширении свои регистры (РС и РН).
  2. Через механизм &После или &Перед расширяем процедуру ОбработкаПроведения заказов или реализаций.
  3. Добавляем обработчики событий на форму документа для интерактивной проверки лимита.

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

← На главную