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