При настройке правил обмена в конфигурации «Конвертация данных 2.0» для переноса справочника номенклатуры из «Бухгалтерии предприятия 3.0» в «Комплексную автоматизацию 1.1» разработчики часто сталкиваются с несоответствием структуры метаданных. В БП 3.0 реквизит ЕдиницаИзмерения ссылается на общий классификатор, а в КА 1.1 учет разделен: реквизит БазоваяЕдиницаИзмерения связан с классификатором, а ЕдиницаХраненияОстатков и ЕдиницаДляОтчетов ссылаются на подчиненный справочник ЕдиницыИзмерения. В результате стандартной загрузки эти реквизиты остаются пустыми. Разберем по шагам, почему возникает эта проблема, как программно создать единицы измерения в правилах обмена и как устранить ошибку неуникального кода.
Выясним причину, почему типовые механизмы не заполняют единицы измерения автоматически при обмене данными:
СправочникСсылка.ЕдиницыИзмерения, владельцем которого обязательно выступает конкретная позиция номенклатуры.ОбменДанными.Загрузка = Истина, из-за чего события форм не срабатывают.Ошибка при вызове метода контекста (Записать): Значение "999" поля "Код" не уникально. Это происходит из-за появления в базе элементов с кодами максимальной числовой длины или со скрытыми хвостовыми пробелами, что сбивает встроенный платформенный автонумератор.Рассмотрим основной способ решения задачи непосредственно в конфигурации «Конвертация данных 2.0». Для правила конвертации объекта (ПКО) «Номенклатура» необходимо задействовать обработчик события ПослеЗагрузки. В этом обработчике ссылка на номенклатуру уже существует или может быть получена, что позволяет корректно указать владельца подчиненного элемента.
Посмотрим на пример программного кода, который решает задачу создания и привязки единиц измерения:
Если Не Объект.ЭтоГруппа Тогда
// Проверяем наличие базовой единицы классификатора
Если ЗначениеЗаполнено(Объект.БазоваяЕдиницаИзмерения) Тогда
// Обеспечиваем получение ссылки для нового элемента
Если Объект.ЭтоНовый() Тогда
Объект.УстановитьСсылкуНового(Объект.ПолучитьСсылкуНового());
КонецЕсли;
СсылкаНаОбъект = Объект.Ссылка;
// Поиск уже существующей единицы по владельцу и классификатору
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Единицы.Ссылка КАК Ссылка
|ИЗ
| Справочник.ЕдиницыИзмерения КАК Единицы
|ГДЕ
| Единицы.Владелец = &Владелец
| И Единицы.ЕдиницаПоКлассификатору = &Классификатор";
Запрос.УстановитьПараметр("Владелец", СсылкаНаОбъект);
Запрос.УстановитьПараметр("Классификатор", Объект.БазоваяЕдиницаИзмерения);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
// Создаем подчиненную единицу измерения
НоваяЕдиница = Справочники.ЕдиницыИзмерения.СоздатьЭлемент();
НоваяЕдиница.Владелец = СсылкаНаОбъект;
НоваяЕдиница.ЕдиницаПоКлассификатору = Объект.БазоваяЕдиницаИзмерения;
НоваяЕдиница.Коэффициент = 1;
НоваяЕдиница.Наименование = СокрЛП(Объект.БазоваяЕдиницаИзмерения.Наименование);
// Отключаем проверки нумератора при записи подчиненной единицы
НоваяЕдиница.ОбменДанными.Загрузка = Истина;
НоваяЕдиница.Записать();
СсылкаНаЕдиницу = НоваяЕдиница.Ссылка;
Иначе
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
СсылкаНаЕдиницу = Выборка.Ссылка;
КонецЕсли;
// Заполняем реквизиты номенклатуры
Если НЕ ЗначениеЗаполнено(Объект.ЕдиницаХраненияОстатков) Тогда
Объект.ЕдиницаХраненияОстатков = СсылкаНаЕдиницу;
КонецЕсли;
Если НЕ ЗначениеЗаполнено(Объект.ЕдиницаДляОтчетов) Тогда
Объект.ЕдиницаДляОтчетов = СсылкаНаЕдиницу;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Обратите внимание: при обращении к свойствам загружаемого объекта в контексте обработчиков КД обязательно нужно указывать префикс Объект. (например, Объект.ЭтоГруппа, Объект.БазоваяЕдиницаИзмерения), так как переменные модуля объекта напрямую в контексте обработчика КД недоступны.
Проанализируем ситуацию с ошибкой Значение "999" поля "Код" не уникально. Если в справочнике ЕдиницыИзмерения длина кода мала (например, 3 символа) или был записан элемент с неформатированным кодом без ведущих нулей (например, строка "999" вместо "000000999"), механизм автонумерации платформы 1С блокирует создание новых строк.
Разберем по шагам порядок исправления нумерации:
ЕдиницыИзмерения, чтобы найти элементы, код которых оканчивается на «999» или содержит максимальное числовое значение с пробелами в конце."000000001").НоваяЕдиница.ОбменДанными.Загрузка = Истина; перед вызовом Записать(). Это временно отключает встроенный контроль уникальности номеров платформой.Если правила конвертации уже отработали, а номенклатура перенесена с пустыми единицами хранения остатков, не обязательно выполнять повторную выгрузку из БП 3.0. Достаточно запустить внешнюю обработку непосредственно в базе «Комплексная автоматизация 1.1».
Посмотрим на пример кода для группового заполнения единиц в уже загруженных данных:
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
Если НЕ ЗначениеЗаполнено(Выборка.ЕдиницаХраненияОстатков)
И ЗначениеЗаполнено(Выборка.БазоваяЕдиницаИзмерения) Тогда
ОбъектНоменклатура = Выборка.ПолучитьОбъект();
// Создаем подчиненный элемент единицы
НоваяЕдиница = Справочники.ЕдиницыИзмерения.СоздатьЭлемент();
НоваяЕдиница.Владелец = ОбъектНоменклатура.Ссылка;
НоваяЕдиница.ЕдиницаПоКлассификатору = ОбъектНоменклатура.БазоваяЕдиницаИзмерения;
НоваяЕдиница.Коэффициент = 1;
НоваяЕдиница.Наименование = СокрЛП(ОбъектНоменклатура.БазоваяЕдиницаИзмерения.Наименование);
НоваяЕдиница.ОбменДанными.Загрузка = Истина;
НоваяЕдиница.Записать();
// Привязываем реквизиты и сохраняем без лишних проверок формы
ОбъектНоменклатура.ЕдиницаХраненияОстатков = НоваяЕдиница.Ссылка;
ОбъектНоменклатура.ЕдиницаДляОтчетов = НоваяЕдиница.Ссылка;
ОбъектНоменклатура.ОбменДанными.Загрузка = Истина;
ОбъектНоменклатура.Записать();
КонецЕсли;
КонецЦикла;
Важный момент: использование флага ОбменДанными.Загрузка = Истина как для подчиненного справочника, так и для самой номенклатуры позволяет избежать падения транзакции из-за проверок прав доступа, заполненности ставок НДС или других регламентных ограничений конфигурации КА 1.1.