При работе с маркировкой товаров в современных конфигурациях 1С (ERP, КА, УТ 11) программисты часто сталкиваются с необходимостью автоматизировать создание упаковок — палет или коробов (а пользователям часто требуются дополнительные колонки со штрихкодами в справочнике номенклатуры). Типовой справочник ШтрихкодыУпаковокТоваров имеет сложную внутреннюю логику, из-за которой данные, видимые в отладчике перед записью, могут бесследно исчезнуть или обнулиться после выполнения метода Записать(). В этой статье мы подробно разберем, как правильно наполнять этот справочник программно (что актуально, например, при загрузке штрихкодов из StoreHouse), почему очищается реквизит Количество и как работать с вложенными структурами данных.
Рассмотрим ситуацию, когда разработчик пытается создать элемент справочника и заполнить его табличную часть ВложенныеШтрихкоды строковыми значениями QR-кодов (DataMatrix). На первый взгляд код выглядит логично: создается объект (или выполняется загрузка кодов маркировки из XML), заполняются основные реквизиты, добавляются строки в таблицу. Однако после записи поле Количество становится равным нулю, а табличная часть пустой. Выясним причину этого поведения.
Основная ошибка заключается в несоответствии типов данных. В справочнике ШтрихкодыУпаковокТоваров табличная часть ВложенныеШтрихкоды содержит реквизит Штрихкод, который имеет тип СправочникСсылка.ШтрихкодыУпаковокТоваров. Это означает, что справочник ссылается сам на себя (рекурсивная структура). Если мы попытаемся записать туда строку с кодом маркировки вместо ссылки на уже существующий элемент этого же справочника, 1С не сможет сопоставить типы и фактически оставит поле пустым.
Вторая важная причина — работа типового обработчика ПередЗаписью. В модуле объекта этого справочника прописана жесткая логика пересчета итогов. Давайте проанализируем, что происходит внутри системы при вызове метода записи.
В типовых решениях процедура ПередЗаписью выполняет автоматический расчет многих полей. Посмотрим на фрагмент кода, который отвечает за это:
Процедура ПередЗаписью(Отказ)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
Если Не (ДополнительныеСвойства.Свойство("НеРассчитыватьКоличествоВложенныхШтрихкодов") И ДополнительныеСвойства.НеРассчитыватьКоличествоВложенныхШтрихкодов) Тогда
РассчитатьКоличествоВложенныхШтрихкодов;
КонецЕсли;
// ... расчет хеш-сумм и заполнение служебных полей
КонецПроцедуры
Обратите внимание на вызов процедуры РассчитатьКоличествоВложенныхШтрихкодов. Система игнорирует то значение, которое вы установили в реквизит Количество вручную в коде. Она берет данные из табличной части вложенных штрихкодов, проверяет их наличие в базе данных, определяет их тип и заново вычисляет итоговое количество. Если табличная часть заполнена неверно (строками вместо ссылок) или вложенные элементы еще не записаны в базу, функция вернет 0, который и будет записан в объект.
Для того чтобы данные корректно сохранились, необходимо соблюдать строгую последовательность действий. Представим, что нам нужно создать «Палет», внутри которого находятся две «Коробки» (или две единицы продукции) — для этого подойдёт автоматическая агрегация КИТУ и SSCC в 1С. Правильный алгоритм действий (который также стоит учитывать, если вы реализуете перенос штрихкодов и упаковок между номенклатурой) будет выглядеть следующим образом:
Ссылка).ВложенныеШтрихкоды палета мы добавляем именно ссылки, полученные на шаге 2.РассчитатьКоличествоВложенныхШтрихкодов увидит в базе вложенные ссылки и корректно посчитает итоговое количество.Посмотрим на пример кода, реализующий этот подход:
// 1. Создаем первый вложенный код (например, потребительскую упаковку)
ЭлементВложенный1 = Справочники.ШтрихкодыУпаковокТоваров.СоздатьЭлемент();
ЭлементВложенный1.ЗначениеШтрихкода = "КодМаркировки1...";
ЭлементВложенный1.ТипУпаковки = Перечисления.ТипыУпаковок.МаркированныйТовар;
ЭлементВложенный1.Номенклатура = СсылкаНоменклатура;
ЭлементВложенный1.Записать();
// 2. Создаем второй вложенный код
ЭлементВложенный2 = Справочники.ШтрихкодыУпаковокТоваров.СоздатьЭлемент();
ЭлементВложенный2.ЗначениеШтрихкода = "КодМаркировки2...";
ЭлементВложенный2.ТипУпаковки = Перечисления.ТипыУпаковок.МаркированныйТовар;
ЭлементВложенный2.Номенклатура = СсылкаНоменклатура;
ЭлементВложенный2.Записать();
// 3. Создаем общую упаковку (Палет)
НовыйПалет = Справочники.ШтрихкодыУпаковокТоваров.СоздатьЭлемент();
НовыйПалет.ЗначениеШтрихкода = "КодПалета...";
НовыйПалет.ТипУпаковки = Перечисления.ТипыУпаковок.МонотоварнаяУпаковка;
НовыйПалет.Номенклатура = СсылкаНоменклатура;
// Добавляем в ТЧ ссылки на созданные ранее элементы
НоваяСтрока = НовыйПалет.ВложенныеШтрихкоды.Добавить();
НоваяСтрока.Штрихкод = ЭлементВложенный1.Ссылка;
НоваяСтрока = НовыйПалет.ВложенныеШтрихкоды.Добавить();
НоваяСтрока.Штрихкод = ЭлементВложенный2.Ссылка;
// Записываем палет. Теперь Количество заполнится автоматически как 2.
НовыйПалет.Записать();
Если в вашей специфической задаче автоматический расчет 1С работает некорректно (например, при сложной агрегации, данные о которой еще не полностью переданы в ГИС МТ), вы можете «обмануть» систему — упростить обмен поможет готовый модуль обмена с Честным Знаком. Для этого используется механизм ДополнительныеСвойства.
Ранее мы видели в коде ПередЗаписью проверку флага НеРассчитыватьКоличествоВложенныхШтрихкодов. Мы можем установить его программно перед вызовом Записать(). В этом случае 1С примет ваше значение реквизита Количество «как есть» и не будет пытаться его пересчитать.
НовыйПалет.Количество = НужноеМнеЧисло;
НовыйПалет.ДополнительныеСвойства.Вставить("НеРассчитыватьКоличествоВложенныхШтрихкодов", Истина);
НовыйПалет.Записать();
Однако будьте осторожны: использование этого флага возлагает на разработчика полную ответственность за консистентность данных. Если количество не будет соответствовать реальному числу строк в табличной части, это может вызвать ошибки в дальнейшем при отгрузке маркированной продукции или при проверках в ГИС МТ.
Выясним несколько важных технических нюансов, которые помогут избежать ошибок при интеграции:
ЗначениеШтрихкода всегда используйте типовые функции разбора. Коды DataMatrix часто содержат спецсимволы (например, GS1 Group Separator), которые визуально не видны, но важны для уникальности. Используйте РазборКодаМаркировкиИССлужебный.РазобратьКодМаркировки для получения чистого значения.Загрузка = Истина), обязательно вызывайте метод пересчета хеша, иначе сканеры на складе могут не распознать содержимое палета.ТипыУпаковок. Для конечного товара это всегда МаркированныйТовар. Для агрегатов — МонотоварнаяУпаковка (если внутри один артикул) или СоставнаяУпаковка (если внутри разные товары). Ошибки в этом поле блокируют возможность проведения документов «Маркировка товаров ИСМП».Справочники.ШтрихкодыУпаковокТоваров.НайтиПоРеквизиту("ЗначениеШтрихкода", ...).Таким образом, мы выяснили, что секрет успешной записи реквизитов кроется в правильной последовательности создания объектов и соблюдении типов данных в табличной части. Следуя этим правилам, вы сможете корректно автоматизировать процессы маркировки в вашей организации — для этого разработан модуль интеграции и печати этикеток маркировки.