Как программно создать документ перемещения при проведении реализации в 1С:УТ 11.5?

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

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

Анализ проблемы и выбор архитектурного подхода

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

С другой стороны, создание перемещения внутри транзакции проведения реализации увеличивает время блокировки таблиц остатков. Если в документе десятки строк, система будет выполнять проверку остатков, списание, запись перемещения и его проведение одновременно, что в многопользовательском режиме приведет к ошибкам «Превышено время ожидания блокировки».

Способ 1. Использование штатного механизма «Группы складов»

Прежде чем программно создавать новые объекты, разберем штатный способ, который предлагает 1С. В УТ 11.5 существует возможность объединения складов в группы. Если в настройках группы складов разрешить «Разрешить продажи из нескольких складов», то в документе реализации можно будет указывать разные склады для каждой строки товара.

Рассмотрим преимущества этого метода:

  1. Нет необходимости в лишних документах перемещения.
  2. Система автоматически контролирует остатки по каждому складу.
  3. Печатные формы могут выводить информацию консолидировано или с разбивкой.

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

Способ 2. Программное создание через «Подписку на событие»

Для реализации автоматического создания документа лучше всего использовать механизм Подписок на события. Нам подойдет событие ОбработкаПроведения документа РеализацияТоваровУслуг. Это позволит не снимать документ с поддержки и реализовать логику в отдельном модуле.

Разберем алгоритм действий:

  1. Создаем новую Подписку на событие.
  2. Источник — ДокументОбъект.РеализацияТоваровУслуг.
  3. Событие — ОбработкаПроведения.
  4. В обработчике проверяем, достаточно ли остатков на складе реализации. Если нет — формируем запрос к остаткам на складе-источнике.

Пример кода для создания перемещения:


Процедура ПриПроведенииРеализации(Источник, Отказ, РежимПроведения) Экспорт
    
    // Проверяем, что это новая запись или перемещение еще не создано
    Если Источник.ДополнительныеСвойства.Свойство("ПеремещениеСоздано") Тогда
        Возврат;
    КонецЕсли;

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

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

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

Способ 3. Асинхронное создание через фоновые задания

Если объем данных велик и проведение реализации становится слишком долгим, проанализируем вариант с фоновыми заданиями. В этом случае перемещение создается сразу после успешного завершения транзакции реализации.

Посмотрим, как это реализовать:

  1. В событии ПриЗаписи (после успешного проведения) проверяем наличие перемещения.
  2. Если перемещения нет, вызываем метод ФоновыеЗадания.Выполнить().
  3. В процедуре фонового задания программно создаем и проводим документ.

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

Способ 4. Использование схем обеспечения потребностей

В УТ 11.5 развит механизм обеспечения. Вместо прямой «сцепки» документов кодом, мы можем настроить систему так, чтобы она сама видела потребность. Рассмотрим этот путь:

  1. Для «Склада 2» настраивается Схема обеспечения, где основным способом обеспечения указано «Перемещение со Склада 1».
  2. При создании «Заказа клиента» (на основании которого делается реализация) система анализирует остатки.
  3. Кладовщик или менеджер через рабочее место «Формирование заказов по потребностям» видит необходимость перемещения и создает его одной кнопкой для всех заказов за день.

Этот метод является наиболее методологически верным для 1С, так как разделяет ответственность: менеджер продает, а логист перемещает.

Защита от дублирования и обработка отмены проведения

Выясним причину возможного «бардака» в учете при программном создании. Основная проблема — повторное проведение. Если пользователь изменит количество в реализации и снова ее проведет, код может создать еще одно перемещение.

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

Пример проверки на существование перемещения:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ПеремещениеТоваров.Ссылка КАК Ссылка
    |ИЗ
    |	Документ.ПеремещениеТоваров КАК ПеремещениеТоваров
    |ГДЕ
    |	ПеремещениеТоваров.ДокументОснование = &Основание
    |	И НЕ ПеремещениеТоваров.ПометкаУдаления";

Запрос.УстановитьПараметр("Основание", Источник.Ссылка);
РезультатЗапроса = Запрос.Выполнить();

Если НЕ РезультатЗапроса.Пустой() Тогда
    // Документ уже есть, возможно нужно обновить его ТЧ, а не создавать новый
КонецЕсли;

Резюме

Подведем итог: наиболее стабильным техническим решением является использование Подписки на событие с выполнением кода внутри транзакции проведения. Это гарантирует, что товар не «повиснет» в воздухе. Однако для высоконагруженных систем (где одновременно работают десятки пользователей) следует рассмотреть штатные механизмы Групп складов или Обеспечения потребностей, так как они не создают избыточных блокировок в базе данных и соответствуют логике работы конфигурации 1С:Управление торговлей 11.5.

← На главную