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