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