Как сформировать запрос 1С по чекам ККМ со смешанной оплатой без дублирования строк товаров?

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

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

Разберем подробно причину возникновения такой ситуации и проанализируем правильные способы построения запросов и обработки результатов в 1С.

Выясним причину дублирования строк в запросе

Проанализируем структуру хранения данных в типовых конфигурациях 1С (например, «1С:Розница» или «1С:Управление торговлей»). В документе ЧекККМ сведения о проданных позициях и сведения об оплате хранятся в разных местах:

  1. Номенклатура и товары — хранятся в табличной части Товары.
  2. Оплата платежными картами — хранится в табличной части ОплатаПлатежнымиКартами.
  3. Оплата сертификатами — хранится в табличной части ПодарочныеСертификаты.
  4. Наличные средства — хранятся в реквизите шапки документа ПолученоНаличными.

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

Если выполнить прямое соединение (ВНУТРЕННЕЕ СОЕДИНЕНИЕ или ЛЕВОЕ СОЕДИНЕНИЕ) табличной части Товары с табличной частью ОплатаПлатежнымиКартами, произойдет так называемое декартово произведение. Если в чеке 2 товара и 2 вида оплаты, запрос вернет 4 строки. При использовании оператора ОБЪЕДИНИТЬ ВСЕ для разных видов оплаты каждая товарная позиция выгружается отдельными записями с заполнением колонок только одного вида оплаты, из-за чего строки в макете не сворачиваются.

Способ 1. Использование группировок и секции ИТОГИ ПО в запросе

Чтобы исключить дублирование товаров в отчете, разберем подход с использованием иерархических итогов. Мы выбираем товары, сгруппированные по документу чека, а виды оплаты обрабатываем на верхнем уровне группировки или во вложенных выборках.

Рассмотрим пример запроса с секцией ИТОГИ:


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

При обходе результатов такого запроса в программном коде BSL мы применяем двухуровневый цикл:

  1. На верхнем уровне (по документу ЧекККМ) получаем общие суммы оплаты наличными (ЧекККМ.ПолученоНаличными), безналичными средствами и сертификатами из соответствующих табличных частей документа.
  2. На внутреннем уровне обходим строки выборки с детальными записями по номенклатуре и выводим их в табличный документ.

Посмотрим на пример обработки выборки в коде 1С:


ВыборкаЧеки = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаЧеки.Следующий() Цикл
	
	// Получаем данные об оплатах для текущего чека
	ДокСсылка = ВыборкаЧеки.ЧекККМ;
	СуммаНаличные = ДокСсылка.ПолученоНаличными;
	
	// Обходим товары текущего чека без дублирования
	ВыборкаДетали = ВыборкаЧеки.Выбрать();
	Пока ВыборкаДетали.Следующий() Цикл
		ОбластьСтрока = Макет.ПолучитьОбласть("СтрокаТовар");
		ОбластьСтрока.Параметры.Заполнить(ВыборкаДетали);
		
		// Заполняем виды оплат на уровне документа или первой строки
		ОбластьСтрока.Параметры.СуммаНаличные = СуммаНаличные;
		
		ТабДок.Вывести(ОбластьСтрока);
	КонецЦикла;
	
КонецЦикла;

Способ 2. Разделение запросов на товары и оплаты

Ещё одно надежное решение — выполнить пакетный запрос или два отдельных запроса: один для табличной части Товары, второй — для сводных сумм оплат по документам чеков.

Рассмотрим структуру такого подхода:

  1. Первым запросом выбираем уникальные строки с товарами за кассовую смену с фильтрацией возвратов.
  2. Вторым запросом (или во временную таблицу) собираем суммы оплат по каждому документу `ЧекККМ`, сгруппированные по ссылке чека.
  3. Связываем полученные данные по ключу `Ссылка` чека при формировании печатной формы или в Системе компоновки данных (СКД).

При использовании СКД создаются два набора данных — запрос (`НаборДанныхТовары` и `НаборДанныхОплаты`), между которыми настраивается связь по полю Ссылка. Это позволяет СКД корректно выводить позиции номенклатуры без размножения строк при наличии нескольких видов оплат.

Форматирование данных в ячейках макета

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


МассивВидовОплаты = Новый Массив;

Если СуммаНаличные > 0 Тогда
	МассивВидовОплаты.Добавить("Наличные: " + Формат(СуммаНаличные, "ЧДЦ=2"));
КонецЕсли;

Если СуммаКарта > 0 Тогда
	МассивВидовОплаты.Добавить("Безналичные: " + Формат(СуммаКарта, "ЧДЦ=2"));
КонецЕсли;

ОбластьМакета.Параметры.ВидыОплаты = СтрСоединить(МассивВидовОплаты, Символы.ПС);

В свойствах ячейки макета табличного документа при этом необходимо установить свойство Размещение текста в значение Переносить или Авто.

← На главную