From 0497089e27608a654cd19ab5228853fafdf9ca35 Mon Sep 17 00:00:00 2001 From: David Bomba Date: Thu, 12 Jan 2023 21:31:46 +1100 Subject: [PATCH] Fixes for pro rata calculations where discounts are involved --- .../Subscription/SubscriptionService.php | 33 ++++- tests/Unit/SubscriptionsCalcTest.php | 118 ++++++++++++++++++ 2 files changed, 149 insertions(+), 2 deletions(-) diff --git a/app/Services/Subscription/SubscriptionService.php b/app/Services/Subscription/SubscriptionService.php index b4902dc868..3af24a43ea 100644 --- a/app/Services/Subscription/SubscriptionService.php +++ b/app/Services/Subscription/SubscriptionService.php @@ -393,6 +393,8 @@ class SubscriptionService if(!$invoice) return []; + $handle_discount = false; + /* depending on whether we are creating an invoice or a credit*/ $multiplier = $is_credit ? 1 : -1; @@ -408,17 +410,27 @@ class SubscriptionService $line_items = []; + //Handle when we are refunding a discounted invoice. Need to consider the + //total discount and also the line item discount. + if($invoice->discount > 0) + $handle_discount = true; + + foreach($invoice->line_items as $item) { if($item->product_key != ctrans('texts.refund') && ($item->type_id == "1" || $item->type_id == "2")) { - $item->cost = ($item->cost*$ratio*$multiplier); + $discount_ratio = 1; + + if($handle_discount) + $discount_ratio = $this->calculateDiscountRatio($invoice); + + $item->cost = ($item->cost*$ratio*$multiplier*$discount_ratio); $item->product_key = ctrans('texts.refund'); $item->notes = ctrans('texts.refund') . ": ". $item->notes; - $line_items[] = $item; } @@ -428,6 +440,23 @@ class SubscriptionService } + + /** + * We only charge for the used days + * + * @param Invoice $invoice + * @return float + */ + public function calculateDiscountRatio($invoice) : float + { + + if($invoice->is_amount_discount) + return $invoice->discount / ($invoice->amount + $invoice->discount); + else + return $invoice->discount / 100; + + } + /** * We only charge for the used days * diff --git a/tests/Unit/SubscriptionsCalcTest.php b/tests/Unit/SubscriptionsCalcTest.php index 93ded70631..a944507c3a 100644 --- a/tests/Unit/SubscriptionsCalcTest.php +++ b/tests/Unit/SubscriptionsCalcTest.php @@ -11,6 +11,7 @@ namespace Tests\Unit; +use App\Factory\InvoiceItemFactory; use App\Helpers\Invoice\ProRata; use App\Helpers\Subscription\SubscriptionCalculator; use App\Models\Invoice; @@ -101,4 +102,121 @@ class SubscriptionsCalcTest extends TestCase // $this->assertEquals(3.23, $upgrade); } + + public function testProrataDiscountRatioPercentage() + { + + $subscription = Subscription::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'price' => 100, + ]); + + $item = InvoiceItemFactory::create(); + $item->quantity = 1; + + $item->cost = 100; + $item->product_key = 'xyz'; + $item->notes = 'test'; + $item->custom_value1 = 'x'; + $item->custom_value2 = 'x'; + $item->custom_value3 = 'x'; + $item->custom_value4 = 'x'; + + $line_items[] = $item; + + $invoice = Invoice::factory()->create([ + 'line_items' => $line_items, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'tax_rate1' => 0, + 'tax_name1' => '', + 'tax_rate2' => 0, + 'tax_name2' => '', + 'tax_rate3' => 0, + 'tax_name3' => '', + 'discount' => 0, + 'subscription_id' => $subscription->id, + 'date' => '2021-01-01', + 'discount' => 10, + 'is_amount_discount' => false, + 'status_id' => 1, + ]); + + $invoice = $invoice->calc()->getInvoice(); + $this->assertEquals(90, $invoice->amount); + $this->assertEquals(0, $invoice->balance); + + $invoice->service()->markSent()->save(); + + $this->assertEquals(90, $invoice->amount); + $this->assertEquals(90, $invoice->balance); + + + $ratio = $subscription->service()->calculateDiscountRatio($invoice); + + $this->assertEquals(.1, $ratio); + + } + + public function testProrataDiscountRatioAmount() + { + + $subscription = Subscription::factory()->create([ + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'price' => 100, + ]); + + $item = InvoiceItemFactory::create(); + $item->quantity = 1; + + $item->cost = 100; + $item->product_key = 'xyz'; + $item->notes = 'test'; + $item->custom_value1 = 'x'; + $item->custom_value2 = 'x'; + $item->custom_value3 = 'x'; + $item->custom_value4 = 'x'; + + $line_items[] = $item; + + $invoice = Invoice::factory()->create([ + 'line_items' => $line_items, + 'company_id' => $this->company->id, + 'user_id' => $this->user->id, + 'client_id' => $this->client->id, + 'tax_rate1' => 0, + 'tax_name1' => '', + 'tax_rate2' => 0, + 'tax_name2' => '', + 'tax_rate3' => 0, + 'tax_name3' => '', + 'discount' => 0, + 'subscription_id' => $subscription->id, + 'date' => '2021-01-01', + 'discount' => 20, + 'is_amount_discount' => true, + 'status_id' => 1, + ]); + + $invoice = $invoice->calc()->getInvoice(); + $this->assertEquals(80, $invoice->amount); + $this->assertEquals(0, $invoice->balance); + + $invoice->service()->markSent()->save(); + + $this->assertEquals(80, $invoice->amount); + $this->assertEquals(80, $invoice->balance); + + + $ratio = $subscription->service()->calculateDiscountRatio($invoice); + + $this->assertEquals(.2, $ratio); + + } + + + }