PHP определяет оставшийся процент месяца

Мне нужно применить скидки к нашим биллинговым службам, и я чертовски долго пытаюсь выяснить, как определить использованный процент примененной скидки. Я выбросил почти 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 секунд.

Является ли процент скидки пропорциональным для каждого платежного цикла на основе дат начала и окончания скидки и дат начала и окончания платежного цикла?

Wahyu Kristianto 16.02.2023 16:41

Почему бы вам просто не рассчитать это в день? Так что, если день в период скидки, просто примените 50%

ustmaestro 16.02.2023 16:41

Отсутствие синхронизации периода скидки с расчетным периодом кажется излишне сложным.

gre_gor 16.02.2023 16:43

@WahyuKristianto - это примененная скидка, если даты счета-фактуры попадают в даты примененных скидок

rolinger 16.02.2023 16:51

@gre_gor - Я согласен, но мы предлагаем first 30/60/90 day скидки на некоторые услуги для НОВЫХ клиентов. Поэтому, если клиент зарегистрируется 10 марта, мы должны иметь возможность применить 60-дневную скидку с 10 марта по 10 мая. Если мы переместим его так, чтобы он совпал с началом расчетных циклов, то они не получат полную скидку, если мы начнем ее 1 марта, то есть с 1 по 10 мая скидка не будет ИЛИ мы начнем ее 1 апреля, тогда клиент не получают скидку в день начала их услуг.

rolinger 16.02.2023 16:55

Этот вопрос кажется актуальным: Как найти перекрывающиеся периоды/диапазоны дат в PHP?

gre_gor 16.02.2023 17:00

@gre_gor - Хорошая находка! И НАМНОГО проще, чем все подходы, которые я пробовал. Используйте определенное количество дней перекрытия, чтобы затем получить процент дней в этом диапазоне месяцев. IE: 10 марта - 31 перекрытие с 1 по 31 марта на 21 день... затем разделите определенное количество дней перекрытия на количество дней в месяце: 21/31 = 67,7% Отлично! Если вы опубликуете это как ответ, я поддержу его.

rolinger 16.02.2023 17:10

Отвечает ли это на ваш вопрос? Как найти перекрывающиеся периоды/диапазоны дат в PHP?

user3783243 16.02.2023 17:17

В этом случае он должен быть дубликатом.

user3783243 16.02.2023 17:17

В марте выставлен счет за 22 дня, что составляет 71%, а не 66%.

gre_gor 16.02.2023 17:29
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Запись файлов cookie в файл с помощью XSS R
Запись файлов cookie в файл с помощью XSS R
Привет всем :), здесь я продемонстрирую получение cookies, которые будут сохранены в виде txt файла, используя дефект XSS Reflected.
Каковы некоторые из продвинутых концепций языков программирования?
Каковы некоторые из продвинутых концепций языков программирования?
В языках программирования существует множество продвинутых концепций, но некоторые из них являются наиболее важными:
PHPStorm vs Visual Studio Code: Выбор лучшей IDE для ваших потребностей в веб-разработке
PHPStorm vs Visual Studio Code: Выбор лучшей IDE для ваших потребностей в веб-разработке
PHPStorm и Visual Studio Code - две популярные интегрированные среды разработки (IDE), используемые веб-разработчиками. Оба инструмента предлагают...
Повышение качества Laravel с помощью принципов SOLID: Лучшие практики и примеры
Повышение качества Laravel с помощью принципов SOLID: Лучшие практики и примеры
Когда мы говорим о том, как сделать следующий шаг в качестве разработчика, мы должны понимать, что качество кода всегда является основным фокусом на...
Получение URL-адреса изображения курса в Moodle с помощью PHP
Получение URL-адреса изображения курса в Moodle с помощью PHP
Moodle - это популярная система управления обучением с открытым исходным кодом, используемая многими учебными заведениями и организациями по всему...
1
10
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам необходимо рассчитать количество дней, перекрывающих расчетный период и период скидки, и разделить его на количество дней в расчетном периоде.

С помощью функции перекрытия в этом ответе получается вот что:

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

Другие вопросы по теме