Сгорание бонусов в УНФ

Клиенту нужно, чтобы в карточке покупателя выводилась ближайшая сумма сгораемых бонусных баллов.

Я сначала сделал так:

Функция ИнформацияСтрокойОБонусахПоКонтрагенту(Контрагент) Экспорт                    
	Р = "";                        

	Сгорает = 0;
	ДатаСгорания = Неопределено;
	Остаток = 0;

	//=== ПОЛУЧАЕМ ОСТАТОК ===
	
	З = Новый Запрос(
	"ВЫБРАТЬ
	|	Т.НачисленоОстаток - Т.КСписаниюОстаток КАК Остаток
	|ИЗ
	|	РегистрНакопления.БонусныеБаллы.Остатки(&ТекущаяДата, БонуснаяКарта.ВладелецКарты = &Контрагент) КАК Т");
	З.УстановитьПараметр("Контрагент", Контрагент);
	З.УстановитьПараметр("ТекущаяДата", ТекущаяДата());
	Выборка = З.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда  
		Остаток = Макс(Выборка.Остаток, 0);
	КонецЕсли;   
	
	З.Текст = 
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Т.Период КАК Дата,
	|	Т.КСписаниюОборот КАК Сумма
	|ИЗ
	|	РегистрНакопления.БонусныеБаллы.Обороты(&ТекущаяДата, , Регистратор, БонуснаяКарта.ВладелецКарты = &Контрагент) КАК Т
	|ГДЕ
	|	Т.КСписаниюОборот > 0";
	З.УстановитьПараметр("Контрагент", Контрагент);
	Выборка = З.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда  
		ДатаСгорания = Выборка.Дата;
		Сгорает = Выборка.Сумма;
	КонецЕсли;   
	
	Р = 
	"остаток: " + Остаток + 
	?(ЗначениеЗаполнено(ДатаСгорания), " сгорает: " + Сгорает + " в: " + Формат(ДатаСгорания, "ДФ=dd.MMM.yyyy"), "");

	Возврат Р;     
	
КонецФункции

Но здесь выводится сумма планового сгорания. Если клиент успел потратить бонусы, они не сгорят, но предупреждение об их сгорании будет (потому что показывается дата запланированного списания), что не совсем корректно.

Поэтому клиент заказал вывод корректной суммы сгорания.

Сначала я решил поискать сумму сгорания в типовом коде.

Я нашел автоматическое списание бонусов в процедуре РаботаСБонусами.ВыполнитьАвтоматическоеНачислениеИСписание, которая вызывается из регламентного задания АвтоматическоеНачислениеИСписаниеБонусныхБаллов.

Запрос по списаниям баллов выглядит так:

А код списания так:

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

Я буду использовать вместо «К списанию» просто «Списание», так короче.

Таким образом, корректная логика выглядит так — если остаток на текущий момент по Начислено меньше нуля, ничего не списываем, иначе списываем минимум между остатком по Начислено и Списание. Кстати, тут не учитываются ошибки, когда Списание может быть меньше нуля, что спишет отрицательное количество. Хотя в итоге Списание обратится в ноль, но это как-то не очевидно.

Я добавил корректировку суммы к сгоранию небольшой правкой:

//Корректируем что сгорание не может быть больше, чем текущий остаток баллов
//См. РаботаСБонусами.ВыполнитьАвтоматическоеНачислениеИСписание
Если Сгорает > Остаток Тогда
	Сгорает = Остаток;
КонецЕсли;

Корректен ли алгоритм списания бонусов УНФ?

Но корректен ли сам типовой алгоритм? Проверим на примере:

  • 1 января начислено 100 бонусов сроком на три месяца до 1 апреля
  • 1 февраля начислено 200 бонусов сроком на три месяца до 1 мая
  • 1 марта потрачено 80 бонусов

30 марта будет остаток Начислено 220 бонусов и 1 апреля остаток Списание 100 бонусов. Реально 1 апреля сгорят минимум между остатками по Начислено (220) и Списание (100) = 100 баллов.

Тут и кроется ошибка, потому что сгореть должны были только 20 баллов, но УНФ не поддерживает партионный учет бонусов.

Как 1С может выкладывать в продакшн такие сырые решения, не знаю, видимо у нее «нет ни стыда ни совести«. По сути 1С обсчитывает клиента, а негатив из-за ошибок 1С будет получать продавец.

Проверка на практике списания бонусов УНФ

Смоделируем ситуацию. Сделаем начисление баллов на вчера, 17 апреля:

А затем вызовем сегодня, 18 апреля, списание баллов вызовом регламентного задания АвтоматическоеНачислениеИСписаниеБонусныхБаллов:, следует учитывать что она делает начисление по остаткам на начало дня, поэтому начисление баллов делали на вчера:

И как и предсказывалось, списываются 100 баллов, а не 80 (на закладке Списание):

Среда: УНФ 3.0.6.200. Объем: 1.5 час

image_pdfimage_print

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Вам может также понравиться...

комментария 4

  1. Serg:

    А EROR это такой тонкий юмор?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *