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