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