В процессе разработки в конфигурациях на базе обычных форм, таких как Управление торговлей 10.3 или Управление производственным предприятием 1.3, программисты часто сталкиваются с проблемой: метод ЭтоНовый() перестает работать так, как ожидается, в момент записи элемента номенклатуры. Особенно остро это проявляется, когда пользователю нужно создать единицы измерения (хранения остатков или отчетов) до того, как карточка будет окончательно заполнена и сохранена.
Разберем ситуацию подробно: для того чтобы создать подчиненный справочник (в данном случае ЕдиницыИзмерения), основному объекту (Номенклатура) уже должна быть присвоена ссылка в базе данных. Типовой механизм 1С принудительно записывает объект, чтобы получить эту ссылку. В результате проверка ЭтоНовый() в модуле объекта при последующих нажатиях кнопки "ОК" или "Записать" всегда возвращает Ложь. Давайте проанализируем, как можно обойти это ограничение и корректно реализовать проверку обязательных реквизитов.
Проанализируем механику работы типовой формы номенклатуры. Когда пользователь нажимает на кнопку выбора единицы измерения в еще не записанной карточке, система вызывает функцию из общего модуля (например, РаботаСДиалогами.ЗаписатьОбъектИСоздатьЕдиницыИзмерения). Внутри этого процесса происходит вызов ЭтотОбъект.Записать().
После этого действия:
ЭтоНовый() во всех последующих событиях будет возвращать Ложь.Если мы хотим запретить запись без заполнения, например, реквизита "Статья затрат" или "Номенклатурная группа", обычный код в модуле объекта заблокирует и ту самую "техническую" запись, которая необходима для создания единиц измерения. В итоге пользователь попадет в замкнутый круг: он не может создать единицы без записи, и не может записать объект без единиц.
Рассмотрим самый надежный программный способ разделения "технической" записи и "финального" сохранения пользователем. Для этого мы воспользуемся коллекцией ДополнительныеСвойства. Это структура, которая живет вместе с экземпляром объекта в памяти, но не записывается в базу данных.
Посмотрим на пример реализации в модуле формы номенклатуры. Перед тем как инициировать запись для создания единиц, мы можем установить специальный флаг:
Процедура ПриНажатииКнопкиВыбораЕдиницы()
ЭтотОбъект.ДополнительныеСвойства.Вставить("ПрограммнаяЗаписьДляЕдиниц", Истина);
// Вызов типового механизма записи
Если Не ЭтотОбъект.Записать() Тогда
Возврат;
КонецЕсли;
// ... логика открытия формы выбора единиц ...
КонецПроцедуры
Теперь проанализируем изменения, которые необходимо внести в модуль объекта номенклатуры в обработчик ПередЗаписью:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Если установлен флаг программной записи, пропускаем жесткие проверки
Если ДополнительныеСвойства.Свойство("ПрограммнаяЗаписьДляЕдиниц")
И ДополнительныеСвойства.ПрограммнаяЗаписьДляЕдиниц = Истина Тогда
Возврат;
КонецЕсли;
// Стандартная проверка, если объект уже не новый
Если Не ЭтоНовый() Тогда
Если Не ЗначениеЗаполнено(НужныйРеквизит) Тогда
Сообщить("Для сохранения номенклатуры необходимо заполнить реквизит!");
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В типовых конфигурациях УТ 10.3 и УПП 1.3 разработчики 1С уже предусмотрели механизм отслеживания состояния "новизны" карточки на уровне формы. В модуле формы часто встречается переменная мЭтоНовыйОбъект. Она инициализируется при открытии формы (если ссылка пустая) и сохраняет значение Истина до тех пор, пока пользователь не закроет форму или успешно не выполнит основное сохранение.
Выясним причину, почему это удобно: даже если объект был технически записан в базу для создания единиц измерения, флаг мЭтоНовыйОбъект в форме все еще будет равен Истина. Мы можем использовать это в событии формы ПередЗаписью:
Процедура ПередЗаписью(Отказ)
// Проверяем, считается ли объект новым в контексте текущего сеанса редактирования
Если мЭтоНовыйОбъект И Не ЗначениеЗаполнено(НужныйРеквизит) Тогда
// Здесь мы можем решить: выдавать ошибку или просто предупреждение
ТекстВопроса = "Не заполнен важный реквизит. Все равно продолжить?";
Если Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Нет Тогда
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Рассмотрим ситуацию, когда жесткий запрет в модуле объекта (Отказ = Истина) может привести к появлению "мусорных" данных. Как отметили участники обсуждения, если мы разрешим техническую запись, но пользователь потом просто закроет форму, в базе останется "недозаполненный" элемент с уже созданными единицами измерения.
Чтобы избежать этого, опытные разработчики рекомендуют:
Подведем итоги нашего анализа. Если ваша задача — гарантировать заполнение реквизита именно после того, как были созданы единицы измерения, но до того, как карточка считается "готовой", наиболее правильным путем будет использование комбинации ДополнительныхСвойств и проверки в форме.
Важный момент: Помните, что в обычных формах 1С 8.3/8.2 работа внутри транзакции ограничена. Как только программная запись прошла успешно, объект уже в базе. Поэтому вместо жесткого блокирования в ПередЗаписью модуля объекта (которое может сломать типовые механизмы), лучше использовать проверку в модуле формы перед закрытием или интерактивные сообщения, которые не дают пользователю забыть о заполнении полей.
Используя предложенные методы, вы сможете настроить гибкую логику контроля данных, сохранив при этом работоспособность стандартных функций конфигурации.