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