При массовой загрузке данных в конфигурацию «Управление торговлей 10.3», особенно при использовании внешних обработок с диска ИТС, часто возникает ситуация, когда справочник Номенклатура заполняется корректно, а сопутствующие регистры — лишь частично. Одной из наиболее распространенных проблем является отсутствие привязки штрихкода к единице измерения в регистре сведений Штрихкоды.
В этой статье мы подробно разберем, почему возникает эта ошибка, проанализируем структуру регистра и разработаем надежный алгоритм для восстановления данных, который позволит избежать ручного исправления тысяч записей.
Прежде чем приступать к написанию кода, давайте проанализируем, как устроен регистр сведений Штрихкоды в УТ 10.3. Это независимый и непериодический регистр. Его ключевая особенность заключается в том, что поле ЕдиницаИзмерения является не ресурсом, а измерением.
Почему это критически важно: В платформе 1С:Предприятие 8 изменение значения измерения в существующей записи невозможно. С точки зрения базы данных, комбинация всех измерений — это уникальный ключ записи. Если мы хотим «поменять» единицу измерения, нам технически нужно удалить старую запись с пустым значением и создать новую с заполненным.
Рассмотрим основные ошибки, с которыми сталкиваются разработчики при попытке автоматического исправления:
Владелец, которое имеет составной тип (СправочникСсылка.Номенклатура или СправочникСсылка.СерииНоменклатуры). Обращение зап.Номенклатура вызывает ошибку, так как такого поля в метаданных нет.Перед внесением изменений в базу данных, нам необходимо точно определить масштаб проблемы. Для этого воспользуемся консолью запросов. Выясним, у каких записей не заполнена единица измерения и есть ли у соответствующей номенклатуры ЕдиницаХраненияОстатков, которую мы планируем подставить.
ВЫБРАТЬ
Штрихкоды.ТипШтрихкода,
Штрихкоды.Штрихкод,
Штрихкоды.Владелец КАК НоменклатураСсылка,
Штрихкоды.Владелец.ЕдиницаХраненияОстатков КАК НужнаяЕдиница
ИЗ
РегистрСведений.Штрихкоды КАК Штрихкоды
ГДЕ
Штрихкоды.ЕдиницаИзмерения = ЗНАЧЕНИЕ(Справочник.ЕдиницыИзмерения.ПустаяСсылка)
И Штрихкоды.Владелец ССЫЛКА Справочник.Номенклатура
Проанализируем результат запроса. Если поле НужнаяЕдиница заполнено, мы можем приступать к обработке. Если же оно пустое, значит, проблема глубже: у номенклатуры не заданы базовые единицы измерения, и сначала нужно исправить справочник Номенклатура.
Если записей немного (до пары тысяч), можно воспользоваться простым кодом, который исправляет значения «на лету». Однако помните о замечании про измерения: чтобы запись обновилась корректно, лучше использовать метод полной замены или частичного удаления.
Рассмотрим исправленный код, который обсуждался в сообщении №8 темы форума:
Процедура ИсправитьШтрихкодыНабором()
нз = РегистрыСведений.Штрихкоды.СоздатьНаборЗаписей();
// Внимание: чтение всего регистра без отбора может занять много памяти!
нз.Прочитать();
Для каждого зап Из нз Цикл
Если зап.ЕдиницаИзмерения.Пустая() Тогда
// Проверяем, что владелец — это номенклатура
Если ТипЗнч(зап.Владелец) = Тип("СправочникСсылка.Номенклатура") Тогда
зап.ЕдиницаИзмерения = зап.Владелец.ЕдиницаХраненияОстатков;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Попытка
нз.Записать();
Сообщить("Данные успешно обновлены");
Исключение
Сообщить("Ошибка при записи: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Для объема в 11 000 строк, как у автора вопроса, чтение всего регистра в память — не лучшая идея. Проанализируем более профессиональный подход: постраничная обработка или использование менеджера записи. Поскольку ЕдиницаИзмерения — это измерение, нам нужно удалить старую запись (с пустой единицей) и создать новую.
Разберем алгоритм по шагам:
Выборка = РегистрыСведений.Штрихкоды.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ЕдиницаИзмерения.Пустая() Тогда
// Получаем правильную единицу из владельца
ТекЕдиница = Выборка.Владелец.ЕдиницаХраненияОстатков;
Если ТекЕдиница.Пустая() Тогда
Продолжить; // Пропускаем, если у товара нет единицы хранения
КонецЕсли;
// Создаем менеджер записи для удаления старой записи
МЗ_Старый = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(МЗ_Старый, Выборка);
МЗ_Старый.Прочитать();
Если МЗ_Старый.Выбран() Тогда
МЗ_Старый.Удалить();
КонецЕсли;
// Создаем менеджер записи для новой записи
МЗ_Новый = РегистрыСведений.Штрихкоды.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(МЗ_Новый, Выборка);
МЗ_Новый.ЕдиницаИзмерения = ТекЕдиница;
МЗ_Новый.Записать();
КонецЕсли;
КонецЦикла;
Проанализируем возможные побочные эффекты. В УТ 10.3 штрихкоды могут быть привязаны не только к номенклатуре, но и к характеристикам. Если в вашей базе ведется учет по характеристикам, обязательно убедитесь, что при перезаписи поле ХарактеристикаНоменклатуры не очищается. В приведенном выше коде использование ЗаполнитьЗначенияСвойств помогает сохранить все измерения.
Транзакции и безопасность:
ЗафиксироватьТранзакцию() каждые 500-1000 итераций, чтобы не переполнять лог транзакций и не блокировать таблицу для других пользователей на долгое время.ЕдиницыИзмерения для каждой номенклатуры содержит именно ту запись, которая является «Единицей хранения остатков». В УТ 10.3 это часто путают с «Базовой единицей» (из классификатора ОКЕИ). Штрихкод в РС всегда должен ссылаться на подчиненный справочник ЕдиницыИзмерения.Рассмотрим ситуацию с ошибкой «Штрихкод уже имеет владельца». Она часто возникает, если вы пытаетесь присвоить единицу измерения, которая уже занята другим штрихкодом. В этом случае перед записью стоит добавить проверку на существование аналогичной записи в регистре, чтобы избежать прерывания работы обработки.
Используя предложенные методы, вы сможете быстро и корректно восстановить целостность данных в регистре штрихкодов, обеспечив правильную работу сканеров штрихкодов и терминалов сбора данных в вашей системе.