0

I need to apply discounts to our billing services and am having a devil of a time trying to figure out how to determine the used percent of an applied discount. I have scrapped almost 10 versions of code and think I am just to close to the problem and am not able to see this clearly.

I am trying to make universal function that will use the first/last day of the billing cycle, plus the startDiscount and endDiscount dates to determine what percent to apply to the actual discount; regardless if the discount is a % discount or an actual $ value.

Example: Bill month March 2023 (31 day bill cycle), invoiced services from Mar 1st - Mar 31st. But a 50% discount was applied starting on March 10th - the discount is for 90 days.

This means that roughly 66% of the 50% discount (IE: 33%) needs to be applied to the march invoice, the full 50% of April and May...and then 34% of the 50% discount (IE: 17%) needs to be applied to Junes bill.

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

So as each invoice is processed, the first/last day of the invoice range is passed in as well as the start/finish dates of the discount

$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 ;

}

Then $discPercent can be applied an existing 90 day 50% discount OR or can be applied to $100 credit per invoice cycle for 90s

rolinger
  • 2,787
  • 1
  • 31
  • 53
  • Is it prorated discount percentage for each billing cycle based on the start - end dates of the discount and the start - end dates of the billing cycle? – Wahyu Kristianto Feb 16 '23 at 15:41
  • Why you not just calculate it per day? So if day in discount period just apply 50% – ustmaestro Feb 16 '23 at 15:41
  • 3
    Not having discount period synced with the billing period, seems unnecessarily complicated. – gre_gor Feb 16 '23 at 15:43
  • @WahyuKristianto - its an applied discount if the invoice dates fall within the applied discount dates – rolinger Feb 16 '23 at 15:51
  • @gre_gor - I don't disagree but we are offering `first 30/60/90 day` discounts on certain services for NEW customers. So if the customer signs up on March 10th - we need to be able to apply a 60 day discount on from March 10th - May 10th. If we moved it to coincide with the start of the billing cycles, then they aren't getting the full discount if we start it on March 1st - meaning May 1st-10th gets no discount OR we start it on April 1st, then customer isn't getting discount on the day their services started. – rolinger Feb 16 '23 at 15:55
  • 3
    This question seems relevant: [How can I find overlapping dateperiods/date ranges in PHP?](https://stackoverflow.com/q/14202687) – gre_gor Feb 16 '23 at 16:00
  • 2
    @gre_gor - Nice Find! And WAY more simple than all the approaches I was trying. Use the determined amount of overlap days to then get the percentage of days within that month range. IE: March 10th - 31 over laps March 1st-31st by 21 days...then divide the determined overlap days by the days in month: 21/ 31 = 67.7% Awesome! If you post this as the answer I will upvote it. – rolinger Feb 16 '23 at 16:10
  • 2
    Does this answer your question? [How can I find overlapping dateperiods/date ranges in PHP?](https://stackoverflow.com/questions/14202687/how-can-i-find-overlapping-dateperiods-date-ranges-in-php) – user3783243 Feb 16 '23 at 16:17
  • 2
    It should be a duplicate in that case. – user3783243 Feb 16 '23 at 16:17
  • March has 22 days billed, that makes it 71% not 66%. – gre_gor Feb 16 '23 at 16:29

1 Answers1

1

You need to calculate the number of days overlapping the billing period and the discount period and divide it by number of days in the billing period.

With the help of the overlap function in this answer, you get this:

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";

This results in:

71
100
100
33
gre_gor
  • 6,669
  • 9
  • 47
  • 52