Мне нужно применить скидки к нашим биллинговым службам, и я чертовски долго пытаюсь выяснить, как определить использованный процент примененной скидки. Я выбросил почти 10 версий кода и думаю, что просто близко к проблеме и не могу ясно это увидеть.
Я пытаюсь создать универсальную функцию, которая будет использовать первый/последний день цикла выставления счетов, а также даты startDiscount и endDiscount, чтобы определить, какой процент применять к фактической скидке; независимо от того, является ли скидка процентной скидкой или фактической стоимостью в долларах.
Пример: месяц выставления счетов март 2023 г. (31-дневный цикл выставления счетов), счета за услуги выставляются с 1 марта по 31 марта. Но с 10 марта была применена скидка 50% - скидка на 90 дней.
Это означает, что примерно 66 % от 50 % скидки (IE: 33 %) необходимо применить к счету за март, полные 50 % за апрель и май… и затем 34 % от 50 % скидки (IE: 17). %) необходимо применять к счету за июнь.
So for the applied discounts:
March = 66% of the 50% discount = 33% discount applied to charges
April = 100% of the 50% discount = 50% discount applied to the charges
May = = 100% of the 50% discount = 50% discount applied to the charges
June = 33% of the 50% discount = 17% discount applied to charges
Таким образом, при обработке каждого счета-фактуры передается первый/последний день диапазона счета-фактуры, а также даты начала/окончания скидки.
$discPercent = applyDiscount("2023-03-01","2023-03-31","2023-03-10","2023-06-10") ;
$discPercent = applyDiscount("2023-04-01","2023-04-30","2023-03-10","2023-06-10") ;
$discPercent = applyDiscount("2023-05-01","2023-05-31","2023-03-10","2023-06-10") ;
$discPercent = applyDiscount("2023-06-01","2023-06-30","2023-03-10","2023-06-10") ;
function applyDiscount($firstDay,$lastDay,$startDisc,$endDisc) {
...
...
return $applyThisPercent ;
}
Затем $discPercent можно применить существующую 90-дневную скидку 50% ИЛИ можно применить к кредиту в размере 100 долларов США за цикл счета в течение 90 секунд.
Почему бы вам просто не рассчитать это в день? Так что, если день в период скидки, просто примените 50%
Отсутствие синхронизации периода скидки с расчетным периодом кажется излишне сложным.
@WahyuKristianto - это примененная скидка, если даты счета-фактуры попадают в даты примененных скидок
@gre_gor - Я согласен, но мы предлагаем first 30/60/90 day скидки на некоторые услуги для НОВЫХ клиентов. Поэтому, если клиент зарегистрируется 10 марта, мы должны иметь возможность применить 60-дневную скидку с 10 марта по 10 мая. Если мы переместим его так, чтобы он совпал с началом расчетных циклов, то они не получат полную скидку, если мы начнем ее 1 марта, то есть с 1 по 10 мая скидка не будет ИЛИ мы начнем ее 1 апреля, тогда клиент не получают скидку в день начала их услуг.
Этот вопрос кажется актуальным: Как найти перекрывающиеся периоды/диапазоны дат в PHP?
@gre_gor - Хорошая находка! И НАМНОГО проще, чем все подходы, которые я пробовал. Используйте определенное количество дней перекрытия, чтобы затем получить процент дней в этом диапазоне месяцев. IE: 10 марта - 31 перекрытие с 1 по 31 марта на 21 день... затем разделите определенное количество дней перекрытия на количество дней в месяце: 21/31 = 67,7% Отлично! Если вы опубликуете это как ответ, я поддержу его.
Отвечает ли это на ваш вопрос? Как найти перекрывающиеся периоды/диапазоны дат в PHP?
В этом случае он должен быть дубликатом.
В марте выставлен счет за 22 дня, что составляет 71%, а не 66%.
Вам необходимо рассчитать количество дней, перекрывающих расчетный период и период скидки, и разделить его на количество дней в расчетном периоде.
С помощью функции перекрытия в этом ответе получается вот что:
function datesOverlap($start_one, $end_one, $start_two, $end_two) {
if ($start_one <= $end_two && $end_one >= $start_two) { //If the dates overlap
return datesDays(min($end_one, $end_two), max($start_two, $start_one));
}
return 0; //Return 0 if there is no overlap
}
function datesDays($start, $end) {
return $start->diff($end)->days+1;
}
function applyDiscount($firstDay, $lastDay, $startDisc, $endDisc) {
$firstDay = new DateTime($firstDay);
$lastDay = new DateTime($lastDay);
$startDisc = new DateTime($startDisc);
$endDisc = new DateTime($endDisc);
$all_days = datesDays($firstDay, $lastDay);
$used_days = datesOverlap($firstDay, $lastDay, $startDisc, $endDisc);
return round(100*$used_days/$all_days);
}
echo applyDiscount("2023-03-01","2023-03-31","2023-03-10","2023-06-10")."\n";
echo applyDiscount("2023-04-01","2023-04-30","2023-03-10","2023-06-10")."\n";
echo applyDiscount("2023-05-01","2023-05-31","2023-03-10","2023-06-10")."\n";
echo applyDiscount("2023-06-01","2023-06-30","2023-03-10","2023-06-10")."\n";
Это приводит к:
71
100
100
33
Является ли процент скидки пропорциональным для каждого платежного цикла на основе дат начала и окончания скидки и дат начала и окончания платежного цикла?