В этой статье мы подробно разберем ситуацию, с которой сталкиваются пользователи и администраторы конфигурации "1С:Бухгалтерия предприятия" (редакция 3.0). Проблема проявляется следующим образом: в карточке организации перестает сохраняться поле E-mail (или другие виды контактной информации). Значение вводится, но после записи и повторного открытия поле оказывается пустым. При этом в справочнике "Виды контактной информации" нужный элемент может отсутствовать визуально, но существовать в конфигураторе.
Мы проанализируем причины этого поведения, изучим структуру хранения БД, и рассмотрим пошаговые методы восстановления корректной работы базы данных.
Чаще всего проблема обнаруживается случайно: пользователи жалуются, что не могут сохранить адрес электронной почты. При техническом анализе выясняется следующее:
ВидыКонтактнойИнформации отсутствует элемент "Email".Основная причина: На версиях платформы 8.3.24 (особенно ранних сборках) была зафиксирована ошибка, возникающая после реструктуризации или ТиИ при наличии расширений. В результате теряется связь между предопределенным элементом в метаданных (конфигурации) и реальной записью в таблице базы данных. Поле ИмяПредопределенныхДанных у существующего элемента может "слететь" или элемент может быть помечен как непредопределенный, хотя его имя занято.
Прежде чем приступать к лечению, давайте убедимся, что мы имеем дело именно с потерей связи предопределенного элемента. Для этого воспользуемся консолью запросов или внешней обработкой. Нам нужно посмотреть, есть ли в базе элементы, которые "держат" системное имя, но не видны или испорчены.
Выполним следующий запрос:
ВЫБРАТЬ
ВидыКИ.Ссылка,
ВидыКИ.Наименование,
ВидыКИ.ПометкаУдаления,
ВидыКИ.Предопределенный,
ВидыКИ.ИмяПредопределенныхДанных
ИЗ
Справочник.ВидыКонтактнойИнформации КАК ВидыКИ
ГДЕ
ВидыКИ.ИмяПредопределенныхДанных ПОДОБНО "%Email%"
Если запрос вернет запись, обратите внимание на колонку Предопределенный. Если там стоит Ложь, но поле ИмяПредопределенныхДанных заполнено — это и есть наш "виновник". Система не дает создать новый правильный элемент или привязать существующий, так как имя уже занято.
Это наиболее быстрый и безопасный способ, не требующий выгрузки базы. Нам нужно найти элемент, который ошибочно занимает имя предопределенных данных, освободить это имя, а затем присвоить его нужному (или новому) элементу.
Многие пытаются просто присвоить имя нужному элементу и получают ошибку: "Предопределенный элемент не уникален". Это происходит именно потому, что где-то в базе (возможно, среди удаленных) есть дубль, требующий чистки и восстановления целостности.
Давайте напишем алгоритм исправления. Этот код можно выполнить в обработке "Групповое изменение реквизитов" (в режиме "Выполнить произвольный алгоритм") или в простейшей внешней обработке.
Шаг 1. Освобождаем имя (если мешает помеченный объект, предварительно выполните удаление помеченных объектов с отбором)
// Ищем элемент, который сейчас занимает нужное имя
// В БП 3.0 для Email организации имя обычно "EmailОрганизации"
ИскомоеИмя = "EmailОрганизации";
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВидыКИ.Ссылка
|ИЗ
| Справочник.ВидыКонтактнойИнформации КАК ВидыКИ
|ГДЕ
| ВидыКИ.ИмяПредопределенныхДанных = &Имя";
Запрос.УстановитьПараметр("Имя", ИскомоеИмя);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
// Получаем объект, чтобы изменить его
БлокирующийЭлемент = Выборка.Ссылка.ПолучитьОбъект();
// Очищаем имя, освобождая его для правильного элемента
БлокирующийЭлемент.ИмяПредопределенныхДанных = "";
// Пытаемся записать. Если элемент помечен на удаление или испорчен,
// запись может пройти успешно, освободив имя.
Попытка
БлокирующийЭлемент.Записать();
Сообщить("Имя освобождено у элемента: " + БлокирующийЭлемент.Наименование);
Исключение
Сообщить("Не удалось очистить имя: " + ОписаниеОшибки());
КонецПопытки;
Иначе
Сообщить("Элемент с таким именем предопределенных данных не найден. Можно создавать новый.");
КонецЕсли;
Шаг 2. Назначаем имя правильному элементу
После того как мы освободили имя, нужно найти "правильный" элемент (тот, который вы используете, или создать новый, если его нет) и привязать его к конфигурации.
// Находим элемент, который должен стать предопределенным
// Лучше искать по наименованию или создать новый
ИскомоеИмя = "EmailОрганизации";
НашеНазвание = "Email"; // Как он называется у вас в базе
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ВидыКИ.Ссылка
|ИЗ
| Справочник.ВидыКонтактнойИнформации КАК ВидыКИ
|ГДЕ
| ВидыКИ.Наименование = &Название
| И ВидыКИ.ИмяПредопределенныхДанных = """""; // Ищем тот, который еще не привязан
Запрос.УстановитьПараметр("Название", НашеНазвание);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ПравильныйЭлемент = Выборка.Ссылка.ПолучитьОбъект();
ПравильныйЭлемент.ИмяПредопределенныхДанных = ИскомоеИмя;
Попытка
ПравильныйЭлемент.Записать();
Сообщить("Связь восстановлена успешно!");
Исключение
Сообщить("Ошибка при связывании: " + ОписаниеОшибки());
КонецПопытки;
Иначе
// Если элемента нет, создаем новый
НовыйЭлемент = Справочники.ВидыКонтактнойИнформации.СоздатьЭлемент();
НовыйЭлемент.Наименование = НашеНазвание;
// Заполните остальные обязательные реквизиты (Тип, Вид и т.д.) согласно логике БП
НовыйЭлемент.Тип = Перечисления.ТипыКонтактнойИнформации.АдресЭлектроннойПочты;
НовыйЭлемент.ВидОбъектаКонтактнойИнформации = Перечисления.ВидыОбъектовКонтактнойИнформации.Организации; // Пример
НовыйЭлемент.ИмяПредопределенныхДанных = ИскомоеИмя;
Попытка
НовыйЭлемент.Записать();
Сообщить("Создан новый предопределенный элемент.");
Исключение
Сообщить("Ошибка создания: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
Если программный метод вызывает затруднения или база сильно повреждена, можно воспользоваться методом прямой подмены данных через XML, как это сделал автор темы. Этот метод требует наличия резервной копии или "здоровой" базы с аналогичной конфигурацией.
Разберем алгоритм действий:
ВидыКонтактнойИнформации в файл.PredefinedDataName с файлом из "здоровой" базы.Ref (Уникальный Идентификатор) совпадал с тем элементом, который реально используется у вас в регистрах сведений (где хранятся сами e-mail адреса), но добавьте ему правильное PredefinedDataName.Важно: Этот метод рискованный, так как можно создать дубликаты ключей или нарушить ссылочную целостность, если вы ошибетесь с GUID (Уникальным идентификатором). Всегда делайте бэкап перед загрузкой!
Иногда помогает штатный механизм обновления вспомогательных данных БСП (Библиотеки стандартных подсистем). Если элемент просто отсутствует (удален), а не "завис" в полуразрушенном состоянии, система может создать его сама при обновлении.
Для принудительного запуска процедур начального заполнения можно запустить 1С с ключом запуска:
/C ЗапуститьОбновлениеИнформационнойБазы
Это заставит программу выполнить отложенные обработчики, которые проверяют наличие предопределенных элементов и создают их при отсутствии. Однако, если у вас случай с "фантомным" занятым именем (как описано в Способе 1), этот метод вернет ошибку или не сработает, пока вы не освободите имя вручную.
Исходя из опыта обсуждения проблемы, основной причиной является ошибка платформы 8.3.24 при проведении "Тестирования и исправления" на базах с расширениями. Чтобы избежать повторения ситуации: