Как программно создать «Приходный ордер на товары» на основании «Поступления» и обойти ошибку «Приходный ордер на товары нужно вводить из формы "Приемка"»?

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

При автоматизации складского учета в конфигурациях «1С:Управление торговлей» (включая редакцию для Беларуси), «1С:ERP» или «1С:Комплексная автоматизация» разработчики часто сталкиваются с необходимостью программного создания цепочки документов. Типичная задача — загрузить или создать документ Поступление товаров и услуг (в более новых редакциях — Приобретение товаров и услуг), а затем на его основании автоматически сформировать и провести Приходный ордер на товары.

Однако при попытке вызвать стандартный метод Заполнить() система часто выбрасывает исключение с текстом: «Приходный ордер на товары нужно вводить из формы "Приемка"». В этой статье мы подробно разберем причины возникновения этой ошибки и рассмотрим два надежных способа ее решения.

---

Почему возникает ошибка при программном заполнении ордера?

Давайте разберем внутреннюю логику работы конфигурации. При вызове метода ПриходныйОрдерНаТовары.Заполнить(ДокументПоступление) управление передается в процедуру ОбработкаЗаполнения в модуле объекта приходного ордера. В этой процедуре система выполняет целый ряд строгих проверок:

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

Ниже мы подробно разберем два пути решения этой проблемы: правильное использование стандартного механизма заполнения и альтернативный вариант с ручным заполнением реквизитов.

---

Способ 1. Использование стандартного заполнения (с предварительной подготовкой данных)

Если мы хотим использовать типовой механизм Заполнить(), нам необходимо строго соблюсти последовательность действий и подготовить данные в базе данных так, чтобы они успешно прошли все проверки внутри модуля объекта приходного ордера.

Рассмотрим пошагово правильный алгоритм реализации этого способа:

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

Проанализируем пример кода, реализующий этот подход:


// Шаг 1. Создание и проведение финансового документа-основания
НовоеПоступление = Документы.ПриобретениеТоваровУслуг.СоздатьДокумент();
НовоеПоступление.Дата = ТекущаяДата();
// ... (Заполнение обязательных реквизитов: Организация, Контрагент, Склад, Товары и т.д.)
НовоеПоступление.Записать(РежимЗаписиДокумента.Проведение);

СсылкаНаОснование = НовоеПоступление.Ссылка;

// Шаг 2. Создание Приходного ордера на товары
НовыйОрдер = Документы.ПриходныйОрдерНаТовары.СоздатьДокумент();
НовыйОрдер.Дата = ТекущаяДата();

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

---

Способ 2. Ручное заполнение реквизитов (Обход ОбработкиЗаполнения)

Что делать, если вам нужно создать приходный ордер на товары без предварительного проведения финансового документа или если вы хотите иметь полный контроль над переносимыми данными, минуя любые ограничения и проверки платформы? В этом случае лучшим решением будет ручной перенос данных из документа-основания в ордер.

При этом подходе мы не вызываем метод Заполнить(), а самостоятельно заполняем шапку и табличную часть ордера в кодовой обработке.

Рассмотрим детальный пример реализации ручного заполнения:


// Предположим, у нас уже есть созданная и записанная ссылка на Поступление
СсылкаНаОснование = Объект.ДокументИсточник; 

НовыйОрдер = Документы.ПриходныйОрдерНаТовары.СоздатьДокумент();
НовыйОрдер.Дата = ТекущаяДата();

// Заполнение реквизитов шапки документа
НовыйОрдер.Склад = СсылкаНаОснование.Склад;
НовыйОрдер.Отправитель = СсылкаНаОснование.Партнер;
НовыйОрдер.Распоряжение = СсылкаНаОснование; // Связываем документы напрямую через реквизит Распоряжение
НовыйОрдер.СкладскаяОперация = Перечисления.СкладскиеОперации.ПриемкаОтПоставщика;

// Установка статуса документа. 
// Статус "Принят" делает фактические движения по складским регистрам накопления.
НовыйОрдер.Статус = Перечисления.СтатусыПриходныхОрдеров.Принят;

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

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

---

Важные нюансы, о которых нужно помнить

Таким образом, мы детально разобрали обе методики интеграции складских документов. Способ с ручным заполнением является наиболее гибким для разработчиков внешних обработок интеграции и загрузки данных из внешних источников (например, Excel или API), так как он позволяет полностью избежать конфликтов с интерфейсными ограничениями платформы 1С.

← На главную