Приветствуем вас! Довольно часто при разработке интеграций, загрузок из внешних систем или автоматизации складских процессов в 1С программистам приходится сталкиваться с необходимостью программного создания элементов справочников. Одним из таких важных объектов является справочник ПартииНоменклатуры, который активно используется в конфигурациях «1С:Управление нашей фирмой» (УНФ) и «1С:Розница».
Казалось бы, задача проста: создать новый элемент, заполнить ключевые реквизиты, такие как наименование и владелец, и записать его в базу данных. Однако на практике разработчики нередко сталкиваются с ситуацией, когда код уходит в блок Исключение, не выдавая явных ошибок, а элемент в базе так и не появляется. В этой статье мы подробно разберем, почему возникает эта проблема, как правильно её локализовать и какие стандарты разработки 1С необходимо соблюдать для написания надежного кода.
Рассмотрим типичный пример кода, с которым часто начинают работу специалисты при создании партий:
&НаСервере
Процедура Расш1_СоздатьПартииПослеНаСервере()
Для каждого Строка из Объект.Продукция цикл
Партия = Справочники.ПартииНоменклатуры.СоздатьЭлемент();
Партия.Наименование = Строка(Строка.Количество) + " м/п";
Партия.Владелец = Строка.Номенклатура;
Попытка
Партия.Записать();
Исключение
Сообщить("Партия не записалась");
КонецПопытки;
Строка.Партия = Партия.Ссылка;
КонецЦикла;
КонецПроцедуры
Проанализируем эту ситуацию. С одной стороны, разработчик обезопасил транзакцию от аварийного завершения работы программы. С другой стороны, конструкция Попытка...Исключение полностью скрыла от нас системное сообщение платформы. В случае ошибки мы видим лишь сухой и малоинформативный текст «Партия не записалась».
Важное правило отладки: на этапе разработки и тестирования функционала всегда выносите метод Записать() за пределы блока Попытка. Это позволит платформе 1С выбросить полноценное исключение с указанием конкретной причины сбоя (например, нарушение уникальности, незаполненные обязательные реквизиты или ошибки в подписках на события).
В конфигурациях 1С:УНФ и 1С:Розница справочник ПартииНоменклатуры имеет жесткую бизнес-логику. Для успешной записи элемента недостаточно указать только Наименование и Владелец (номенклатуру). В справочнике присутствует строго обязательный реквизит Статус.
Этот реквизит имеет тип данных ПеречислениеСсылка.СтатусыПартий. Если он не заполнен, платформа на уровне объектной техники (или в модуле объекта в процедурах ПередЗаписью / ПриЗаписи) блокирует транзакцию.
Давайте разберем по шагам, какие значения может принимать статус партии:
Перечисления.СтатусыПартий.СобственныеЗапасы) — используется для обычного учета товаров, принадлежащих организации.Перечисления.СтатусыПартий.ТоварыНаКомиссии) — применяется при реализации комиссионных товаров.Перечисления.СтатусыПартий.ОтветственноеХранение) — используется для ТМЦ, принятых на склад под отчет.Перечисления.СтатусыПартий.ДавальческоеСырье) — для переработки материалов заказчика.Для исправления ошибки нам обязательно нужно явно инициализировать этот реквизит перед вызовом метода записи:
Партия.Статус = Перечисления.СтатусыПартий.СобственныеЗапасы; // Либо иной статус в зависимости от вашей бизнес-логики
Помимо статуса, при работе со справочником партий следует обратить внимание на следующие нюансы:
ВладелецПартии. В него записывается ссылка на контрагента (поставщика, комитента или давальца).Использование слепого блока Попытка...Исключение при записи бизнес-объектов в свою же базу данных считается плохим тоном разработки. Платформа 1С предоставляет более изящные и правильные способы контроля данных.
Вместо того чтобы доводить транзакцию до аварийного прерывания и перехватывать его, мы можем программно вызвать проверку заполнения всех обязательных реквизитов. Рассмотрим, как это выглядит на практике:
Если Партия.ПроверитьЗаполнение() Тогда
Партия.Записать();
Строка.Партия = Партия.Ссылка;
Иначе
// Платформа автоматически выведет пользователю сообщения о том, какие реквизиты не заполнены
КонецЕсли;
Этот подход позволяет дружелюбно сообщить пользователю о незаполненных полях через стандартный механизм СообщенияПользователю, не прерывая выполнение кода критической ошибкой.
Если специфика алгоритма все же требует обязательного использования блока Попытка (например, запись происходит в транзакции или при импорте данных из внешних файлов), никогда не оставляйте блок Исключение пустым или с неинформативными сообщениями. Обязательно логируйте технические подробности сбоя.
В современных версиях платформы 1С:Предприятие 8.3 для этого используются функции ИнформацияОбОшибке(), ПодробноеПредставлениеОшибки() и КраткоеПредставлениеОшибки().
Давайте посмотрим на пример правильной обработки исключения при записи объекта:
Попытка
Партия.Записать();
Строка.Партия = Партия.Ссылка;
Исключение
ИнфоОбОшибке = ИнформацияОбОшибке();
// 1. Записываем подробную информацию в Журнал регистрации для администратора и программиста
ЗаписатьЖурналРегистрации("ПрограммноеСозданиеПартий",
УровеньЖурналаРегистрации.Ошибка,
,
,
ПодробноеПредставлениеОшибки(ИнфоОбОшибке));
// 2. Выводим понятное и безопасное сообщение для конечного пользователя
ТекстОшибкиДляПользователя = КраткоеПредставлениеОшибки(ИнфоОбОшибке);
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
NStr("ru = 'Не удалось записать партию. Причина: '") + ТекстОшибкиДляПользователя);
КонецПопытки;
При таком подходе программист всегда сможет открыть Журнал регистрации и по стеку вызовов моментально понять, на какой строчке кода и по какой причине произошел сбой, а пользователь получит аккуратное предупреждение вместо аварийного закрытия программы.
Объединив все полученные знания, перепишем исходную процедуру автора темы в соответствии со стандартами разработки «1С:Предприятие»:
&НаСервере
Процедура Расш1_СоздатьПартииПослеНаСервере()
Для каждого Строка из Объект.Продукция цикл
Партия = Справочники.ПартииНоменклатуры.СоздатьЭлемент();
Партия.Наименование = Строка(Строка.Количество) + " м/п";
Партия.Владелец = Строка.Номенклатура;
// Обязательно заполняем статус партии!
Партия.Статус = Перечисления.СтатусыПартий.СобственныеЗапасы;
// Выполняем проверку и запись
Если Партия.ПроверитьЗаполнение() Тогда
Попытка
Партия.Записать();
Строка.Партия = Партия.Ссылка;
Исключение
ИнфоОбОшибке = ИнформацияОбОшибке();
ЗаписатьЖурналРегистрации("СозданиеПартии",
УровеньЖурналаРегистрации.Ошибка,
Партия.Метаданные(),
,
ПодробноеПредставлениеОшибки(ИнфоОбОшибке));
ВызватьИсключение NStr("ru = 'Ошибка записи партии номенклатуры. Подробности записаны в Журнал регистрации.'");
КонецПопытки;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Применяя данные подходы, вы убережете свои базы данных от некорректно заполненных данных, а код сделаете прозрачным, расширяемым и легким в поддержке. Желаем вам успешной разработки в среде 1С!