В современной торговой деятельности, особенно с внедрением системы "Честный ЗНАК", мы часто сталкиваемся с задачей детальной отчетности. Стандартные документы 1С, такие как "Реализация товаров и услуг", обычно группируют товары: в одной строке мы видим "Номенклатура Х — 10 штук". Однако для спецификаций, паспортов качества или особых требований заказчика нам необходимо предоставить список, где каждая единица товара идет отдельной строкой со своим уникальным кодом маркировки (DataMatrix или QR-кодом).
Давайте подробно разберем, как реализовать такую задачу программно, проанализируем структуру данных типовых конфигураций (ERP, Управление Торговлей, Комплексная Автоматизация) и составим правильный алгоритм запроса.
Представим ситуацию: в документе реализации есть строка с товаром "Салют" в количестве 2 штук. К этой строке привязаны два уникальных кода маркировки. Наша цель — получить в печатной форме или отчете две строки:
Прежде чем писать код, давайте посмотрим, как эти данные хранятся в базе данных. В типовых конфигурациях информация о товарах и их кодах маркировки разнесена по разным табличным частям.
Обычно используются две табличные части:
Товары — здесь хранится номенклатура, цена, сумма и общее количество.ШтрихкодыУпаковок — здесь хранятся конкретные коды маркировки (DataMatrix), привязанные к строкам товаров.Важный момент: Связь между этими двумя таблицами осуществляется не по Номенклатуре (так как одинаковая номенклатура может встречаться в документе несколько раз с разной ценой), а по специальному служебному полю. Чаще всего это поле называется КлючСвязи (в более старых версиях или других документах может встречаться ИдентификаторСтроки).
Рассмотрим базовое решение, которое позволяет "развернуть" свернутые строки. Основная идея заключается в использовании левого соединения (LEFT JOIN) табличной части товаров с табличной частью штрихкодов.
Если мы просто соединим таблицы, то количество из строки товаров (например, 2 шт.) продублируется для каждого найденного штрихкода. Чтобы этого избежать, нам нужно в запросе явно указать, что для каждой найденной марки количество равно 1.
Давайте напишем примерный текст запроса, который решает эту задачу:
ВЫБРАТЬ
ТЧТовары.Номенклатура КАК Номенклатура,
ЕСТЬNULL(ТЧШтрихкоды.ЗначениеШтрихкода, "") КАК QRКод,
ВЫБОР
КОГДА ТЧШтрихкоды.ЗначениеШтрихкода ЕСТЬ NULL ТОГДА ТЧТовары.Количество
ИНАЧЕ 1
КОНЕЦ КАК Количество
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК ТЧТовары
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.ШтрихкодыУпаковок КАК ТЧШтрихкоды
ПО ТЧТовары.КлючСвязи = ТЧШтрихкоды.КлючСвязи
ГДЕ
ТЧТовары.Ссылка = &СсылкаНаДокумент
Давайте проанализируем, как работает этот запрос:
Товары.ШтрихкодыУпаковок по полю КлючСвязи.Количество мы используем условие: если код найден, ставим жестко 1. Если кодов нет (обычный товар), оставляем исходное количество из документа.Приведенный выше запрос хорошо работает в идеальных условиях, когда количество товара строго совпадает с количеством отсканированных марок. Однако на практике часто встречаются сложные ситуации. Давайте разберем их подробнее.
Ситуация "Частичная маркировка": Допустим, в строке указано 10 штук товара, но кладовщик отсканировал только 3 марки. Остальные 7 штук идут без указания конкретных кодов (или коды не были считаны в 1С).
Если использовать простой запрос выше, мы получим 3 строки с количеством 1. Куда денутся остальные 7 штук? Они просто исчезнут из выборки, так как соединение отработает только по найденным записям в таблице штрихкодов.
Чтобы решить эту проблему корректно, нам нужно разбить задачу на два этапа и объединить результаты:
Посмотрим, как будет выглядеть более продвинутый запрос с использованием ОБЪЕДИНИТЬ ВСЕ:
ВЫБРАТЬ
ТЧТовары.Номенклатура,
ТЧТовары.КлючСвязи,
ТЧТовары.Количество КАК ОбщееКоличество
ПОМЕСТИТЬ ВТ_Товары
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК ТЧТовары
ГДЕ
ТЧТовары.Ссылка = &Ссылка;
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ТЧШтрихкоды.КлючСвязи,
ТЧШтрихкоды.ЗначениеШтрихкода,
1 КАК Количество
ПОМЕСТИТЬ ВТ_Марки
ИЗ
Документ.РеализацияТоваровУслуг.ШтрихкодыУпаковок КАК ТЧШтрихкоды
ГДЕ
ТЧШтрихкоды.Ссылка = &Ссылка;
;
////////////////////////////////////////////////////////////////////////////////
// Часть 1: Выводим конкретные марки
ВЫБРАТЬ
ВТ_Товары.Номенклатура,
ВТ_Марки.ЗначениеШтрихкода,
1 КАК Количество
ИЗ
ВТ_Товары КАК ВТ_Товары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Марки КАК ВТ_Марки
ПО ВТ_Товары.КлючСвязи = ВТ_Марки.КлючСвязи
ОБЪЕДИНИТЬ ВСЕ
// Часть 2: Выводим остаток без марок
ВЫБРАТЬ
ВТ_Товары.Номенклатура,
"Без маркировки",
ВТ_Товары.ОбщееКоличество - ЕСТЬNULL(ВложенныйЗапрос.КоличествоМарок, 0)
ИЗ
ВТ_Товары КАК ВТ_Товары
ЛЕВОЕ СОЕДИНЕНИЕ (
ВЫБРАТЬ КлючСвязи, СУММА(1) КАК КоличествоМарок
ИЗ ВТ_Марки СГРУППИРОВАТЬ ПО КлючСвязи
) КАК ВложенныйЗапрос
ПО ВТ_Товары.КлючСвязи = ВложенныйЗапрос.КлючСвязи
ГДЕ
(ВТ_Товары.ОбщееКоличество - ЕСТЬNULL(ВложенныйЗапрос.КоличествоМарок, 0)) > 0
Такой подход гарантирует, что общее количество товара в спецификации сойдется с документом, даже если маркировка заполнена частично.
При подготовке печатной формы нужно учитывать еще несколько технических нюансов:
1. Формат хранения кода.
В поле ЗначениеШтрихкода часто хранится полная строка DataMatrix, включающая спецсимволы, криптохвост и разделители групп (GS). Если заказчику нужен "красивый" вид или только GTIN и Серийный номер, полученную строку придется обрабатывать программно уже после выполнения запроса, используя функции работы со строками 1С.
2. Иерархия упаковок (Агрегация).
В таблице ШтрихкодыУпаковок могут находиться не только коды единиц товара, но и коды транспортных упаковок (коробов, паллет). Если товар был агрегирован, простой запрос может выдать и код коробки, и коды товаров внутри неё, что приведет к задвоению количества.
Чтобы этого избежать, проанализируйте структуру метаданных вашей конфигурации. Часто там есть реквизит, указывающий на тип упаковки, или ссылка на родительскую упаковку. В запросе стоит добавить условие, исключающее агрегационные коды, если вам нужны только единицы товара.
Если ваша задача — не просто получить данные для обработки, а вывести отчет или печатную форму сложной структуры, рассмотрим использование Системы Компоновки Данных (СКД). Это часто бывает эффективнее написания чистого кода.
В СКД вы можете настроить два набора данных и связать их. Основным преимуществом будет возможность настройки иерархического вывода без сложной математики в запросе:
Номенклатуре (для вывода общей строки "Салют — 2 шт").Штрихкоду.В этом случае система сама сгруппирует данные. Вы сможете настроить макет так, чтобы заказчик видел:
Для разбиения номенклатуры по QR-кодам (DataMatrix) в 1С:
Товары и ШтрихкодыУпаковок по полю КлючСвязи.