Решение ошибки проведения документа Отчет о розничных продажах в БП 3.0 с возвратами по продажам той же смены при обмене из УТ 11.5
Задачи пользователя - Корректировка данных
Можно сказать, что статья является ответом на публикацию Не проводится отчет о розничных продажах в БП, при возврате
Текущее состояние и проблема: Если в кассовой смене в УТ были произведены возвраты по продажам, осуществленным в этой же кассовой смене, то в БП в документ «Отчет о розничных продажах» возвраты денежных средств передаются, но не передается возврат самого возвращаемого покупателем товара. Это приводит к ошибке проведения документа.
Предлагаемое решение: при выгрузке на стороне УТ из списка оплат и возвратов (он единый) исключаются сторнирующие строки по одной и той же карте. Т.е. решение касается только оплат по картам. Допущение, из которого исходим: не учитываем в регламентированном учете розничные продажи, по которым был возврат в одной смене(или более широко - день в день).
В данный момент решение работает на релизе 11.5.22.174, стартовало с релиза 11.5.22.137.
Понадобятся процедуры общего модуля «МенеджерОбменаЧерезУниверсальныйФормат», которые добавляем в расширение и производим вставки в режиме &ИзменениеИКонтроль:
ПОД_Документ_ОтчетОРозничныхПродажах_ПриОбработке
ПКО_Документ_ОтчетОРозничныхПродажах_Отправка_ПриОтправкеДанных
Исправление ПОД_Документ_ОтчетОРозничныхПродажах_ПриОбработке вносим в запрос.
Учитывая, что в УТ в отчет о розничных возвратах попадают данные только по возвратам продаж, произведенным в другой кассовой смене, помечаем данные по оплатам (т.е. возвратам) ТЧ «ОплатаПлатежнымиКартами» этого документа как "не в этой смене". И наоборот, данные по оплатам и возвратам документа отчет о розничных продажах ТЧ «ОплатаПлатежнымиКартами» помечаем как "в этой смене".
Исправление процедуры ПКО_Документ_ОтчетОРозничныхПродажах_Отправка_ПриОтправкеДанных.
Имеется таблица значений оплат, содержащая оплаты и возвраты за смену, полученная из доработанного в предыдущем действии запроса. Считаем ее оригинальной. Далее заполняем ее копию только данными возвратов внутри смены. Далее обходим новую таблицу и для ее записей гасим в оригинальной таблице сторнирующие по сумме оплаты и возвраты по данной карте, эти строки новой таблицы также обнуляются. При следующем обходе новой таблицы обрабатываются строки, в которых сумма не совпадает с суммой в оригинальной таблице. Второй обход позволит сторнировать частичный возврат или возврат суммы, осуществленный, например, за два раза. Нужно учитывать, что сторнируются строки для одинаковых номеров карт, в том числе и пустых(«0000 0000…»).
И удаляем ставшие нулевыми по сумме строки оригинальной таблицы, которая уйдет в БП.
Полный код заимствованных процедур достаточно громоздкий для публикации, привожу блоки вставки.
ПОД_Документ_ОтчетОРозничныхПродажах_ПриОбработке
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ОплатаПлатежнымиКартами.Сумма КАК СуммаОплаты,
#Вставка
| Истина КАК ВЭтойСмене,
#КонецВставки
| Выбор
| Когда НомерПлатежнойКарты = """" Тогда
| ""0000 0000 0000 0000 00""
| Иначе
| ОплатаПлатежнымиКартами.НомерПлатежнойКарты
| Конец КАК НомерКарты,
| ""Неопределено"" КАК ВидКарты,
| ОплатаПлатежнымиКартами.ВидОплаты КАК ТипыПлатежнойСистемыККТ,
| ОплатаПлатежнымиКартами.ЭквайринговыйТерминал.Владелец.БанковскийСчет КАК БанковскийСчетОрганизации,
| ОплатаПлатежнымиКартами.ЭквайринговыйТерминал.Код КАК Номер,
| ОплатаПлатежнымиКартами.ЭквайринговыйТерминал.Ссылка КАК Ссылка,
| ВЫБОР
| КОГДА ОплатаПлатежнымиКартами.ЭквайринговыйТерминал.Владелец.Контрагент ЕСТЬ NULL
| ТОГДА ОплатаПлатежнымиКартами.ДоговорПодключения.Контрагент
| КОГДА ОплатаПлатежнымиКартами.ЭквайринговыйТерминал.Владелец.Контрагент = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
| ТОГДА ОплатаПлатежнымиКартами.ДоговорПодключения.Контрагент
| ИНАЧЕ ЕСТЬNULL(ОплатаПлатежнымиКартами.ЭквайринговыйТерминал.Владелец.Контрагент, ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка))
| КОНЕЦ КАК Эквайрер,
| ОплатаПлатежнымиКартами.ДоговорПодключения КАК Договор
|ИЗ
| Документ.ОтчетОРозничныхПродажах.ОплатаПлатежнымиКартами КАК ОплатаПлатежнымиКартами
|
|ГДЕ
| ОплатаПлатежнымиКартами.Ссылка = &Ссылка
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| -ОплатаПлатежнымиКартамиВозврат.Сумма КАК СуммаОплаты,
#Вставка
| Ложь КАК ВЭтойСмене,
#КонецВставки
| Выбор
| Когда НомерПлатежнойКарты = """" Тогда
| ""0000 0000 0000 0000 00""
| Иначе
| ОплатаПлатежнымиКартамиВозврат.НомерПлатежнойКарты
| Конец КАК НомерКарты,
| ""Неопределено"" КАК ВидКарты,
| ОплатаПлатежнымиКартамиВозврат.ВидОплаты КАК ТипыПлатежнойСистемыККТ,
| ОплатаПлатежнымиКартамиВозврат.ЭквайринговыйТерминал.Владелец.БанковскийСчет КАК БанковскийСчетОрганизации,
| ОплатаПлатежнымиКартамиВозврат.ЭквайринговыйТерминал.Код КАК Номер,
| ОплатаПлатежнымиКартамиВозврат.ЭквайринговыйТерминал.Ссылка КАК Ссылка,
| ЕСТЬNULL(ОплатаПлатежнымиКартамиВозврат.ЭквайринговыйТерминал.Владелец.Контрагент, ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)) КАК Эквайрер,
| ОплатаПлатежнымиКартамиВозврат.ДоговорПодключения
|ИЗ
| Документ.ОтчетОРозничныхВозвратах.ОплатаПлатежнымиКартами КАК ОплатаПлатежнымиКартамиВозврат
|ГДЕ
| &ВозвратыОтдельно
| И ОплатаПлатежнымиКартамиВозврат.Ссылка.Проведен
| И ОплатаПлатежнымиКартамиВозврат.Ссылка.КассоваяСмена = &КассоваяСмена
| И ОплатаПлатежнымиКартамиВозврат.Ссылка.КассоваяСмена <> Значение(Документ.КассоваяСмена.ПустаяСсылка)
| И ОплатаПлатежнымиКартамиВозврат.Ссылка.НалогообложениеНДС = &НалогообложениеНДС
|;
ПКО_Документ_ОтчетОРозничныхПродажах_Отправка_ПриОтправкеДанных
#Область ОплатаПлатежнымиКартами
ОплатаКартами = РезультатыЗапроса[НомераТаблиц.Получить("ОплатаКартами")].Выгрузить(); // ТаблицаЗначений
#Вставка
//см. также Дор_ПОД_Документ_ОтчетОРозничныхПродажах_ПриОбработке (текст запроса)
ТЗ_Минуса = ОплатаКартами.СкопироватьКолонки();
ТЗ_Минуса.Колонки.Добавить("ИндексСтроки", Новый ОписаниеТипов("Число"));
//Заполняем новую таблицу только строками возвратов
Для Каждого Строка Из ОплатаКартами Цикл
Если Строка.ВЭтойСмене И Строка.СуммаОплаты < 0 Тогда
НоваяСтрока = ТЗ_Минуса.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
НоваяСтрока.ИндексСтроки = ОплатаКартами.Индекс(Строка);
КонецЕсли;
КонецЦикла;
//Первый обход - Сторнирование данного возврата на равную оплату
Для Каждого СтрокаМинус Из ТЗ_Минуса Цикл
//отбираем в оригинальной таблице строки по текущей карте ТЗ_Минуса
Отбор = Новый Структура("НомерКарты,ВЭтойСмене", СтрокаМинус.НомерКарты, Истина);
НайденныеСтрокиОплатаКартами = ОплатаКартами.НайтиСтроки(Отбор);
Для Каждого НайденнаяСтрока Из НайденныеСтрокиОплатаКартами Цикл
Если НайденнаяСтрока.СуммаОплаты = - СтрокаМинус.СуммаОплаты Тогда
НайденнаяСтрока.СуммаОплаты = 0;
СтрокаМинус.СуммаОплаты = 0;
ОплатаКартами[СтрокаМинус.ИндексСтроки].СуммаОплаты = 0;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
//Второй обход - сторнируем несовпадающие суммы
Для Каждого СтрокаМинус Из ТЗ_Минуса Цикл
Если СтрокаМинус.СуммаОплаты = 0 Тогда
Продолжить;
КонецЕсли;
//отбираем в оригинальной таблице строки по текущей карте ТЗ_Минуса
Отбор = Новый Структура("НомерКарты,ВЭтойСмене", СтрокаМинус.НомерКарты, Истина);
НайденныеСтрокиОплатаКартами = ОплатаКартами.НайтиСтроки(Отбор);
Для Каждого НайденнаяСтрока Из НайденныеСтрокиОплатаКартами Цикл
Если НайденнаяСтрока.СуммаОплаты > 0 Тогда
Если НайденнаяСтрока.СуммаОплаты >= - СтрокаМинус.СуммаОплаты Тогда
//Сумма возврата меньше или равна Суммы оплаты
НайденнаяСтрока.СуммаОплаты = НайденнаяСтрока.СуммаОплаты + СтрокаМинус.СуммаОплаты;
СтрокаМинус.СуммаОплаты = 0;
ОплатаКартами[СтрокаМинус.ИндексСтроки].СуммаОплаты = 0;
Иначе
//Сумма возврата больше Суммы оплаты
СтрокаМинус.СуммаОплаты = СтрокаМинус.СуммаОплаты + НайденнаяСтрока.СуммаОплаты;
ОплатаКартами[СтрокаМинус.ИндексСтроки].СуммаОплаты = ОплатаКартами[СтрокаМинус.ИндексСтроки].СуммаОплаты + НайденнаяСтрока.СуммаОплаты;
НайденнаяСтрока.СуммаОплаты = 0;
КонецЕсли;
Если СтрокаМинус.СуммаОплаты = 0 Тогда //строку возврата отработали
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
//Удаление обнуленных строк в оригинальной таблице
Если ТЗ_Минуса.Количество() Тогда
Индекс = ОплатаКартами.Количество()-1;
Пока Индекс >= 0 Цикл
Если ОплатаКартами[Индекс].СуммаОплаты = 0 Тогда
ОплатаКартами.Удалить(ОплатаКартами[Индекс]);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
КонецЕсли;
#КонецВставки
Если ОплатаКартами.Количество() <> 0 Тогда
ОплатаКартами.Колонки.Добавить("ДоговорЭквайринга");
ОплатаКартами.Колонки.Добавить("ЭквайринговыйТерминал");
ПараметрыПоУмолчанию = Новый Структура(ДоговорФиксированнаяСтруктураКлючей());
ПараметрыПоУмолчанию.Организация = ДанныеИБ.Организация;
ПараметрыПоУмолчанию.Контрагент = ОплатаКартами[0].Эквайрер;
ПараметрыПоУмолчанию.ВидДоговора = "Прочее";
ПараметрыПоУмолчанию.ВалютаВзаиморасчетов = ЗначениеНастроекПовтИсп.ВалютаРегламентированногоУчетаОрганизации(ДанныеИБ.Организация);
ПараметрыПоУмолчанию.РасчетыВУсловныхЕдиницах = Ложь;
ДоговорЭквайринга = ДоговорИнструкцияКонвертацииПоДаннымВзаиморасчетов(ПараметрыПоУмолчанию, КомпонентыОбмена);
КонецЕсли;
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.