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

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

В торговой деятельности часто возникает ситуация, когда покупатель резервирует товар, но в установленный срок не оплачивает его и не забирает. Зарезервированный товар продолжает числиться на складе как «занятый», из-за чего другие клиенты не могут его приобрести. Менеджеры часто забывают вовремя снимать такие резервы вручную. В результате фирма теряет прибыль, а на складе образуются ложные дефициты.

В этой статье мы подробно разберем, как автоматизировать процесс снятия просроченных резервов в конфигурациях на платформе «1С:Предприятие 8» с классической архитектурой (таких как «Управление торговым предприятием», «Управление производственным предприятием» или «Управление торговлей 10.3»). Мы проанализируем штатные механизмы системы, разберем архитектурные ошибки разработчиков и напишем надежное решение на базе регламентного задания.

Штатные механизмы резервирования по времени в 1С

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

  1. Настройка в договоре контрагента: В договоре с покупателем (если ведение взаиморасчетов установлено «По заказам») доступен флаг Держать резерв без оплаты ограниченное время, дней не более. При включении этого флага и указании количества дней система будет автоматически рассчитывать реквизит ДатаОплаты в документе ЗаказПокупателя как ДатаЗаказа + N дней.
  2. Документ «Закрытие заказов покупателей»: Это штатный инструмент для снятия неиспользованных резервов и закрытия невыполненных заказов. В нем предусмотрен режим заполнения По неактуальным заказам или По просроченным оплатам.
  3. Учет производственного календаря: В настройках параметров учета системы можно задать контроль сроков оплаты по рабочим дням. В этом случае расчет просрочки будет опираться на регламентированный производственный календарь, исключая выходные и праздничные дни.

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

Анализ архитектурной ошибки: почему нельзя вызывать методы формы из регламентного задания

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

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

Правило разработки в 1С: Вся бизнес-логика (расчеты, заполнение табличных частей, проведение, проверки) должна быть строго отделена от интерфейса. Она должна располагаться либо в модуле объекта документа, либо в серверных общих модулях. Экспортные методы формы должны отвечать только за отображение данных на клиенте.

Пошаговое создание правильного автоматического механизма

Давайте реализуем надежное решение, которое будет работать полностью в фоновом режиме на сервере, не затрагивая клиентский контекст. Мы создадим регламентное задание, которое раз в сутки будет программно формировать и проводить документ ЗакрытиеЗаказовПокупателей.

Шаг 1. Создание серверного общего модуля

Если в вашей конфигурации еще нет подходящего неглобального общего модуля для фоновых процедур, создадим новый модуль. Назовем его, например, РегламентныеПроцедурыСервер. Обязательно установим для него свойства: Сервер и Вызов сервера (флаг Клиент должен быть снят).

Шаг 2. Написание кода программного заполнения и проведения документа

Рассмотрим код процедуры, которая будет выполняться регламентным заданием. Вместо имитации нажатия кнопок на форме, мы напрямую обратимся к механизмам заполнения табличной части документа в модуле объекта. Ниже представлен пример реализации:


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

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

Шаг 3. Создание и настройка Регламентного задания

Теперь нам необходимо зарегистрировать нашу процедуру в качестве регламентного задания в конфигураторе:

  1. Откроем конфигуратор, перейдем в ветку Общие -> Регламентные задания.
  2. Добавим новое регламентное задание с именем АвтоматическоеСнятиеРезервов.
  3. В свойстве Имя метода укажем путь к нашей процедуре: РегламентныеПроцедурыСервер.АвтоматическоеСнятиеПросроченныхРезервов.
  4. Установим флаг Использование.
  5. Настроим Расписание. Оптимально запускать данную процедуру один раз в сутки ночью (например, в 01:00), когда нагрузка на сервер минимальна и менеджеры не работают в базе.

Важные практические нюансы и «подводные камни»

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

Таким образом, автоматизация снятия резервов через регламентный запуск документа Закрытие заказов покупателей является наиболее правильным, «штатным» методом с точки зрения сохранения целостности регистров и истории документов в 1С. Реализовав предложенную схему с учетом особенностей вашего бизнеса, вы освободите время сотрудников и повысите оборачиваемость складских запасов.

← На главную