Как выполнить групповое изменение кодов весового товара в 1С и избежать ошибок уникальности

Программист 1С v8.3 (Обычные формы) 1С:Розница Управленческий учет Торговля и дистрибуция
← На главную

В процессе сопровождения торговых решений на платформе 1С (таких как «1С:Розница» или «1С:Управление торговлей») администраторы и разработчики часто сталкиваются с необходимостью наведения порядка в справочниках и регистрах. Одной из типичных задач является перекодирование весового товара (PLU-кодов). Попытка решить эту задачу простым перебором записей регистра в лоб часто приводит к ошибке: «Значение кода не уникально и запись с такими параметрами уже существует». Даже если в конфигураторе разрядность кода увеличена, система может выдавать ошибку на старых лимитах (например, на значении 99 999).

В этой статье мы подробно разберем, почему возникает данная ошибка, как правильно работать с измерениями регистров сведений и какие безопасные программные методы существуют для массового изменения ключевых полей.

Выясняем причину: почему возникает ошибка уникальности и ограничение в 99 999?

Давайте проанализируем ситуацию, описанную автором темы. Он пытается записать новые шестизначные коды, начинающиеся с пятерки (например, 500000, 500001), но платформа упорно сообщает об ошибке уникальности на коде 99 999. При этом в конфигураторе длина кода весового товара расширена до 10 символов.

Здесь кроются сразу две проблемы:

  1. Ограничение параметров учета в пользовательском режиме. В типовых конфигурациях 1С максимальная длина PLU-кода регулируется не только свойствами метаданных в конфигураторе, но и константами или настройками параметров учета. Например, перейдите по пути: Настройка параметров учета -> вкладка Коды товара -> параметр Длина кода весового товара. Если там установлено значение 5, система при записи программно округлит или обрежет любой ваш новый код (например, 500000) до максимально возможного пятизначного — 99 999. При следующей итерации цикла следующий код тоже превратится в 99 999, что вызовет конфликт уникальности ключа записи.
  2. Попытка изменения измерения «на лету». В регистре сведений КодыВесовогоТовара поле Код является измерением. Измерения составляют уникальный ключ записи. Платформа 1С устроена так, что мы не можем просто прочитать набор записей, поменять значение измерения в цикле и записать набор обратно. Для платформы изменение измерения эквивалентно созданию новой ключевой записи, при этом старая запись никуда не исчезает, вызывая конфликты при записи набора.

Перед тем как приступать к программному изменению кодов, обязательно зайдите в настройки параметров учета вашей информационной базы и увеличьте параметр «Длина кода весового товара» до нужного значения (в нашем случае — 6 или более знаков).

Способ №1: Использование Менеджера Записи (построчный безопасный обход в транзакции)

Давайте рассмотрим первый правильный методологический подход. Поскольку код является измерением регистра, для его изменения нам необходимо сначала удалить старую запись с прежним кодом, а затем создать новую запись с новым кодом. Чтобы гарантировать целостность данных и не потерять информацию в случае сбоя, все действия обязательно нужно выполнять в единой транзакции.

Разберем по шагам алгоритм с использованием объекта РегистрСведенийМенеджерЗаписи:


НачатьТранзакцию();

Попытка
    // Выбираем все текущие записи регистра сведений
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	КодыВесовогоТовара.Номенклатура КАК Номенклатура,
        |	КодыВесовогоТовара.Код КАК Код,
        |	КодыВесовогоТовара.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
        |	КодыВесовогоТовара.Качество КАК Качество
        |ИЗ
        |	РегистрСведений.КодыВесовогоТовара КАК КодыВесовогоТовара";
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    НовыйНомер = 500000;
    
    Пока Выборка.Следующий() Цикл
        
        // 1. Удаляем старую запись
        МенеджерЗаписиСтарый = РегистрыСведений.КодыВесовогоТовара.СоздатьМенеджерЗаписи();
        МенеджерЗаписиСтарый.Код = Выборка.Код; // Передаем старое измерение
        МенеджерЗаписиСтарый.Прочитать();
        
        Если МенеджерЗаписиСтарый.Выбран() Тогда
            // Сохраняем значения ресурсов во временные переменные
            ТекущаяНоменклатура = МенеджерЗаписиСтарый.Номенклатура;
            ТекущаяХарактеристика = МенеджерЗаписиСтарый.ХарактеристикаНоменклатуры;
            ТекущееКачество = МенеджерЗаписиСтарый.Качество;
            
            // Удаляем старую ключевую запись
            МенеджерЗаписиСтарый.Удалить();
        Иначе
            Продолжить;
        КонецЕсли;
        
        // 2. Создаем новую запись с новым измерением
        МенеджерЗаписиНовый = РегистрыСведений.КодыВесовогоТовара.СоздатьМенеджерЗаписи();
        МенеджерЗаписиНовый.Код = НовыйНомер; // Устанавливаем новое измерение
        
        // Заполняем ресурсы сохраненными данными
        МенеджерЗаписиНовый.Номенклатура = ТекущаяНоменклатура;
        МенеджерЗаписиНовый.ХарактеристикаНоменклатуры = ТекущаяХарактеристика;
        МенеджерЗаписиНовый.Качество = ТекущееКачество;
        
        // Записываем новую строку
        МенеджерЗаписиНовый.Записать();
        
        НовыйНомер = НовыйНомер + 1;
        
    КонецЦикла;
    
    ЗафиксироватьТранзакцию();
    Сообщить("Перекодирование весовых товаров успешно завершено!");
    
Исключение
    ОтменитьТранзакцию();
    Сообщить("Произошла ошибка при изменении кодов: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;

Этот метод гарантирует, что если на каком-то шаге (например, на 5000-й записи) произойдет системная ошибка, транзакция полностью откатится, и все коды весовых товаров вернутся в исходное состояние. База данных не останется в разрушенном или частично измененном виде.

Способ №2: Пакетный метод через Таблицу Значений (для высокой производительности)

Если в вашем регистре содержатся десятки тысяч записей, построчный метод через МенеджерЗаписи может работать достаточно медленно из-за большого количества обращений к базе данных. В этом случае мы можем применить пакетный метод: выгрузить все записи в Таблицу Значений (ТЗ), модифицировать их в памяти компьютера, полностью очистить регистр одним движением и загрузить новые данные.

Важное предупреждение: Метод очистки регистра с последующей записью несет в себе риски. Если очистка пройдет успешно, а на этапе записи новых данных возникнет непредвиденная ошибка (например, аварийно завершится служба СУБД или пропадет электропитание сервера), регистр останется пустым. Поэтому данный код также критически важно выполнять внутри транзакции и блока обработки исключений.

Давайте проанализируем и реализуем этот алгоритм:


НачатьТранзакцию();

Попытка
    // Шаг 1. Создаем набор записей для чтения всей информации из регистра
    НаборЗаписей = РегистрыСведений.КодыВесовогоТовара.СоздатьНаборЗаписей();
    НаборЗаписей.Прочитать();
    
    // Шаг 2. Выгружаем данные в Таблицу Значений
    ТаблицаДанных = НаборЗаписей.Выгрузить();
    
    // Шаг 3. Модифицируем измерения в Таблице Значений
    НовыйНомер = 500000;
    Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
        СтрокаДанных.Код = НовыйНомер;
        НовыйНомер = НовыйНомер + 1;
    КонецЦикла;
    
    // Шаг 4. Полностью очищаем регистр сведений
    НаборОчистки = РегистрыСведений.КодыВесовогоТовара.СоздатьНаборЗаписей();
    // Запись пустого набора без отборов очищает всю таблицу регистра в БД
    НаборОчистки.Записать(); 
    
    // Шаг 5. Загружаем измененную таблицу данных обратно в регистр
    НаборЗагрузки = РегистрыСведений.КодыВесовогоТовара.СоздатьНаборЗаписей();
    НаборЗагрузки.Загрузить(ТаблицаДанных);
    НаборЗагрузки.Записать();
    
    ЗафиксироватьТранзакцию();
    Сообщить("Данные успешно обновлены пакетным методом!");
    
Исключение
    ОтменитьТранзакцию();
    Сообщить("Ошибка выполнения пакета. Регистр восстановлен в исходное состояние. Описание: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;

Что нужно сделать после изменения кодов в 1С? (Важные нюансы)

Просто обновить цифры в базе данных 1С недостаточно для восстановления корректной работы розничного магазина. Весовые товары имеют тесную связь с торговым оборудованием. Давайте разберем, какие шаги обязательно нужно выполнить после проведения групповой обработки кодов:

  1. Синхронизация и выгрузка на весы (Offline). Весы с печатью этикеток хранят внутреннюю память соответствия кодов PLU и товаров. После изменения кодов в 1С старые коды на весах перестанут совпадать с базой. Необходимо запустить полную очистку памяти весов во всех торговых точках и выполнить повторную полную выгрузку товаров на весы через стандартные обработки обслуживания торгового оборудования.
  2. Обновление и перегенерация штрихкодов. Во многих конфигурациях штрихкод весового товара формируется динамически по маске (например, 21XXXXXYYYYYК, где 21 — префикс весового товара, XXXXX — пятизначный код PLU, а YYYYY — вес товара). Если вы изменили разрядность кода с 5 до 6 знаков (сделав его 500000), вам необходимо проверить и перенастроить правила (шаблоны) формирования весовых штрихкодов в настройках программы. В противном случае кассовые аппараты и сканеры не смогут корректно декодировать считанный штрихкод при продаже на кассе.
  3. Обмен данными в РИБ. Если ваше предприятие работает по схеме распределенных информационных баз (РИБ), массовое изменение 7000 записей регистра сведений приведет к генерации огромного объема зарегистрированных изменений для узлов обмена. Настоятельно рекомендуем выполнять данную процедуру в конце рабочего дня или в выходные, чтобы файлы обмена РИБ успели мигрировать на периферийные базы и кассовые узлы без создания избыточной нагрузки на каналы связи в пиковые часы продаж.
← На главную