При разработке или доработке конфигураций на платформе 1С разработчики нередко сталкиваются с ситуацией, когда при попытке программно создать и сохранить объект система выдает сухую и неинформативную ошибку. Чаще всего текст выглядит примерно так: «Ошибка при вызове метода контекста (Записать) ... по причине: Не удалось записать: "Имя справочника"!».
Рассмотрим классический пример кода, который приводит к такой ситуации:
Если НовыйНаселенныйПункт.ПроверитьЗаполнение() Тогда
НовыйНаселенныйПункт.Записать();
КонецЕсли;
На первый взгляд, все верно: мы проверяем заполнение обязательных реквизитов с помощью метода ПроверитьЗаполнение, и если оно проходит успешно, вызываем Записать. Но элемент всё равно не создается. Разберем по шагам, куда смотреть в первую очередь и как отловить причину такого поведения.
Первое и самое главное место, которое нужно проверить — это модуль самого справочника. В нем платформой предусмотрены стандартные обработчики событий, которые вызываются при попытке сохранения данных. Обратите внимание на процедуры ПередЗаписью и ПриЗаписи.
Если внутри этих процедур выполняется какая-либо бизнес-логика, которая решает, что данные некорректны (но при этом не выводит сообщение пользователю через функцию Сообщить или механизм сообщений), разработчик может просто установить параметр Отказ в значение Истина. В таком случае транзакция записи будет молча прервана платформой, и в вызывающий код вернется та самая общая ошибка.
Посмотрим на пример того, как это может выглядеть внутри модуля объекта:
Процедура ПередЗаписью(Отказ)
Если Не ЗначениеЗаполнено(РеквизитДляПроверки) Тогда
Отказ = Истина; // Запись прерывается без явного уведомления!
КонецЕсли;
КонецПроцедуры
Если в модуле самого справочника логики нет или она отрабатывает без ошибок, прерывание записи чаще всего происходит в подписках на события. В конфигураторе к вашему справочнику могут быть привязаны общие подписки на события ПередЗаписью, ПриЗаписи или ОбработкаПроверкиЗаполнения.
Эти подписки перенаправляют выполнение кода в процедуры общих модулей. Если в одной из таких процедур параметр Отказ принимает значение Истина, запись также отменяется. Обязательно найдите все подписки, источником которых является проблемный справочник, и проанализируйте их код.
В современных конфигурациях 1С логика записи может быть существенно изменена с помощью механизма расширений. Методы вроде ПередЗаписью могут незаметно перехватываться аннотациями &Перед или &Вместо в модулях расширений.
Обязательно выясним, не подключены ли к информационной базе расширения, модифицирующие этот справочник. Если перехватчик в расширении устанавливает отказ, базовая конфигурация об этом даже не узнает.
Даже если у пользователя есть базовые права на чтение и изменение справочника, в системе могут быть настроены ограничения прав на уровне записей (Record Level Security — RLS).
Если записываемый элемент содержит реквизиты, конфликтующие с текущей политикой доступа (например, указана организация, подразделение или группа доступа, к которой у данного пользователя нет прав), платформа не позволит совершить запись на уровне базы данных. Это также приведет к генерации общей ошибки записи.
Выясним причину, связанную с методом ПроверитьЗаполнение. Если условие в коде проходит успешно, это означает лишь то, что базовые проверки реквизитов со свойством «Выдавать ошибку» выполнены.
Однако внутри модуля объекта, подписок на события или расширений может быть переопределена процедура ОбработкаПроверкиЗаполнения. Разработчик мог написать логику, которая не генерирует текстовых исключений для пользователя, но тихо устанавливает Отказ = Истина. Это нарушает стандарты разработки, но на практике встречается довольно часто.
Иногда платформа не может записать объект из-за нарушения уникальности в базе данных. Например, дублируется автоматически сгенерированный код, который должен быть уникален в рамках всей базы или в рамках подчинения владельцу. При программной записи без вызова исключений (если используется блок Попытка-Исключение на уровне выше) это замаскируется под базовую ошибку.
Если ваш код выполняется в рамках нестандартных обработок (обмен данными, первоначальная загрузка), внутри модуля справочника может быть заложена логика, блокирующая запись «не из интерфейса». Для обхода таких проверок объекту перед записью принудительно устанавливают свойство ОбменДанными.Загрузка:
НовыйНаселенныйПункт.ОбменДанными.Загрузка = Истина;
НовыйНаселенныйПункт.Записать();
Важно: злоупотреблять установкой этого флага не стоит, так как при этом отключаются проверки бизнес-логики, платформенные проверки уникальности и многие другие механизмы защиты целостности данных.
Если визуальный анализ кода не дал результатов, перейдем к использованию инструментов платформы.
Записать отладчик сам прервется ровно в том месте, где генерируется исключение или скрытый сбой.Записать, выполнить один шаг (F10) и остановить замер, то в полученном дереве вызовов будут видны абсолютно все процедуры и функции. Туда попадут подписки на события, фоновые вызовы и расширения, в которые заходила платформа перед тем, как произошел отказ записи.Комплексно применяя эти подходы, вы сможете быстро локализовать проблему, понять, на каком этапе система блокирует создание объекта, и корректно исправить логику приложения.