Как в запросе 1С разбить строку номенклатуры на отдельные позиции по кодам маркировки (QR/DataMatrix)?

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

В современной торговой деятельности, особенно с внедрением системы "Честный ЗНАК", мы часто сталкиваемся с задачей детальной отчетности. Стандартные документы 1С, такие как "Реализация товаров и услуг", обычно группируют товары: в одной строке мы видим "Номенклатура Х — 10 штук". Однако для спецификаций, паспортов качества или особых требований заказчика нам необходимо предоставить список, где каждая единица товара идет отдельной строкой со своим уникальным кодом маркировки (DataMatrix или QR-кодом).

Давайте подробно разберем, как реализовать такую задачу программно, проанализируем структуру данных типовых конфигураций (ERP, Управление Торговлей, Комплексная Автоматизация) и составим правильный алгоритм запроса.

Постановка задачи и анализ структуры данных

Представим ситуацию: в документе реализации есть строка с товаром "Салют" в количестве 2 штук. К этой строке привязаны два уникальных кода маркировки. Наша цель — получить в печатной форме или отчете две строки:

  1. Салют — 1 шт — КодМаркировки_1
  2. Салют — 1 шт — КодМаркировки_2

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

Обычно используются две табличные части:

  1. Товары — здесь хранится номенклатура, цена, сумма и общее количество.
  2. ШтрихкодыУпаковок — здесь хранятся конкретные коды маркировки (DataMatrix), привязанные к строкам товаров.

Важный момент: Связь между этими двумя таблицами осуществляется не по Номенклатуре (так как одинаковая номенклатура может встречаться в документе несколько раз с разной ценой), а по специальному служебному полю. Чаще всего это поле называется КлючСвязи (в более старых версиях или других документах может встречаться ИдентификаторСтроки).

Реализация запроса: Левое соединение

Рассмотрим базовое решение, которое позволяет "развернуть" свернутые строки. Основная идея заключается в использовании левого соединения (LEFT JOIN) табличной части товаров с табличной частью штрихкодов.

Если мы просто соединим таблицы, то количество из строки товаров (например, 2 шт.) продублируется для каждого найденного штрихкода. Чтобы этого избежать, нам нужно в запросе явно указать, что для каждой найденной марки количество равно 1.

Давайте напишем примерный текст запроса, который решает эту задачу:


ВЫБРАТЬ
    ТЧТовары.Номенклатура КАК Номенклатура,
    ЕСТЬNULL(ТЧШтрихкоды.ЗначениеШтрихкода, "") КАК QRКод,
    ВЫБОР
        КОГДА ТЧШтрихкоды.ЗначениеШтрихкода ЕСТЬ NULL ТОГДА ТЧТовары.Количество
        ИНАЧЕ 1
    КОНЕЦ КАК Количество
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК ТЧТовары
        ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.ШтрихкодыУпаковок КАК ТЧШтрихкоды
        ПО ТЧТовары.КлючСвязи = ТЧШтрихкоды.КлючСвязи
ГДЕ
    ТЧТовары.Ссылка = &СсылкаНаДокумент

Давайте проанализируем, как работает этот запрос:

  1. Мы берем основную таблицу Товары.
  2. Присоединяем к ней таблицу ШтрихкодыУпаковок по полю КлючСвязи.
  3. Если у товара есть коды маркировки, в выборку попадет столько строк, сколько кодов найдено.
  4. В поле Количество мы используем условие: если код найден, ставим жестко 1. Если кодов нет (обычный товар), оставляем исходное количество из документа.

Проблема частичной маркировки и дублирования данных

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

Ситуация "Частичная маркировка": Допустим, в строке указано 10 штук товара, но кладовщик отсканировал только 3 марки. Остальные 7 штук идут без указания конкретных кодов (или коды не были считаны в 1С).

Если использовать простой запрос выше, мы получим 3 строки с количеством 1. Куда денутся остальные 7 штук? Они просто исчезнут из выборки, так как соединение отработает только по найденным записям в таблице штрихкодов.

Чтобы решить эту проблему корректно, нам нужно разбить задачу на два этапа и объединить результаты:

  1. Выбрать все маркированные единицы (количество = 1).
  2. Вычислить "немаркированный остаток" (Общее количество минус Количество марок).

Посмотрим, как будет выглядеть более продвинутый запрос с использованием ОБЪЕДИНИТЬ ВСЕ:


ВЫБРАТЬ
    ТЧТовары.Номенклатура,
    ТЧТовары.КлючСвязи,
    ТЧТовары.Количество КАК ОбщееКоличество
ПОМЕСТИТЬ ВТ_Товары
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК ТЧТовары
ГДЕ
    ТЧТовары.Ссылка = &Ссылка;
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ТЧШтрихкоды.КлючСвязи,
    ТЧШтрихкоды.ЗначениеШтрихкода,
    1 КАК Количество
ПОМЕСТИТЬ ВТ_Марки
ИЗ
    Документ.РеализацияТоваровУслуг.ШтрихкодыУпаковок КАК ТЧШтрихкоды
ГДЕ
    ТЧШтрихкоды.Ссылка = &Ссылка;
;

////////////////////////////////////////////////////////////////////////////////
// Часть 1: Выводим конкретные марки
ВЫБРАТЬ
    ВТ_Товары.Номенклатура,
    ВТ_Марки.ЗначениеШтрихкода,
    1 КАК Количество
ИЗ
    ВТ_Товары КАК ВТ_Товары
    ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Марки КАК ВТ_Марки
    ПО ВТ_Товары.КлючСвязи = ВТ_Марки.КлючСвязи

ОБЪЕДИНИТЬ ВСЕ

// Часть 2: Выводим остаток без марок
ВЫБРАТЬ
    ВТ_Товары.Номенклатура,
    "Без маркировки",
    ВТ_Товары.ОбщееКоличество - ЕСТЬNULL(ВложенныйЗапрос.КоличествоМарок, 0)
ИЗ
    ВТ_Товары КАК ВТ_Товары
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ КлючСвязи, СУММА(1) КАК КоличествоМарок 
        ИЗ ВТ_Марки СГРУППИРОВАТЬ ПО КлючСвязи
    ) КАК ВложенныйЗапрос
    ПО ВТ_Товары.КлючСвязи = ВложенныйЗапрос.КлючСвязи
ГДЕ
    (ВТ_Товары.ОбщееКоличество - ЕСТЬNULL(ВложенныйЗапрос.КоличествоМарок, 0)) > 0

Такой подход гарантирует, что общее количество товара в спецификации сойдется с документом, даже если маркировка заполнена частично.

Особенности работы с DataMatrix и упаковками

При подготовке печатной формы нужно учитывать еще несколько технических нюансов:

1. Формат хранения кода.
В поле ЗначениеШтрихкода часто хранится полная строка DataMatrix, включающая спецсимволы, криптохвост и разделители групп (GS). Если заказчику нужен "красивый" вид или только GTIN и Серийный номер, полученную строку придется обрабатывать программно уже после выполнения запроса, используя функции работы со строками 1С.

2. Иерархия упаковок (Агрегация).
В таблице ШтрихкодыУпаковок могут находиться не только коды единиц товара, но и коды транспортных упаковок (коробов, паллет). Если товар был агрегирован, простой запрос может выдать и код коробки, и коды товаров внутри неё, что приведет к задвоению количества.

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

Альтернативный вариант: Использование СКД

Если ваша задача — не просто получить данные для обработки, а вывести отчет или печатную форму сложной структуры, рассмотрим использование Системы Компоновки Данных (СКД). Это часто бывает эффективнее написания чистого кода.

В СКД вы можете настроить два набора данных и связать их. Основным преимуществом будет возможность настройки иерархического вывода без сложной математики в запросе:

  1. Создайте группировку по Номенклатуре (для вывода общей строки "Салют — 2 шт").
  2. Внутри этой группировки создайте детальные записи (или вложенную группировку) по Штрихкоду.

В этом случае система сама сгруппирует данные. Вы сможете настроить макет так, чтобы заказчик видел:

Заключение

Для разбиения номенклатуры по QR-кодам (DataMatrix) в 1С:

  1. Используйте соединение таблиц Товары и ШтрихкодыУпаковок по полю КлючСвязи.
  2. В запросе принудительно устанавливайте количество равным 1 для строк с заполненным штрихкодом.
  3. Не забывайте про контроль "немаркированного остатка", чтобы не потерять количество товара, для которого коды не были отсканированы.
  4. Для сложных отчетов используйте возможности СКД по работе с иерархией.
← На главную