Как найти Расходный ордер на товары по Распоряжению в 1С:КА 2.4 и ERP

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

В процессе автоматизации складской логистики в конфигурациях 1С:Комплексная автоматизация 2.4 или 1С:ERP программисты часто сталкиваются с ситуацией, когда после программного проведения Заказа клиента или Реализации товаров и услуг система не «видит» автоматически созданный Расходный ордер на товары. Мы подготовили подробный разбор этой задачи, выясним причины «невидимости» документа и рассмотрим правильные методы работы с цепочками документов на ордерном складе.

Проблема: Почему запрос не находит ордер сразу после записи распоряжения?

Рассмотрим типовую ситуацию: разработчик пишет код, который переводит статус позиций в Заказе клиента в значение «Отгрузить», проводит документ и сразу пытается найти созданный Расходный ордер на товары (РОНТ) с помощью запроса по табличной части ТоварыПоРаспоряжениям. Однако запрос возвращает пустой результат, хотя при проверке в консоли запросов чуть позже документ прекрасно находится.

Проанализируем основные причины этого поведения:

  1. Транзакционная целостность. Если поиск ордера происходит внутри той же транзакции, в которой записывается распоряжение, механизмы автоматического создания ордеров могут еще не завершить свою работу.
  2. Асинхронность и фоновые задания. В современных версиях ERP-систем создание складских документов часто выносится в фоновые процессы для повышения производительности. Запрос выполняется мгновенно, а фоновое задание по созданию ордера может отставать на несколько секунд.
  3. Настройки склада. Параметр «Оформление расходных ордеров» в карточке склада определяет, что именно является распоряжением: сам заказ или накладная (реализация).

Разбор кода: Поиск ордера через запрос

Для начала рассмотрим классический способ поиска ордера. Нам необходимо обратиться к табличной части документа РОНТ, так как именно там хранится связь с документом-основанием. Проанализируем пример кода:


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

Запрос.УстановитьПараметр("Распоряжение", СсылкаНаДокумент);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    // Обработка найденного ордера
    ОбъектОрдера = Выборка.Ссылка.ПолучитьОбъект();
    ОбъектОрдера.Статус = Перечисления.СтатусыРасходныхОрдеров.Отгружен;
    ОбъектОрдера.Записать(РежимЗаписиДокумента.Проведение);
КонецЦикла;

Важный нюанс: Поле Распоряжение в табличной части имеет Определяемый тип. При передаче параметра убедитесь, что тип ссылки (например, ДокументСсылка.ЗаказКлиента) входит в этот определяемый тип. Если вы ищете ордер по Реализации, а в складских настройках указано «По заказам», запрос не вернет результат.

Метод 1: Определение правильного распоряжения

Выясним причину, по которой ордер может не находиться. В 1С:КА 2.4/ERP логика работы склада гибко настраивается. Перейдем в настройки склада и проверим поле «Порядок оформления расходных ордеров»:

Если ваш код создает Реализацию на основании Заказа, а склад работает «по накладным», то в параметре запроса &Распоряжение нужно передавать ссылку на созданную Реализацию, а не на Заказ.

Метод 2: Использование критериев отбора

Вместо прямого запроса к табличным частям, который может быть тяжелым для базы данных, мы рекомендуем использовать критерий отбора СвязанныеДокументы. Это штатный механизм системы, который позволяет быстро получить список всех подчиненных документов.


// Получаем все связанные документы для нашего Заказа или Реализации
СписокСвязанных = КритерииОтбора.СвязанныеДокументы.Найти(СсылкаНаРаспоряжение);

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

Метод 3: Обработка ожидания и завершение транзакции

Проанализируем ситуацию, когда ордер создается фоновым заданием. Если вы программно провели распоряжение, 1С ставит задачу в очередь. Пытаться найти ордер в ту же миллисекунду — плохая практика. Рассмотрим, как сделать это правильно:

Никогда не используйте пустые циклы для «задержки» кода — это вешает систему. Вместо этого разделите процесс на два этапа:

  1. Программное создание и проведение распоряжения.
  2. Использование ПодключитьОбработчикОжидания (на клиенте) для проверки появления ордера через 2-3 секунды.

Если же код выполняется полностью на сервере (например, в регламентном задании), можно использовать конструкцию с попытками, но обязательно с выходом из транзакции распоряжения:


// Пример логики в регламентном задании
ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
// Здесь транзакция завершена. Теперь можно попробовать найти ордер.
Счетчик = 0;
Найден = Ложь;
Пока Счетчик < 5 И Не Найден Цикл
    // Запрос на поиск ордера
    // ...
    Если ОрдерНайден Тогда
        Найден = Истина;
    Иначе
        Счетчик = Счетчик + 1;
        // Можно использовать небольшую паузу, если это допустимо в фоновом задании
    КонецЕсли;
КонецЦикла;

Рекомендация по архитектуре решения

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

В этом случае вам не нужно «ловить» момент его создания из распоряжения. Как только система (сама или через фоновое задание) создаст ордер, сработает ваша подписка. В ней вы сможете проверить документ-основание и, если это ваш заказ, установить нужный статус и провести ордер. Это гарантирует 100% результат и исключает проблемы с таймингами транзакций.

Посмотрим, как может выглядеть такая проверка в подписке:


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

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

← На главную