1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-09-20 08:21:34 +02:00

Fixes for pro rata calculations where discounts are involved

This commit is contained in:
David Bomba 2023-01-12 21:31:46 +11:00
parent fa668a4749
commit 0497089e27
2 changed files with 149 additions and 2 deletions

View File

@ -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
*

View File

@ -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);
}
}