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