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