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