From 17507fd2581bdb165e7a369bfac364906f7a4301 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 21 Oct 2021 11:26:19 +1100 Subject: [PATCH] Tests for pro rata refunds --- .../Subscription/SubscriptionService.php | 53 +++++++++++ tests/Unit/RefundUnitTest.php | 95 +++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 tests/Unit/RefundUnitTest.php diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index 8771b9034c8c..e303b3038ab3 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -299,6 +299,24 @@ class SubscriptionService } + /** + * Calculates the pro rata refund between two dates + * using a daily calculation. + * + * @param float $amount + * @param Carbon $from_date + * @param Carbon $to_date + * @param int $frequency The billing interval + * @return float + */ + private function proRataRefund(float $amount, Carbon $from_date, Carbon $to_date, int $frequency) :float + { + $days = $from_date->diffInDays($to_date); + $days_in_frequency = $this->getDaysInFrequencySpecific($frequency); + + return round( ($days/$days_in_frequency) * $amount); + } + /** * Returns refundable set of line items * transformed for direct injection into @@ -934,6 +952,41 @@ class SubscriptionService } + private function getDaysInFrequencySpecific($frequency) + { + + switch ($frequency) { + case RecurringInvoice::FREQUENCY_DAILY: + return 1; + case RecurringInvoice::FREQUENCY_WEEKLY: + return 7; + case RecurringInvoice::FREQUENCY_TWO_WEEKS: + return 14; + case RecurringInvoice::FREQUENCY_FOUR_WEEKS: + return now()->diffInDays(now()->addWeeks(4)); + case RecurringInvoice::FREQUENCY_MONTHLY: + return now()->diffInDays(now()->addMonthNoOverflow()); + case RecurringInvoice::FREQUENCY_TWO_MONTHS: + return now()->diffInDays(now()->addMonthNoOverflow(2)); + case RecurringInvoice::FREQUENCY_THREE_MONTHS: + return now()->diffInDays(now()->addMonthNoOverflow(3)); + case RecurringInvoice::FREQUENCY_FOUR_MONTHS: + return now()->diffInDays(now()->addMonthNoOverflow(4)); + case RecurringInvoice::FREQUENCY_SIX_MONTHS: + return now()->diffInDays(now()->addMonthNoOverflow(6)); + case RecurringInvoice::FREQUENCY_ANNUALLY: + return now()->diffInDays(now()->addYear()); + case RecurringInvoice::FREQUENCY_TWO_YEARS: + return now()->diffInDays(now()->addYears(2)); + case RecurringInvoice::FREQUENCY_THREE_YEARS: + return now()->diffInDays(now()->addYears(3)); + default: + return 0; + } + + } + + /** * 'email' => $this->email ?? $this->contact->email, diff --git a/tests/Unit/RefundUnitTest.php b/tests/Unit/RefundUnitTest.php new file mode 100644 index 000000000000..5679a534f8bc --- /dev/null +++ b/tests/Unit/RefundUnitTest.php @@ -0,0 +1,95 @@ +proRataRefund(10, Carbon::parse('2021-01-01'), Carbon::parse('2021-01-31'), RecurringInvoice::FREQUENCY_MONTHLY); + + $this->assertEquals(9.68, $refund); + + $this->assertEquals(30, Carbon::parse('2021-01-01')->diffInDays(Carbon::parse('2021-01-31'))); + + } + + public function testProRataRefundYearly() + { + + $refund = $this->proRataRefund(10, Carbon::parse('2021-01-01'), Carbon::parse('2021-01-31'), RecurringInvoice::FREQUENCY_ANNUALLY); + + $this->assertEquals(0.82, $refund); + } + + public function testDiffInDays() + { + + $this->assertEquals(30, Carbon::parse('2021-01-01')->diffInDays(Carbon::parse('2021-01-31'))); + + } + + private function proRataRefund(float $amount, Carbon $from_date, Carbon $to_date, int $frequency) :float + { + $days = $from_date->diffInDays($to_date); + $days_in_frequency = $this->getDaysInFrequencySpecific($frequency); + + return round( (($days/$days_in_frequency) * $amount),2); + } + + private function getDaysInFrequencySpecific($frequency) + { + + switch ($frequency) { + case RecurringInvoice::FREQUENCY_DAILY: + return 1; + case RecurringInvoice::FREQUENCY_WEEKLY: + return 7; + case RecurringInvoice::FREQUENCY_TWO_WEEKS: + return 14; + case RecurringInvoice::FREQUENCY_FOUR_WEEKS: + return now()->diffInDays(now()->addWeeks(4)); + case RecurringInvoice::FREQUENCY_MONTHLY: + return now()->diffInDays(now()->addMonthNoOverflow()); + case RecurringInvoice::FREQUENCY_TWO_MONTHS: + return now()->diffInDays(now()->addMonthNoOverflow(2)); + case RecurringInvoice::FREQUENCY_THREE_MONTHS: + return now()->diffInDays(now()->addMonthNoOverflow(3)); + case RecurringInvoice::FREQUENCY_FOUR_MONTHS: + return now()->diffInDays(now()->addMonthNoOverflow(4)); + case RecurringInvoice::FREQUENCY_SIX_MONTHS: + return now()->diffInDays(now()->addMonthNoOverflow(6)); + case RecurringInvoice::FREQUENCY_ANNUALLY: + return now()->diffInDays(now()->addYear()); + case RecurringInvoice::FREQUENCY_TWO_YEARS: + return now()->diffInDays(now()->addYears(2)); + case RecurringInvoice::FREQUENCY_THREE_YEARS: + return now()->diffInDays(now()->addYears(3)); + default: + return 0; + } + } + +} \ No newline at end of file