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