При автоматизации учетных задач в 1С:Предприятии 7.7 разработчики часто сталкиваются с ситуацией, когда документ, созданный из внешнего кода или обработки, ведет себя некорректно: в журнале отсутствует наименование операции, в заголовке окна отображается неполное название, а при попытке проведения возникает ошибка вида «Не заполнен реквизит "Валюта документа". Документ не проводится!».
Разберем подробно, почему возникает такое поведение платформы и как правильно организовать программное заполнение и проведение документов.
Проанализируем исходный код создания объекта:
Процедура Сформировать()
Док = СоздатьОбъект("Документ.СписаниеТМЦ");
фирмы = СоздатьОбъект("Справочник.Фирмы");
склад = СоздатьОбъект("Справочник.Склады");
Прод = СоздатьОбъект("Справочник.Номенклатура");
Док.Новый();
фирмы.НайтиПоКоду("00003");
склад.НайтиПоКоду("00004");
Прод.НайтиПоКоду("41835");
Док.Фирма = фирмы.ТекущийЭлемент();
Док.Склад = склад.ТекущийЭлемент();
Док.НоваяСтрока();
Док.Номенклатура = Прод.ТекущийЭлемент();
Док.Количество = 10;
Док.Записать();
КонецПроцедуры
Выясним причину возникших сложностей:
ВводНового(), а также вызываются типовые функции заполнения шапки по умолчанию. При программной инициализации через СоздатьОбъект("Документ...") и метод Новый() модуль формы не загружается, и все реквизиты, обычно заполняемые по умолчанию (валюта, вид операции, флаги учета налогов, коэффициенты), остаются пустыми.ВидОперации. В большинстве типовых конфигураций 7.7 заголовок документа в журнале и шапке формируется динамически на основе значения реквизита ВидОперации (например, Перечисление.ВидыОперацийСписаниеТМЦ.СписаниеРозница или СписаниеОпт). Если значение не присвоено, документ не получает детального описания операции.Валюта или ВалютаДокумента), курса и кратности.НайтиПоКоду() или НайтиПоНаименованию() без проверки возвращаемого статуса может привести к записи пустого значения, если нужный элемент справочника не найден.Рассмотрим по шагам, как построить надежный алгоритм программного создания документа списания ТМЦ.
Если фирмы.НайтиПоКоду("00003") = 0 Тогда
Сообщить("Фирма с указанным кодом не найдена!");
Возврат;
КонецЕсли;
Док.ВидОперации = Перечисление.ВидыОперацийСписаниеТМЦ.СписаниеРозница;
Док.Валюта = Константа.БазоваяВалюта;
Док.Курс = 1;
Док.Кратность = 1;
глЗаполнитьШапку(Док);
Док.Фирма = фирмы.ТекущийЭлемент();
глПриИзмененииФирмы(Док);
Важно: Обратите внимание, что некоторые типовые процедуры из глобального модуля рассчитывают на контекст открытой формы (обращаются к Форма...). При работе с программным объектом Документ используйте только те функции, которые принимают объект документа и оперируют реквизитами базы данных.
Док.АвтоВремяКонецДня();
Записать() только сохраняет документ в базе. Для выполнения движений по регистрам необходимо вызвать метод Провести():
Если Док.Провести(РежимПроведения.Оперативный) = 0 Тогда
Сообщить("Не удалось провести документ! Проверьте остатки на складе.");
КонецЕсли;
Посмотрим на полный и рабочий пример процедуры программного создания документа с контролем ссылок, заполнением обязательных реквизитов и проведением:
Процедура Сформировать()
Перем спрФирмы, спрСклады, спрНоменклатура, Док;
спрФирмы = СоздатьОбъект("Справочник.Фирмы");
спрСклады = СоздатьОбъект("Справочник.Склады");
спрНоменклатура = СоздатьОбъект("Справочник.Номенклатура");
Если спрФирмы.НайтиПоКоду("00003") = 0 Тогда
Сообщить("Ошибка: Фирма не найдена!");
Возврат;
КонецЕсли;
Если спрСклады.НайтиПоКоду("00004") = 0 Тогда
Сообщить("Ошибка: Склад не найден!");
Возврат;
КонецЕсли;
Если спрНоменклатура.НайтиПоКоду("41835") = 0 Тогда
Сообщить("Ошибка: Номенклатура не найдена!");
Возврат;
КонецЕсли;
Док = СоздатьОбъект("Документ.СписаниеТМЦ");
Док.Новый();
Док.ДатаДок = РабочаяДата();
Док.АвтоВремяКонецДня();
// Заполнение обязательных реквизитов шапки
Док.Фирма = спрФирмы.ТекущийЭлемент();
Док.Склад = спрСклады.ТекущийЭлемент();
Док.ВидОперации = Перечисление.ВидыОперацийСписаниеТМЦ.СписаниеРозница;
Док.Валюта = Константа.БазоваяВалюта;
Док.Курс = 1;
Док.Кратность = 1;
// Заполнение табличной части
Док.НоваяСтрока();
Док.Номенклатура = спрНоменклатура.ТекущийЭлемент();
Док.Количество = 10;
Док.Коэффициент = 1;
// Запись и проведение документа
Док.Записать();
Если Док.Провести(РежимПроведения.Оперативный) = 1 Тогда
Сообщить("Документ " + Док.ТекущийДокумент() + " успешно создан и проведен!");
Иначе
Предупреждение("Документ записан, но не проведен!");
КонецЕсли;
КонецПроцедуры
Такой подход гарантирует, что у документа будет корректный заголовок во всех журналах учета, заполнятся все ключевые реквизиты, а проведение по регистрам остатков и партий пройдет без системных ошибок.