При автоматизации бизнес-процессов в среде 1С:Управление торговлей 11 (а также в ERP 2 или Комплексной автоматизации 2) программисты часто сталкиваются с ситуацией, когда документ, созданный программно, отказывается проводиться. Одной из самых коварных ошибок является сообщение: «Запись не верна! Значение поля "Распоряжение" не может быть пустым! (Регистр накопления: Движение товаров; Номер строки: 1)». Ситуация осложняется тем, что при интерактивном открытии этого же документа и простом перевыборе договора проблема «магически» исчезает, и документ проводится без нареканий.
В этой статье мы подробно разберем причины возникновения этой ошибки, выясним, почему интерактивные действия помогают, и научимся правильно писать код для программного создания документов, чтобы избежать подобных коллизий.
Для начала проанализируем архитектуру системы. Регистр накопления ДвиженияТоваров является ключевым для оперативного учета остатков на складах. В отличие от простых регистров остатков, здесь поле Распоряжение является обязательным. Система должна четко понимать, на каком основании товар поступил или выбыл. В качестве распоряжения могут выступать:
Когда вы создаете документ программно, вы просто заполняете реквизиты объекта. Однако в современных конфигурациях на базе BSP (Библиотеки стандартных подсистем) и типовых решениях УТ 11 огромная часть логики скрыта в процедурах формы. Когда пользователь меняет договор на форме, срабатывают обработчики событий (ПриИзменении), которые не только подставляют значения, но и заполняют внутренние (иногда скрытые от глаз) реквизиты документа или устанавливают флаги в дополнительных свойствах объекта.
Рассмотрим ситуацию: вы создали объект документа, заполнили организацию, контрагента, договор и табличную часть. Но при попытке ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение) система выдает ошибку распоряжения. Это происходит потому, что механизм проведения не смог определить «хозяйственный смысл» операции из-за пустоты определенных служебных полей.
Проанализируем основные причины «пустого распоряжения»:
ХозяйственнаяОперация критически важен. Если вы указали договор, но не установили операцию (например, ЗакупкаУПоставщика), алгоритмы проведения по регистрам склада могут отработать некорректно.ЗаказПоставщику или специфические идентификаторы строк. Если они пусты, система пытается найти распоряжение в шапке, но из-за несоответствия настроек склада (например, если склад ордерный) не находит его.Чтобы документ проводился корректно, нам нужно имитировать действия пользователя. Простого присвоения Объект.Договор = Ссылка недостаточно. Необходимо вызвать экспортные процедуры из общих модулей, которые отвечают за инициализацию параметров соглашений и договоров.
Посмотрим на пример кода, который решает проблему заполнения необходимых реквизитов:
// Предположим, ДокОбъект — это наше создаваемое Приобретение товаров и услуг
ДокОбъект.Дата = ТекущаяДата();
ДокОбъект.Организация = Справочники.Организации.НайтиПоРеквизиту("ИНН", "7700000000");
ДокОбъект.Партнер = ПартнерСсылка;
ДокОбъект.Контрагент = КонтрагентСсылка;
ДокОбъект.Договор = ДоговорСсылка;
// Важнейший шаг: установка хозяйственной операции
ДокОбъект.ХозяйственнаяОперация = Перечисления.ХозяйственныеОперации.ЗакупкаУПоставщика;
// Вызываем типовой механизм заполнения реквизитов по соглашению/договору
// Это заполнит налогообложение, счета учета, валюты и прочие скрытые параметры
ПараметрыЗаполнения = ЗакупкиСервер.ПараметрыЗаполненияПоСоглашению();
ЗакупкиСервер.ЗаполнитьРеквизитыПоСоглашению(ДокОбъект, ДокОбъект.Соглашение, ПараметрыЗаполнения);
// Если используем договор, убедимся, что параметры договора применены
// В некоторых версиях УТ это делается через вызов:
ПродажиВызовСервера.ОпределитьУсловияПродаж(ДокОбъект); // Аналогично для закупок
Выясним причину, связанную с табличной частью. Часто в УТ 11 поле Распоряжение в движениях регистра Движения товаров берется из колонки Заказ (или аналогичной) в ТЧ Товары. Даже если вы не используете заказы, это поле должно быть заполнено ссылкой на само это Приобретение (после его записи) или оставаться корректно пустым при определенных настройках.
Посмотрим, как правильно проинициализировать строки, чтобы они «видели» распоряжение:
Для Каждого СтрокаТЧ Из ДокОбъект.Товары Цикл
// Если закупка идет БЕЗ заказа, убедитесь, что реквизиты связки очищены
// или заполнены согласно логике "Приемка без заказа"
СтрокаТЧ.СтатусУказанияСерий = 0;
// В некоторых релизах нужно явно вызвать пересчет строк
КонецЦикла;
// Перед проведением документ ОБЯЗАТЕЛЬНО должен быть записан,
// чтобы ссылка на него стала валидной для использования в качестве распоряжения
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
Проанализируем ситуацию с ордерным складом. Если в настройках склада указано «Использовать для поступления: Приходный ордер на товары», то Приобретение само по себе становится распоряжением для складского работника. Ошибка «Распоряжение пустое» часто означает, что документ не смог зарегистрировать себя в качестве распоряжения.
Решение: Проверьте реквизит ВариантОформленияЗакупок (или аналогичный в зависимости от версии УТ). Он должен соответствовать значению Перечисления.ВариантыОформленияЗакупок.ПриобретениеПоЗаказу или ПриобретениеБезЗаказа. Также убедитесь, что Статус документа установлен в значение Подтвержден или К поступлению. В статусе Черновик документ может не формировать движений по складским регистрам вовсе, либо формировать их не полностью.
Иногда при программном создании мешают строгие проверки формы. Можно попробовать передать в объект признак того, что заполнение выполнено корректно и дополнительные проверки распоряжения не требуются. Это делается через структуру ДополнительныеСвойства.
ДокОбъект.ДополнительныеСвойства.Вставить("ПересчитатьРазделитель", Истина);
ДокОбъект.ДополнительныеСвойства.Вставить("ПропуститьПроверкуРаспоряжения", Истина); // Если предусмотрено логикой модуля
Однако помните, что это «костыльный» метод. Правильнее всего — обеспечить заполнение ХозяйственнойОперации и вызов метода ОбработкаТабличныхЧастейСервер.ЗаполнитьРеквизитыВТЧ(...).
Для того чтобы успешно провести программно созданный документ «Приобретение товаров и услуг» без ошибки пустого распоряжения, придерживайтесь следующего алгоритма:
ЗакупкиСервер.ЗаполнитьРеквизитыПоСоглашению. Это гарантирует, что все скрытые флаги (налогообложение, способ учета НДС, валютные параметры) будут установлены так же, как если бы их выбрал пользователь.Документ.Записать(), и только потом Документ.Записать(РежимЗаписиДокумента.Проведение). Это важно для формирования ссылочных связей в регистрах.Соблюдение этих правил позволит вам создавать надежные механизмы интеграции и автоматизации, которые не будут требовать «ручного вмешательства» со стороны пользователей для исправления ошибок проведения.