mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-05-31 23:44:35 -04:00
Improve invoice calculations (#3007)
* Fixes for test * Invoice Items Inclusive Tax Calculator * Inclusive taxes * Invoice Inclusive Tax Tests * More tests * clean up * fixes for inclusive tests
This commit is contained in:
parent
02fadc8272
commit
d29f37ef8b
@ -29,9 +29,5 @@ trait Discounter
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// public function pro_rata_discount($amount)
|
|
||||||
// {
|
|
||||||
// return round(($this->invoice->discount/$this->getSubTotal() * $amount),2);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,436 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Invoice Ninja (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://opensource.org/licenses/AAL
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Helpers\Invoice;
|
|
||||||
|
|
||||||
use App\Helpers\Invoice\Discounter;
|
|
||||||
use App\Helpers\Invoice\InvoiceItemCalc;
|
|
||||||
use App\Models\Invoice;
|
|
||||||
use App\Utils\Traits\NumberFormatter;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class for invoice calculations.
|
|
||||||
*/
|
|
||||||
class InvoiceCalc
|
|
||||||
{
|
|
||||||
|
|
||||||
use NumberFormatter;
|
|
||||||
use Discounter;
|
|
||||||
|
|
||||||
protected $invoice;
|
|
||||||
|
|
||||||
protected $settings;
|
|
||||||
|
|
||||||
private $line_items;
|
|
||||||
|
|
||||||
private $item_discount;
|
|
||||||
|
|
||||||
private $balance;
|
|
||||||
|
|
||||||
private $paid_to_date;
|
|
||||||
|
|
||||||
private $amount;
|
|
||||||
|
|
||||||
private $sub_total;
|
|
||||||
|
|
||||||
private $total;
|
|
||||||
|
|
||||||
private $tax_map;
|
|
||||||
|
|
||||||
private $total_item_taxes;
|
|
||||||
|
|
||||||
private $total_taxes;
|
|
||||||
|
|
||||||
private $total_tax_map;
|
|
||||||
|
|
||||||
private $total_discount;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs the object with Invoice and Settings object
|
|
||||||
*
|
|
||||||
* @param \App\Models\Invoice $invoice The invoice
|
|
||||||
*/
|
|
||||||
public function __construct($invoice, $settings)
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->invoice = $invoice;
|
|
||||||
|
|
||||||
$this->settings = $settings;
|
|
||||||
|
|
||||||
$this->tax_map = new Collection;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the invoice values
|
|
||||||
*/
|
|
||||||
public function build()
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->calcLineItems()
|
|
||||||
->calcDiscount()
|
|
||||||
->calcCustomValues()
|
|
||||||
->calcBalance()
|
|
||||||
->calcPartial();
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the partial balance.
|
|
||||||
*
|
|
||||||
* @return self The partial.
|
|
||||||
*/
|
|
||||||
private function calcPartial()
|
|
||||||
{
|
|
||||||
if ( !isset($this->invoice->id) && isset($this->invoice->partial) ) {
|
|
||||||
$this->invoice->partial = max(0, min($this->formatValue($this->invoice->partial, 2), $this->invoice->balance));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the discount.
|
|
||||||
*
|
|
||||||
* @return self The discount.
|
|
||||||
*/
|
|
||||||
private function calcDiscount()
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->setTotalDiscount($this->discount($this->getSubTotal(), $this->invoice->discount, $this->invoice->is_amount_discount));
|
|
||||||
|
|
||||||
$this->setTotal( $this->getTotal() - $this->getTotalDiscount() );
|
|
||||||
|
|
||||||
/* Reduce all taxes */
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the balance.
|
|
||||||
*
|
|
||||||
* @return self The balance.
|
|
||||||
*/
|
|
||||||
private function calcBalance()
|
|
||||||
{
|
|
||||||
|
|
||||||
if(isset($this->invoice->id) && $this->invoice->id >= 1)
|
|
||||||
{
|
|
||||||
$this->balance = round($this->getTotal() - ($this->invoice->amount - $this->invoice->balance), 2);
|
|
||||||
} else {
|
|
||||||
$this->balance = $this->getTotal();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the custom values.
|
|
||||||
*
|
|
||||||
* @return self The custom values.
|
|
||||||
*/
|
|
||||||
private function calcCustomValues()
|
|
||||||
{
|
|
||||||
|
|
||||||
// custom fields charged taxes
|
|
||||||
if (isset($this->invoice->custom_value1) && property_exists($this->settings, 'custom_invoice_taxes1') && $this->settings->custom_invoice_taxes1 === true ) {
|
|
||||||
$this->setTotal($this->getTotal() + $this->invoice->custom_value1);
|
|
||||||
}
|
|
||||||
if (isset($this->invoice->custom_value2) && property_exists($this->settings, 'custom_invoice_taxes1') && $this->settings->custom_invoice_taxes2 === true) {
|
|
||||||
$this->setTotal($this->getTotal() + $this->invoice->custom_value2);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->calcTaxes();
|
|
||||||
|
|
||||||
// custom fields not charged taxes
|
|
||||||
if (isset($this->invoice->custom_value1) && property_exists($this->settings, 'custom_invoice_taxes1') && $this->settings->custom_invoice_taxes1 !== true) {
|
|
||||||
$this->setTotal($this->getTotal() + $this->invoice->custom_value1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($this->invoice->custom_value2) && property_exists($this->settings, 'custom_invoice_taxes1') && $this->settings->custom_invoice_taxes2 !== true) {
|
|
||||||
$this->setTotal($this->getTotal() + $this->invoice->custom_value2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the Invoice Level taxes.
|
|
||||||
*/
|
|
||||||
private function calcTaxes()
|
|
||||||
{
|
|
||||||
|
|
||||||
if (property_exists($this->settings, 'inclusive_taxes') && ! $this->settings->inclusive_taxes) {
|
|
||||||
|
|
||||||
$taxAmount1 = round($this->getSubTotal() * (($this->invoice->tax_rate1 ? $this->invoice->tax_rate1 : 0) / 100), 2);
|
|
||||||
$taxAmount1 -= $this->discount($taxAmount1, $this->invoice->discount, $this->invoice->is_amount_discount);
|
|
||||||
|
|
||||||
$tmp_array = [];
|
|
||||||
|
|
||||||
if($taxAmount1 > 0)
|
|
||||||
$tmp_array[] = ['name' => $this->invoice->tax_name1 . ' ' . $this->invoice->tax_rate1.'%', 'total' => $taxAmount1];
|
|
||||||
|
|
||||||
$taxAmount2 = round($this->getSubTotal() * (($this->invoice->tax_rate2 ? $this->invoice->tax_rate2 : 0) / 100), 2);
|
|
||||||
$taxAmount2 -= $this->discount($taxAmount2, $this->invoice->discount, $this->invoice->is_amount_discount);
|
|
||||||
|
|
||||||
if($taxAmount2 > 0)
|
|
||||||
$tmp_array[] = ['name' => $this->invoice->tax_name2 . ' ' . $this->invoice->tax_rate2.'%', 'total' => $taxAmount2];
|
|
||||||
|
|
||||||
$taxAmount3 = round($this->getSubTotal() * (($this->invoice->tax_rate3 ? $this->invoice->tax_rate3 : 0) / 100), 2);
|
|
||||||
$taxAmount3 -= $this->discount($taxAmount3, $this->invoice->discount, $this->invoice->is_amount_discount);
|
|
||||||
|
|
||||||
if($taxAmount3 > 0)
|
|
||||||
$tmp_array[] = ['name' => $this->invoice->tax_name3 . ' ' . $this->invoice->tax_rate3.'%', 'total' => $taxAmount3];
|
|
||||||
|
|
||||||
|
|
||||||
$this->setTotalTaxMap($tmp_array);
|
|
||||||
|
|
||||||
$this->setItemTotalTaxes($this->getItemTotalTaxes() + $taxAmount1 + $taxAmount2 + $taxAmount3);
|
|
||||||
|
|
||||||
$this->setTotal($this->getTotal() + $this->getItemTotalTaxes());
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculates the line items.
|
|
||||||
*
|
|
||||||
* @return self The line items.
|
|
||||||
*/
|
|
||||||
private function calcLineItems()
|
|
||||||
{
|
|
||||||
//if(!$this->invoice->line_items || !property_exists($this->invoice, 'line_items') || count($this->invoice->line_items) == 0)
|
|
||||||
if(!$this->invoice->line_items || count($this->invoice->line_items) == 0)
|
|
||||||
return $this;
|
|
||||||
|
|
||||||
$new_line_items = [];
|
|
||||||
|
|
||||||
foreach($this->invoice->line_items as $item) {
|
|
||||||
|
|
||||||
$item_calc = new InvoiceItemCalc($item, $this->settings, $this->invoice);
|
|
||||||
$item_calc->process();
|
|
||||||
|
|
||||||
$new_line_items[] = $item_calc->getLineItem();
|
|
||||||
|
|
||||||
//set collection of itemised taxes
|
|
||||||
$this->tax_map->push($item_calc->getGroupedTaxes());
|
|
||||||
|
|
||||||
//set running total of taxes
|
|
||||||
$this->total_item_taxes += $item_calc->getTotalTaxes();
|
|
||||||
|
|
||||||
$this->setItemTotalTaxes($this->getItemTotalTaxes() + ($item_calc->getTotalTaxes() - $this->discount($item_calc->getTotalTaxes(), $this->invoice->discount, $this->invoice->is_amount_discount)));
|
|
||||||
|
|
||||||
//set running total of item discounts
|
|
||||||
$this->item_discount += $item_calc->getTotalDiscounts();
|
|
||||||
|
|
||||||
//set running subtotal
|
|
||||||
$this->setSubTotal($this->getSubTotal() + $item_calc->getLineTotal());
|
|
||||||
|
|
||||||
$this->setTotal($this->getTotal() + $item_calc->getLineTotal());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->invoice->line_items = $new_line_items;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Getters and Setters
|
|
||||||
*/
|
|
||||||
|
|
||||||
public function getSubTotal()
|
|
||||||
{
|
|
||||||
return $this->sub_total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setSubTotal($value)
|
|
||||||
{
|
|
||||||
$this->sub_total = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTotalTaxMap()
|
|
||||||
{
|
|
||||||
return $this->total_tax_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTotalTaxMap($value)
|
|
||||||
{
|
|
||||||
$this->total_tax_map = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sums and reduces the line item taxes
|
|
||||||
*
|
|
||||||
* @return array The array of tax names and tax totals
|
|
||||||
*/
|
|
||||||
public function getTaxMap()
|
|
||||||
{
|
|
||||||
|
|
||||||
$keys = $this->tax_map->collapse()->pluck('key')->unique();
|
|
||||||
|
|
||||||
$values = $this->tax_map->collapse();
|
|
||||||
|
|
||||||
$tax_array = [];
|
|
||||||
|
|
||||||
foreach($keys as $key)
|
|
||||||
{
|
|
||||||
|
|
||||||
$tax_name = $values->filter(function ($value, $k) use($key){
|
|
||||||
return $value['key'] == $key;
|
|
||||||
})->pluck('tax_name')->first();
|
|
||||||
|
|
||||||
$total_line_tax = $values->filter(function ($value, $k) use($key){
|
|
||||||
return $value['key'] == $key;
|
|
||||||
})->sum('total');
|
|
||||||
|
|
||||||
$tax_array[] = ['name' => $tax_name, 'total' => $total_line_tax];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tax_array;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private function adjustTaxesWithDiscount($line_taxes)
|
|
||||||
{
|
|
||||||
return $line_taxes->transform(function($line_tax){
|
|
||||||
|
|
||||||
return $line_tax['total'] -= $this->discount($line_tax['total'], $this->invoice->discount, $this->invoice->is_amount_discount);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTaxMap($value)
|
|
||||||
{
|
|
||||||
$htis->tax_map = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTotalDiscount()
|
|
||||||
{
|
|
||||||
return $this->total_discount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTotalDiscount($value)
|
|
||||||
{
|
|
||||||
$this->total_discount = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getItemTotalTaxes()
|
|
||||||
{
|
|
||||||
return $this->total_taxes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setItemTotalTaxes($value)
|
|
||||||
{
|
|
||||||
$this->total_taxes = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTotalLineTaxes()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTotal()
|
|
||||||
{
|
|
||||||
return $this->total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTotal($value)
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->total = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBalance()
|
|
||||||
{
|
|
||||||
return $this->balance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setBalance($value)
|
|
||||||
{
|
|
||||||
$this->balance = $value;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getInvoice()
|
|
||||||
{
|
|
||||||
//Build invoice values here and return Invoice
|
|
||||||
$this->setCalculatedAttributes();
|
|
||||||
|
|
||||||
return $this->invoice;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build $this->invoice variables after
|
|
||||||
* calculations have been performed.
|
|
||||||
*/
|
|
||||||
private function setCalculatedAttributes()
|
|
||||||
{
|
|
||||||
/* If amount != balance then some money has been paid on the invoice, need to subtract this difference from the total to set the new balance */
|
|
||||||
if($this->invoice->amount != $this->invoice->balance)
|
|
||||||
{
|
|
||||||
$paid_to_date = $this->invoice->amount - $this->invoice->balance;
|
|
||||||
|
|
||||||
$this->invoice->balance = $this->getTotal() - $paid_to_date;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$this->invoice->balance = $this->getTotal();
|
|
||||||
|
|
||||||
/* Set new calculated total */
|
|
||||||
$this->invoice->amount = $this->getTotal();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
private function setDiscount($amount, $discount, $is_amount_discount)
|
|
||||||
{
|
|
||||||
|
|
||||||
if($is_amount_discount)
|
|
||||||
return $amount - $this->formatValue($discount);
|
|
||||||
else
|
|
||||||
return $amount - $this->formatValue($amount * $discount / 100);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,215 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Invoice Ninja (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
|
||||||
*
|
|
||||||
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
|
||||||
*
|
|
||||||
* @license https://opensource.org/licenses/AAL
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace App\Helpers\Invoice;
|
|
||||||
|
|
||||||
use App\Models\Invoice;
|
|
||||||
use App\Utils\Traits\NumberFormatter;
|
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class InvoiceItemCalc
|
|
||||||
{
|
|
||||||
|
|
||||||
use NumberFormatter;
|
|
||||||
|
|
||||||
protected $item;
|
|
||||||
|
|
||||||
protected $settings;
|
|
||||||
|
|
||||||
protected $invoice;
|
|
||||||
|
|
||||||
private $total_taxes;
|
|
||||||
|
|
||||||
private $total_discounts;
|
|
||||||
|
|
||||||
private $tax_collection;
|
|
||||||
|
|
||||||
private $line_total;
|
|
||||||
|
|
||||||
public function __construct(\stdClass $item, $settings, $invoice)
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->item = $item;
|
|
||||||
|
|
||||||
$this->settings = $settings;
|
|
||||||
|
|
||||||
$this->tax_collection = collect([]);
|
|
||||||
|
|
||||||
$this->invoice = $invoice;
|
|
||||||
|
|
||||||
$this->currency = $invoice->client->currency();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function process()
|
|
||||||
{
|
|
||||||
|
|
||||||
$this->setLineTotal($this->formatValue($this->item->cost, $this->currency->precision) * $this->formatValue($this->item->quantity, $this->currency->precision));
|
|
||||||
|
|
||||||
$this->setDiscount()
|
|
||||||
->calcTaxes();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private function setDiscount()
|
|
||||||
{
|
|
||||||
|
|
||||||
if(!isset($this->item->is_amount_discount))
|
|
||||||
return $this;
|
|
||||||
|
|
||||||
if($this->item->is_amount_discount)
|
|
||||||
{
|
|
||||||
$discountedTotal = $this->getLineTotal() - $this->formatValue($this->item->discount, $this->currency->precision);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$discountedTotal = $this->getLineTotal() - $this->formatValue(round($this->getLineTotal() * ($this->item->discount / 100),2), $this->currency->precision);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->setLineTotal($discountedTotal);
|
|
||||||
|
|
||||||
$totalDiscount = $this->getTotalDiscounts() + $discountedTotal;
|
|
||||||
|
|
||||||
$this->setTotalDiscounts($totalDiscount);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private function calcTaxes()
|
|
||||||
{
|
|
||||||
$item_tax = 0;
|
|
||||||
|
|
||||||
if(isset($this->item->tax_rate1) && $this->item->tax_rate1 > 0)
|
|
||||||
{
|
|
||||||
$tax_rate1 = $this->formatValue($this->item->tax_rate1, $this->currency->precision);
|
|
||||||
|
|
||||||
if($this->settings->inclusive_taxes)
|
|
||||||
$item_tax_rate1_total = $this->formatValue(($this->getLineTotal() - ($this->getLineTotal() / (1+$tax_rate1/100))) , $this->currency->precision);
|
|
||||||
else
|
|
||||||
$item_tax_rate1_total = $this->formatValue(($this->getLineTotal() * $tax_rate1/100), $this->currency->precision);
|
|
||||||
|
|
||||||
$item_tax += $item_tax_rate1_total;
|
|
||||||
|
|
||||||
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($this->item->tax_rate2) && $this->item->tax_rate2 > 0)
|
|
||||||
{
|
|
||||||
$tax_rate2 = $this->formatValue($this->item->tax_rate2, $this->currency->precision);
|
|
||||||
|
|
||||||
if($this->settings->inclusive_taxes)
|
|
||||||
$item_tax_rate2_total = $this->formatValue(($this->getLineTotal() - ($this->getLineTotal() / (1+$tax_rate2/100))) , $this->currency->precision);
|
|
||||||
else
|
|
||||||
$item_tax_rate2_total = $this->formatValue(($this->getLineTotal() * $tax_rate2/100), $this->currency->precision);
|
|
||||||
|
|
||||||
$item_tax += $item_tax_rate2_total;
|
|
||||||
|
|
||||||
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isset($this->item->tax_rate3) && $this->item->tax_rate3 > 0)
|
|
||||||
{
|
|
||||||
$tax_rate3 = $this->formatValue($this->item->tax_rate3, $this->currency->precision);
|
|
||||||
|
|
||||||
if($this->settings->inclusive_taxes)
|
|
||||||
$item_tax_rate3_total = $this->formatValue(($this->getLineTotal() - ($this->getLineTotal() / (1+$tax_rate3/100))) , $this->currency->precision);
|
|
||||||
else
|
|
||||||
$item_tax_rate3_total = $this->formatValue(($this->getLineTotal() * $tax_rate3/100), $this->currency->precision);
|
|
||||||
|
|
||||||
$item_tax += $item_tax_rate3_total;
|
|
||||||
|
|
||||||
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$this->setTotalTaxes($item_tax);
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function groupTax($tax_name, $tax_rate, $tax_total)
|
|
||||||
{
|
|
||||||
$group_tax = [];
|
|
||||||
|
|
||||||
$key = str_replace(" ", "", $tax_name.$tax_rate);
|
|
||||||
|
|
||||||
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name . ' ' . $tax_rate.'%'];
|
|
||||||
|
|
||||||
$this->tax_collection->push(collect($group_tax));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
|
||||||
*
|
|
||||||
* Getters and Setters
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public function getLineItem()
|
|
||||||
{
|
|
||||||
|
|
||||||
return $this->item;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getLineTotal()
|
|
||||||
{
|
|
||||||
return $this->item->line_total;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setLineTotal($total)
|
|
||||||
{
|
|
||||||
$this->item->line_total = $total;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTotalTaxes()
|
|
||||||
{
|
|
||||||
return $this->total_taxes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTotalTaxes($total)
|
|
||||||
{
|
|
||||||
$this->total_taxes = $total;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTotalDiscounts()
|
|
||||||
{
|
|
||||||
return $this->total_discounts;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setTotalDiscounts($total)
|
|
||||||
{
|
|
||||||
$this->total_discounts = $total;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getGroupedTaxes()
|
|
||||||
{
|
|
||||||
return $this->tax_collection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setGroupedTaxes($group_taxes)
|
|
||||||
{
|
|
||||||
$this->tax_collection = $group_taxes;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -55,13 +55,14 @@ class InvoiceItemSum
|
|||||||
|
|
||||||
$this->invoice = $invoice;
|
$this->invoice = $invoice;
|
||||||
|
|
||||||
$this->currency = $invoice->client->currency();
|
$this->currency = $this->invoice->client->currency();
|
||||||
|
|
||||||
$this->line_items = [];
|
$this->line_items = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function process()
|
public function process()
|
||||||
{
|
{
|
||||||
|
|
||||||
if(!$this->invoice->line_items || count($this->invoice->line_items) == 0){
|
if(!$this->invoice->line_items || count($this->invoice->line_items) == 0){
|
||||||
$this->items = [];
|
$this->items = [];
|
||||||
return $this;
|
return $this;
|
||||||
|
275
app/Helpers/Invoice/InvoiceItemSumInclusive.php
Normal file
275
app/Helpers/Invoice/InvoiceItemSumInclusive.php
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Helpers\Invoice;
|
||||||
|
|
||||||
|
use App\Helpers\Invoice\Discounter;
|
||||||
|
use App\Helpers\Invoice\Taxer;
|
||||||
|
use App\Models\Invoice;
|
||||||
|
use App\Utils\Traits\NumberFormatter;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class InvoiceItemSumInclusive
|
||||||
|
{
|
||||||
|
|
||||||
|
use NumberFormatter;
|
||||||
|
use Discounter;
|
||||||
|
use Taxer;
|
||||||
|
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
protected $invoice;
|
||||||
|
|
||||||
|
private $items;
|
||||||
|
|
||||||
|
private $line_total;
|
||||||
|
|
||||||
|
private $currency;
|
||||||
|
|
||||||
|
private $total_taxes;
|
||||||
|
|
||||||
|
private $item;
|
||||||
|
|
||||||
|
private $line_items;
|
||||||
|
|
||||||
|
private $sub_total;
|
||||||
|
|
||||||
|
private $total_discount;
|
||||||
|
|
||||||
|
private $tax_collection;
|
||||||
|
|
||||||
|
public function __construct($invoice, $settings)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->settings = $settings;
|
||||||
|
|
||||||
|
$this->tax_collection = collect([]);
|
||||||
|
|
||||||
|
$this->invoice = $invoice;
|
||||||
|
|
||||||
|
$this->currency = $this->invoice->client->currency();
|
||||||
|
|
||||||
|
$this->line_items = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function process()
|
||||||
|
{
|
||||||
|
|
||||||
|
if(!$this->invoice->line_items || count($this->invoice->line_items) == 0){
|
||||||
|
$this->items = [];
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->calcLineItems();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calcLineItems()
|
||||||
|
{
|
||||||
|
foreach($this->invoice->line_items as $this->item)
|
||||||
|
{
|
||||||
|
$this->sumLineItem()
|
||||||
|
->setDiscount()
|
||||||
|
->calcTaxes()
|
||||||
|
->push();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function push()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->sub_total += $this->getLineTotal();
|
||||||
|
|
||||||
|
$this->line_items[] = $this->item;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function sumLineItem()
|
||||||
|
{
|
||||||
|
$this->setLineTotal($this->formatValue($this->item->cost, $this->currency->precision) * $this->formatValue($this->item->quantity, $this->currency->precision));
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setDiscount()
|
||||||
|
{
|
||||||
|
|
||||||
|
if($this->invoice->is_amount_discount)
|
||||||
|
{
|
||||||
|
$this->setLineTotal($this->getLineTotal() - $this->formatValue($this->item->discount, $this->currency->precision));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->setLineTotal($this->getLineTotal() - $this->formatValue(($this->item->line_total * ($this->item->discount / 100)), $this->currency->precision));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->item->is_amount_discount = $this->invoice->is_amount_discount;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Taxes effect the line totals and item costs. we decrement both on
|
||||||
|
* application of inclusive tax rates.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function calcTaxes()
|
||||||
|
{
|
||||||
|
|
||||||
|
$item_tax = 0;
|
||||||
|
|
||||||
|
$amount = $this->item->line_total - ($this->item->line_total * ($this->invoice->discount/100));
|
||||||
|
|
||||||
|
$item_tax_rate1_total = $this->calcInclusiveLineTax($this->item->tax_rate1, $amount);
|
||||||
|
|
||||||
|
$item_tax += $this->formatValue($item_tax_rate1_total, $this->currency->precision);
|
||||||
|
|
||||||
|
if($item_tax_rate1_total > 0)
|
||||||
|
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
|
||||||
|
|
||||||
|
$item_tax_rate2_total = $this->calcInclusiveLineTax($this->item->tax_rate2, $amount);
|
||||||
|
|
||||||
|
$item_tax += $this->formatValue($item_tax_rate2_total, $this->currency->precision);
|
||||||
|
|
||||||
|
if($item_tax_rate2_total > 0)
|
||||||
|
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
|
||||||
|
|
||||||
|
$item_tax_rate3_total = $this->calcInclusiveLineTax($this->item->tax_rate3, $amount);
|
||||||
|
|
||||||
|
$item_tax += $this->formatValue($item_tax_rate3_total, $this->currency->precision);
|
||||||
|
|
||||||
|
if($item_tax_rate3_total > 0)
|
||||||
|
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
|
||||||
|
|
||||||
|
$this->setTotalTaxes($this->formatValue($item_tax, $this->currency->precision));
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function groupTax($tax_name, $tax_rate, $tax_total)
|
||||||
|
{
|
||||||
|
$group_tax = [];
|
||||||
|
|
||||||
|
$key = str_replace(" ", "", $tax_name.$tax_rate);
|
||||||
|
|
||||||
|
$group_tax = ['key' => $key, 'total' => $tax_total, 'tax_name' => $tax_name . ' ' . $tax_rate.'%'];
|
||||||
|
|
||||||
|
$this->tax_collection->push(collect($group_tax));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotalTaxes()
|
||||||
|
{
|
||||||
|
return $this->total_taxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTotalTaxes($total)
|
||||||
|
{
|
||||||
|
$this->total_taxes = $total;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLineTotal($total)
|
||||||
|
{
|
||||||
|
$this->item->line_total = $total;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLineTotal()
|
||||||
|
{
|
||||||
|
return $this->item->line_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLineItems()
|
||||||
|
{
|
||||||
|
return $this->line_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroupedTaxes()
|
||||||
|
{
|
||||||
|
return $this->tax_collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupedTaxes($group_taxes)
|
||||||
|
{
|
||||||
|
$this->tax_collection = $group_taxes;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubTotal()
|
||||||
|
{
|
||||||
|
return $this->sub_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSubTotal($value)
|
||||||
|
{
|
||||||
|
$this->sub_total = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice Amount Discount
|
||||||
|
*
|
||||||
|
* The problem, when calculating invoice level discounts,
|
||||||
|
* the tax collected changes.
|
||||||
|
*
|
||||||
|
* We need to synthetically reduce the line_total amounts
|
||||||
|
* and recalculate the taxes and then pass back
|
||||||
|
* the updated map
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function calcTaxesWithAmountDiscount()
|
||||||
|
{
|
||||||
|
$this->setGroupedTaxes(collect([]));
|
||||||
|
|
||||||
|
$item_tax = 0;
|
||||||
|
|
||||||
|
foreach($this->line_items as $this->item)
|
||||||
|
{
|
||||||
|
|
||||||
|
$amount = $this->item->line_total - ($this->item->line_total * ($this->invoice->discount/$this->sub_total));
|
||||||
|
$item_tax_rate1_total = $this->calcInclusiveLineTax($this->item->tax_rate1, $amount);
|
||||||
|
|
||||||
|
$item_tax += $item_tax_rate1_total;
|
||||||
|
|
||||||
|
if($item_tax_rate1_total > 0)
|
||||||
|
$this->groupTax($this->item->tax_name1, $this->item->tax_rate1, $item_tax_rate1_total);
|
||||||
|
|
||||||
|
$item_tax_rate2_total = $this->calcInclusiveLineTax($this->item->tax_rate2, $amount);
|
||||||
|
|
||||||
|
$item_tax += $item_tax_rate2_total;
|
||||||
|
|
||||||
|
if($item_tax_rate2_total > 0)
|
||||||
|
$this->groupTax($this->item->tax_name2, $this->item->tax_rate2, $item_tax_rate2_total);
|
||||||
|
|
||||||
|
$item_tax_rate3_total = $this->calcInclusiveLineTax($this->item->tax_rate3, $amount);
|
||||||
|
|
||||||
|
$item_tax += $item_tax_rate3_total;
|
||||||
|
|
||||||
|
if($item_tax_rate3_total > 0)
|
||||||
|
$this->groupTax($this->item->tax_name3, $this->item->tax_rate3, $item_tax_rate3_total);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setTotalTaxes($item_tax);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
296
app/Helpers/Invoice/InvoiceSumInclusive.php
Normal file
296
app/Helpers/Invoice/InvoiceSumInclusive.php
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2019. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://opensource.org/licenses/AAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Helpers\Invoice;
|
||||||
|
|
||||||
|
use App\Helpers\Invoice\Balancer;
|
||||||
|
use App\Helpers\Invoice\CustomValuer;
|
||||||
|
use App\Helpers\Invoice\Discounter;
|
||||||
|
use App\Helpers\Invoice\InvoiceItemSum;
|
||||||
|
use App\Helpers\Invoice\InvoiceItemSumInclusive;
|
||||||
|
use App\Helpers\Invoice\Taxer;
|
||||||
|
use App\Utils\Traits\NumberFormatter;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
|
class InvoiceSumInclusive
|
||||||
|
{
|
||||||
|
use Taxer;
|
||||||
|
use Balancer;
|
||||||
|
use CustomValuer;
|
||||||
|
use Discounter;
|
||||||
|
|
||||||
|
use NumberFormatter;
|
||||||
|
|
||||||
|
protected $invoice;
|
||||||
|
|
||||||
|
protected $settings;
|
||||||
|
|
||||||
|
public $tax_map;
|
||||||
|
|
||||||
|
public $invoice_item;
|
||||||
|
|
||||||
|
public $total_taxes;
|
||||||
|
|
||||||
|
private $total;
|
||||||
|
|
||||||
|
private $total_discount;
|
||||||
|
|
||||||
|
private $total_custom_values;
|
||||||
|
|
||||||
|
private $total_tax_map;
|
||||||
|
|
||||||
|
private $sub_total;
|
||||||
|
/**
|
||||||
|
* Constructs the object with Invoice and Settings object
|
||||||
|
*
|
||||||
|
* @param \App\Models\Invoice $invoice The invoice
|
||||||
|
*/
|
||||||
|
public function __construct($invoice, $settings)
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->invoice = $invoice;
|
||||||
|
|
||||||
|
$this->settings = $settings;
|
||||||
|
|
||||||
|
$this->tax_map = new Collection;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function build()
|
||||||
|
{
|
||||||
|
$this->calculateLineItems()
|
||||||
|
->calculateDiscount()
|
||||||
|
->calculateCustomValues()
|
||||||
|
->calculateInvoiceTaxes()
|
||||||
|
->setTaxMap()
|
||||||
|
// ->calculateTotals()
|
||||||
|
->calculateBalance()
|
||||||
|
->calculatePartial();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateLineItems()
|
||||||
|
{
|
||||||
|
$this->invoice_items = new InvoiceItemSumInclusive($this->invoice, $this->settings);
|
||||||
|
$this->invoice_items->process();
|
||||||
|
$this->invoice->line_items = $this->invoice_items->getLineItems();
|
||||||
|
$this->total = $this->invoice_items->getSubTotal();
|
||||||
|
$this->setSubTotal($this->invoice_items->getSubTotal());
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateDiscount()
|
||||||
|
{
|
||||||
|
$this->total_discount = $this->discount($this->invoice_items->getSubTotal());
|
||||||
|
|
||||||
|
$this->total -= $this->total_discount;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateCustomValues()
|
||||||
|
{
|
||||||
|
$this->total_taxes += $this->valuerTax($this->invoice->custom_value1, $this->settings->custom_invoice_taxes1);
|
||||||
|
$this->total_custom_values += $this->valuer($this->invoice->custom_value1);
|
||||||
|
|
||||||
|
$this->total_taxes += $this->valuerTax($this->invoice->custom_value2, $this->settings->custom_invoice_taxes2);
|
||||||
|
$this->total_custom_values += $this->valuer($this->invoice->custom_value2);
|
||||||
|
|
||||||
|
$this->total_taxes += $this->valuerTax($this->invoice->custom_value3, $this->settings->custom_invoice_taxes3);
|
||||||
|
$this->total_custom_values += $this->valuer($this->invoice->custom_value3);
|
||||||
|
|
||||||
|
$this->total_taxes += $this->valuerTax($this->invoice->custom_value4, $this->settings->custom_invoice_taxes4);
|
||||||
|
$this->total_custom_values += $this->valuer($this->invoice->custom_value4);
|
||||||
|
|
||||||
|
$this->total += $this->total_custom_values;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateInvoiceTaxes()
|
||||||
|
{
|
||||||
|
$amount = $this->total;
|
||||||
|
|
||||||
|
if($this->invoice->discount > 0 && $this->invoice->is_amount_discount)
|
||||||
|
$amount = $this->formatValue(($this->sub_total - $this->invoice->discount),2);
|
||||||
|
|
||||||
|
if($this->invoice->discount > 0 && !$this->invoice->is_amount_discount)
|
||||||
|
$amount = $this->formatValue(($this->sub_total - ($this->sub_total * ($this->invoice->discount/100))),2);
|
||||||
|
|
||||||
|
if($this->invoice->tax_rate1 > 0){
|
||||||
|
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate1, $amount);
|
||||||
|
$this->total_taxes += $tax;
|
||||||
|
|
||||||
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name1 . ' ' . $this->invoice->tax_rate1.'%', 'total' => $tax];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if($this->invoice->tax_rate2 > 0){
|
||||||
|
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate2, $amount);
|
||||||
|
$this->total_taxes += $tax;
|
||||||
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name2. ' ' . $this->invoice->tax_rate2.'%', 'total' => $tax];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->invoice->tax_rate3 > 0){
|
||||||
|
$tax = $this->calcInclusiveLineTax($this->invoice->tax_rate3, $amount);
|
||||||
|
$this->total_taxes += $tax;
|
||||||
|
$this->total_tax_map[] = ['name' => $this->invoice->tax_name3 . ' ' . $this->invoice->tax_rate3.'%', 'total' => $tax];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the balance.
|
||||||
|
*
|
||||||
|
* @return self The balance.
|
||||||
|
*/
|
||||||
|
private function calculateBalance()
|
||||||
|
{
|
||||||
|
//$this->invoice->balance = $this->balance($this->getTotal(), $this->invoice);
|
||||||
|
$this->setCalculatedAttributes();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculatePartial()
|
||||||
|
{
|
||||||
|
if ( !isset($this->invoice->id) && isset($this->invoice->partial) ) {
|
||||||
|
$this->invoice->partial = max(0, min($this->formatValue($this->invoice->partial, 2), $this->invoice->balance));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateTotals()
|
||||||
|
{
|
||||||
|
$this->total += $this->total_taxes;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInvoice()
|
||||||
|
{
|
||||||
|
//Build invoice values here and return Invoice
|
||||||
|
$this->setCalculatedAttributes();
|
||||||
|
$this->invoice->save();
|
||||||
|
|
||||||
|
return $this->invoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build $this->invoice variables after
|
||||||
|
* calculations have been performed.
|
||||||
|
*/
|
||||||
|
private function setCalculatedAttributes()
|
||||||
|
{
|
||||||
|
/* If amount != balance then some money has been paid on the invoice, need to subtract this difference from the total to set the new balance */
|
||||||
|
if($this->invoice->amount != $this->invoice->balance)
|
||||||
|
{
|
||||||
|
$paid_to_date = $this->invoice->amount - $this->invoice->balance;
|
||||||
|
|
||||||
|
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision) - $paid_to_date;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$this->invoice->balance = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||||
|
|
||||||
|
/* Set new calculated total */
|
||||||
|
$this->invoice->amount = $this->formatValue($this->getTotal(), $this->invoice->client->currency()->precision);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubTotal()
|
||||||
|
{
|
||||||
|
return $this->sub_total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSubTotal($value)
|
||||||
|
{
|
||||||
|
$this->sub_total = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotalDiscount()
|
||||||
|
{
|
||||||
|
return $this->total_discount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotalTaxes()
|
||||||
|
{
|
||||||
|
return $this->total_taxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotalTaxMap()
|
||||||
|
{
|
||||||
|
return $this->total_tax_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTotal()
|
||||||
|
{
|
||||||
|
return $this->total;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTaxMap()
|
||||||
|
{
|
||||||
|
if($this->invoice->is_amount_discount == true)
|
||||||
|
$this->invoice_items->calcTaxesWithAmountDiscount();
|
||||||
|
|
||||||
|
$this->tax_map = collect();
|
||||||
|
|
||||||
|
$keys = $this->invoice_items->getGroupedTaxes()->pluck('key')->unique();
|
||||||
|
|
||||||
|
$values = $this->invoice_items->getGroupedTaxes();
|
||||||
|
|
||||||
|
foreach($keys as $key)
|
||||||
|
{
|
||||||
|
|
||||||
|
$tax_name = $values->filter(function ($value, $k) use($key){
|
||||||
|
return $value['key'] == $key;
|
||||||
|
})->pluck('tax_name')->first();
|
||||||
|
|
||||||
|
$total_line_tax = $values->filter(function ($value, $k) use($key){
|
||||||
|
return $value['key'] == $key;
|
||||||
|
})->sum('total');
|
||||||
|
|
||||||
|
//$total_line_tax -= $this->discount($total_line_tax);
|
||||||
|
|
||||||
|
$this->tax_map[] = ['name' => $tax_name, 'total' => $total_line_tax];
|
||||||
|
|
||||||
|
$this->total_taxes += $total_line_tax;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTaxMap()
|
||||||
|
{
|
||||||
|
return $this->tax_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBalance()
|
||||||
|
{
|
||||||
|
return $this->invoice->balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getItemTotalTaxes()
|
||||||
|
{
|
||||||
|
return $this->getTotalTaxes();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -24,7 +24,13 @@ trait Taxer
|
|||||||
|
|
||||||
public function calcAmountLineTax($tax_rate, $amount)
|
public function calcAmountLineTax($tax_rate, $amount)
|
||||||
{
|
{
|
||||||
return $this->formatValue(($amount * $tax_rate/100), 4);
|
return $this->formatValue(($amount * $tax_rate/100), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function calcInclusiveLineTax($tax_rate, $amount)
|
||||||
|
{
|
||||||
|
return $this->formatValue($amount - ($amount / (1 + ($tax_rate/100))), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Events\Invoice\InvoiceWasUpdated;
|
use App\Events\Invoice\InvoiceWasUpdated;
|
||||||
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
|
use App\Helpers\Invoice\InvoiceSumInclusive;
|
||||||
use App\Models\Currency;
|
use App\Models\Currency;
|
||||||
use App\Models\Filterable;
|
use App\Models\Filterable;
|
||||||
use App\Models\PaymentTerm;
|
use App\Models\PaymentTerm;
|
||||||
@ -19,7 +21,6 @@ use App\Utils\Number;
|
|||||||
use App\Utils\Traits\MakesDates;
|
use App\Utils\Traits\MakesDates;
|
||||||
use App\Utils\Traits\MakesInvoiceValues;
|
use App\Utils\Traits\MakesInvoiceValues;
|
||||||
use App\Utils\Traits\NumberFormatter;
|
use App\Utils\Traits\NumberFormatter;
|
||||||
use App\Helpers\Invoice\InvoiceSum;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
@ -267,9 +268,12 @@ class Invoice extends BaseModel
|
|||||||
*/
|
*/
|
||||||
public function calc()
|
public function calc()
|
||||||
{
|
{
|
||||||
//todo will need to switch between inclusive and exclusive implementations of InvoiceSum
|
$invoice_calc = null;
|
||||||
|
|
||||||
$invoice_calc = new InvoiceSum($this, $this->settings);
|
if($this->settings->inclusive_taxes)
|
||||||
|
$invoice_calc = new InvoiceSumInclusive($this, $this->settings);
|
||||||
|
else
|
||||||
|
$invoice_calc = new InvoiceSum($this, $this->settings);
|
||||||
|
|
||||||
return $invoice_calc->build();
|
return $invoice_calc->build();
|
||||||
|
|
||||||
|
@ -75,9 +75,11 @@ class InvoiceRepository extends BaseRepository
|
|||||||
|
|
||||||
event(new CreateInvoiceInvitation($invoice));
|
event(new CreateInvoiceInvitation($invoice));
|
||||||
|
|
||||||
$invoice_calc = new InvoiceSum($invoice, $invoice->settings);
|
$invoice = $invoice->calc()->getInvoice();
|
||||||
|
|
||||||
|
// $invoice_calc = new InvoiceSum($invoice, $invoice->settings);
|
||||||
|
|
||||||
$invoice = $invoice_calc->build()->getInvoice();
|
// $invoice = $invoice_calc->build()->getInvoice();
|
||||||
|
|
||||||
$invoice->save();
|
$invoice->save();
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class CompanyGatewayTransformer extends EntityTransformer
|
|||||||
'min_limit' => (float)$company_gateway->min_limit,
|
'min_limit' => (float)$company_gateway->min_limit,
|
||||||
'max_limit' => (float)$company_gateway->max_limit,
|
'max_limit' => (float)$company_gateway->max_limit,
|
||||||
'fee_amount' => (float) $company_gateway->fee_amount,
|
'fee_amount' => (float) $company_gateway->fee_amount,
|
||||||
'fee_percent' => (float)$company_gateway->fee_percent ?: '',
|
'fee_percent' => (float)$company_gateway->fee_percent,
|
||||||
'fee_tax_name1' => (string)$company_gateway->fee_tax_name1 ?: '',
|
'fee_tax_name1' => (string)$company_gateway->fee_tax_name1 ?: '',
|
||||||
'fee_tax_name2' => (string) $company_gateway->fee_tax_name2 ?: '',
|
'fee_tax_name2' => (string) $company_gateway->fee_tax_name2 ?: '',
|
||||||
'fee_tax_name3' => (string) $company_gateway->fee_tax_name3 ?: '',
|
'fee_tax_name3' => (string) $company_gateway->fee_tax_name3 ?: '',
|
||||||
|
@ -369,10 +369,10 @@ class CreateUsersTable extends Migration
|
|||||||
$table->text('config');
|
$table->text('config');
|
||||||
$table->unsignedInteger('priority_id')->default(0);
|
$table->unsignedInteger('priority_id')->default(0);
|
||||||
|
|
||||||
$table->decimal('min_limit', 13, 2)->nullable();
|
$table->decimal('min_limit', 13, 2)->default(0);
|
||||||
$table->decimal('max_limit', 13, 2)->nullable();
|
$table->decimal('max_limit', 13, 2)->default(0);
|
||||||
$table->decimal('fee_amount', 13, 2)->nullable();
|
$table->decimal('fee_amount', 13, 2)->default(0);
|
||||||
$table->decimal('fee_percent', 13, 2)->nullable();
|
$table->decimal('fee_percent', 13, 2)->default(0);
|
||||||
$table->string('fee_tax_name1')->nullable();
|
$table->string('fee_tax_name1')->nullable();
|
||||||
$table->string('fee_tax_name2')->nullable();
|
$table->string('fee_tax_name2')->nullable();
|
||||||
$table->string('fee_tax_name3')->nullable();
|
$table->string('fee_tax_name3')->nullable();
|
||||||
@ -380,7 +380,7 @@ class CreateUsersTable extends Migration
|
|||||||
$table->decimal('fee_tax_rate2', 13, 2)->nullable();
|
$table->decimal('fee_tax_rate2', 13, 2)->nullable();
|
||||||
$table->decimal('fee_tax_rate3', 13, 2)->nullable();
|
$table->decimal('fee_tax_rate3', 13, 2)->nullable();
|
||||||
$table->unsignedInteger('fee_cap')->default(0);
|
$table->unsignedInteger('fee_cap')->default(0);
|
||||||
$table->boolean('adjust_fee_percent');
|
$table->boolean('adjust_fee_percent')->default(false);
|
||||||
|
|
||||||
$table->timestamps(6);
|
$table->timestamps(6);
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
|
@ -7,6 +7,7 @@ use App\Events\Invoice\InvoiceWasMarkedSent;
|
|||||||
use App\Events\Invoice\InvoiceWasUpdated;
|
use App\Events\Invoice\InvoiceWasUpdated;
|
||||||
use App\Events\Payment\PaymentWasCreated;
|
use App\Events\Payment\PaymentWasCreated;
|
||||||
use App\Helpers\Invoice\InvoiceSum;
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
|
use App\Helpers\Invoice\InvoiceSumInclusive;
|
||||||
use App\Jobs\Company\UpdateCompanyLedgerWithInvoice;
|
use App\Jobs\Company\UpdateCompanyLedgerWithInvoice;
|
||||||
use App\Jobs\Invoice\UpdateInvoicePayment;
|
use App\Jobs\Invoice\UpdateInvoicePayment;
|
||||||
use App\Listeners\Invoice\CreateInvoiceInvitation;
|
use App\Listeners\Invoice\CreateInvoiceInvitation;
|
||||||
@ -120,11 +121,17 @@ class RandomDataSeeder extends Seeder
|
|||||||
|
|
||||||
$invoices->each(function ($invoice) use($invoice_repo, $user, $company, $client){
|
$invoices->each(function ($invoice) use($invoice_repo, $user, $company, $client){
|
||||||
|
|
||||||
//$settings = $invoice->settings;
|
$settings = $invoice->settings;
|
||||||
//$settings->inclusive_taxes = (bool)random_int(0, 1);
|
//$settings->inclusive_taxes = (bool)random_int(0, 1);
|
||||||
//$invoice->settings = $settings;
|
$settings->inclusive_taxes = true;
|
||||||
|
$invoice->settings = $settings;
|
||||||
|
|
||||||
$invoice_calc = new InvoiceSum($invoice, $invoice->settings);
|
$invoice_calc = null;
|
||||||
|
|
||||||
|
if($settings->inclusive_taxes)
|
||||||
|
$invoice_calc = new InvoiceSumInclusive($invoice, $invoice->settings);
|
||||||
|
else
|
||||||
|
$invoice_calc = new InvoiceSum($invoice, $invoice->settings);
|
||||||
|
|
||||||
$invoice = $invoice_calc->build()->getInvoice();
|
$invoice = $invoice_calc->build()->getInvoice();
|
||||||
|
|
||||||
|
@ -36,15 +36,11 @@ class MarkInvoicePaidTest extends TestCase
|
|||||||
|
|
||||||
public function testMarkInvoicePaidInvoice()
|
public function testMarkInvoicePaidInvoice()
|
||||||
{
|
{
|
||||||
\Log::error($this->invoice->amount);
|
|
||||||
\Log::error($this->invoice->balance);
|
|
||||||
MarkInvoicePaid::dispatchNow($this->invoice);
|
MarkInvoicePaid::dispatchNow($this->invoice);
|
||||||
|
|
||||||
$invoice = Invoice::find($this->invoice->id);
|
$invoice = Invoice::find($this->invoice->id);
|
||||||
|
|
||||||
\Log::error($invoice->amount);
|
|
||||||
\Log::error($invoice->balance);
|
|
||||||
|
|
||||||
$this->assertEquals(0.00, $invoice->balance);
|
$this->assertEquals(0.00, $invoice->balance);
|
||||||
|
|
||||||
$this->assertEquals(1, count($invoice->payments));
|
$this->assertEquals(1, count($invoice->payments));
|
||||||
|
@ -31,7 +31,6 @@ use App\Utils\Traits\GeneratesCounter;
|
|||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
use App\Helpers\Invoice\InvoiceSum;
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class MockAccountData
|
* Class MockAccountData
|
||||||
@ -99,9 +98,7 @@ trait MockAccountData
|
|||||||
|
|
||||||
$this->client->group_settings_id = $gs->id;
|
$this->client->group_settings_id = $gs->id;
|
||||||
$this->client->save();
|
$this->client->save();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$this->invoice = InvoiceFactory::create($this->company->id,$this->user->id);//stub the company and user_id
|
$this->invoice = InvoiceFactory::create($this->company->id,$this->user->id);//stub the company and user_id
|
||||||
$this->invoice->client_id = $this->client->id;
|
$this->invoice->client_id = $this->client->id;
|
||||||
|
|
||||||
@ -115,6 +112,7 @@ trait MockAccountData
|
|||||||
$this->settings->precision = 2;
|
$this->settings->precision = 2;
|
||||||
|
|
||||||
$this->invoice->settings = $this->settings;
|
$this->invoice->settings = $this->settings;
|
||||||
|
$this->invoice->save();
|
||||||
|
|
||||||
$this->invoice_calc = new InvoiceSum($this->invoice, $this->settings);
|
$this->invoice_calc = new InvoiceSum($this->invoice, $this->settings);
|
||||||
$this->invoice_calc->build();
|
$this->invoice_calc->build();
|
||||||
|
377
tests/Unit/InvoiceInclusiveTest.php
Normal file
377
tests/Unit/InvoiceInclusiveTest.php
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Factory\InvoiceFactory;
|
||||||
|
use App\Factory\InvoiceItemFactory;
|
||||||
|
use App\Helpers\Invoice\InvoiceSum;
|
||||||
|
use App\Helpers\Invoice\InvoiceSumInclusive;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\MockAccountData;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @covers App\Helpers\Invoice\InvoiceSumInclusive
|
||||||
|
*/
|
||||||
|
class InvoiceInclusiveTest extends TestCase
|
||||||
|
{
|
||||||
|
use MockAccountData;
|
||||||
|
use DatabaseTransactions;
|
||||||
|
|
||||||
|
public $invoice;
|
||||||
|
|
||||||
|
public $invoice_calc;
|
||||||
|
|
||||||
|
public $settings;
|
||||||
|
|
||||||
|
public function setUp() :void
|
||||||
|
{
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->makeTestData();
|
||||||
|
|
||||||
|
$this->invoice->line_items = $this->buildLineItems();
|
||||||
|
|
||||||
|
$this->settings = $this->invoice->settings;
|
||||||
|
|
||||||
|
$this->settings->inclusive_taxes = true;
|
||||||
|
$this->settings->precision = 2;
|
||||||
|
|
||||||
|
$this->invoice_calc = new InvoiceSumInclusive($this->invoice, $this->settings);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildLineItems()
|
||||||
|
{
|
||||||
|
$line_items = [];
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
return $line_items;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceTotals()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceTotalsWithDiscount()
|
||||||
|
{
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 15);
|
||||||
|
$this->assertEquals($this->invoice_calc->getBalance(), 15);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceTotalsWithDiscountWithSurcharge()
|
||||||
|
{
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
$this->invoice->custom_value1 = 5;
|
||||||
|
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getBalance(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceTotalsWithDiscountWithSurchargeWithInclusiveTax()
|
||||||
|
{
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
$this->invoice->custom_value1 = 5;
|
||||||
|
$this->invoice->tax_name1 = 'GST';
|
||||||
|
$this->invoice->tax_rate1 = 10;
|
||||||
|
$this->invoice->is_amount_discount = true;
|
||||||
|
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalTaxes(), 1.36);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getBalance(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceTotalsWithPercentDiscountWithSurchargeWithInclusiveTax()
|
||||||
|
{
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
$this->invoice->custom_value1 = 5;
|
||||||
|
$this->invoice->tax_name1 = 'GST';
|
||||||
|
$this->invoice->tax_rate1 = 10;
|
||||||
|
$this->invoice->is_amount_discount = false;
|
||||||
|
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalTaxes(), 1.73);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceTotalsWithDiscountWithSurchargeWithExclusiveTax()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
$this->invoice->custom_value1 = 5;
|
||||||
|
$this->invoice->tax_name1 = 'GST';
|
||||||
|
$this->invoice->tax_rate1 = 10;
|
||||||
|
$this->settings->inclusive_taxes = true;
|
||||||
|
$this->invoice->is_amount_discount = true;
|
||||||
|
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 20);
|
||||||
|
//$this->assertEquals($this->invoice_calc->getTotalTaxes(), 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceTotalsWithDiscountWithSurchargeWithDoubleExclusiveTax()
|
||||||
|
{
|
||||||
|
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
$this->invoice->custom_value1 = 5;
|
||||||
|
$this->invoice->tax_name1 = 'GST';
|
||||||
|
$this->invoice->tax_rate1 = 10;
|
||||||
|
$this->invoice->tax_name2 = 'GST';
|
||||||
|
$this->invoice->tax_rate2 = 10;
|
||||||
|
$this->settings->inclusive_taxes = true;
|
||||||
|
$this->invoice->is_amount_discount = true;
|
||||||
|
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalTaxes(), 2.72);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testLineItemTaxRatesInclusiveTaxes()
|
||||||
|
{
|
||||||
|
$line_items = [];
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$this->invoice->line_items = $line_items;
|
||||||
|
|
||||||
|
$this->settings->inclusive_taxes = true;
|
||||||
|
$this->invoice->discount = 0;
|
||||||
|
$this->invoice->custom_value1 = 0;
|
||||||
|
|
||||||
|
$this->invoice_calc = new InvoiceSumInclusive($this->invoice, $this->settings);
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalTaxes(), 1.82);
|
||||||
|
$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getBalance(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLineItemTaxRatesInclusiveTaxesWithInvoiceTaxes()
|
||||||
|
{
|
||||||
|
$line_items = [];
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$this->invoice->line_items = $line_items;
|
||||||
|
|
||||||
|
$this->settings->inclusive_taxes = true;
|
||||||
|
$this->invoice->discount = 0;
|
||||||
|
$this->invoice->custom_value1 = 0;
|
||||||
|
|
||||||
|
$this->invoice->tax_rate1 = 10;
|
||||||
|
$this->invoice->tax_rate2 = 10;
|
||||||
|
|
||||||
|
$this->invoice_calc = new InvoiceSumInclusive($this->invoice, $this->settings);
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalTaxes(), 5.46);
|
||||||
|
$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 20);
|
||||||
|
$this->assertEquals($this->invoice_calc->getBalance(), 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLineItemTaxRatesInclusiveTaxesWithInvoiceTaxesAndDiscounts()
|
||||||
|
{
|
||||||
|
$line_items = [];
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
$item->discount = 5;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
$item->discount = 5;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$this->invoice->line_items = $line_items;
|
||||||
|
|
||||||
|
$this->settings->inclusive_taxes = true;
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
$this->invoice->is_amount_discount = false;
|
||||||
|
$this->invoice->custom_value1 = 0;
|
||||||
|
|
||||||
|
$this->invoice->tax_rate1 = 10;
|
||||||
|
$this->invoice->tax_rate2 = 10;
|
||||||
|
|
||||||
|
$this->invoice_calc = new InvoiceSumInclusive($this->invoice, $this->settings);
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$line_items = $this->invoice_calc->invoice_items->getLineItems();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 19);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalDiscount(), 0.95);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalTaxes(), 4.92);
|
||||||
|
$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 18.05);
|
||||||
|
$this->assertEquals($this->invoice_calc->getBalance(), 18.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testLineItemTaxRatesInclusiveTaxesWithInvoiceTaxesAndAmountDiscounts()
|
||||||
|
{
|
||||||
|
$line_items = [];
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
$item->discount = 5;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
$item->discount = 5;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$this->invoice->line_items = $line_items;
|
||||||
|
|
||||||
|
$this->settings->inclusive_taxes = true;
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
$this->invoice->is_amount_discount = true;
|
||||||
|
$this->invoice->custom_value1 = 0;
|
||||||
|
|
||||||
|
$this->invoice->tax_rate1 = 10;
|
||||||
|
$this->invoice->tax_rate2 = 10;
|
||||||
|
|
||||||
|
$this->invoice_calc = new InvoiceSumInclusive($this->invoice, $this->settings);
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$line_items = $this->invoice_calc->invoice_items->getLineItems();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 10);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalDiscount(), 5);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalTaxes(), 1.36);
|
||||||
|
$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 5);
|
||||||
|
$this->assertEquals($this->invoice_calc->getBalance(), 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function testLineItemTaxRatesInclusiveTaxesWithInvoiceTaxesAndAmountDiscountsWithLargeCosts()
|
||||||
|
{
|
||||||
|
$line_items = [];
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =100;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
$item->discount = 5;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =100;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_name1 = 10;
|
||||||
|
$item->discount = 5;
|
||||||
|
|
||||||
|
$line_items[] = $item;
|
||||||
|
|
||||||
|
$this->invoice->line_items = $line_items;
|
||||||
|
|
||||||
|
$this->settings->inclusive_taxes = true;
|
||||||
|
$this->invoice->discount = 5;
|
||||||
|
$this->invoice->is_amount_discount = true;
|
||||||
|
$this->invoice->custom_value1 = 0;
|
||||||
|
|
||||||
|
$this->invoice->tax_rate1 = 10;
|
||||||
|
$this->invoice->tax_rate2 = 10;
|
||||||
|
|
||||||
|
$this->invoice_calc = new InvoiceSumInclusive($this->invoice, $this->settings);
|
||||||
|
$this->invoice_calc->build();
|
||||||
|
|
||||||
|
$line_items = $this->invoice_calc->invoice_items->getLineItems();
|
||||||
|
|
||||||
|
$this->assertEquals($this->invoice_calc->getSubTotal(), 190);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalDiscount(), 5);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotalTaxes(), 50.46);
|
||||||
|
$this->assertEquals(count($this->invoice_calc->getTaxMap()), 1);
|
||||||
|
$this->assertEquals($this->invoice_calc->getTotal(), 185);
|
||||||
|
$this->assertEquals($this->invoice_calc->getBalance(), 185);
|
||||||
|
}
|
||||||
|
}
|
231
tests/Unit/InvoiceItemInclusiveTest.php
Normal file
231
tests/Unit/InvoiceItemInclusiveTest.php
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Factory\InvoiceItemFactory;
|
||||||
|
use App\Helpers\Invoice\InvoiceItemSum;
|
||||||
|
use App\Helpers\Invoice\InvoiceItemSumInclusive;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\MockAccountData;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @covers App\Helpers\Invoice\InvoiceItemSumInclusive
|
||||||
|
*/
|
||||||
|
class InvoiceItemInclusiveTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
use MockAccountData;
|
||||||
|
use DatabaseTransactions;
|
||||||
|
|
||||||
|
public function setUp() :void
|
||||||
|
{
|
||||||
|
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->makeTestData();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleX()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->is_amount_discount = true;
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = true;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getLineTotal(), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleWithDiscount()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->is_amount_discount = true;
|
||||||
|
$item->discount = 2;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = true;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getLineTotal(), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleWithDiscountWithPrecision()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->is_amount_discount = true;
|
||||||
|
$item->discount = 2.521254522145214511;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = true;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getLineTotal(), 7.48);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleWithDiscountWithPrecisionWithSingleInclusiveTax()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->is_amount_discount = true;
|
||||||
|
$item->discount = 0;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = false;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getTotalTaxes(), 0.91);
|
||||||
|
$this->assertEquals($item_calc->getSubTotal(), 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleWithDiscountWithPrecisionWithSingleInclusiveTax2()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->is_amount_discount = true;
|
||||||
|
$item->discount = 2;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = false;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getTotalTaxes(), 0.73);
|
||||||
|
$this->assertEquals($item_calc->getSubTotal(), 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleWithDiscountWithPrecisionWithDoubleInclusiveTax()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost = 10;
|
||||||
|
$item->is_amount_discount = true;
|
||||||
|
$item->discount = 0;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_rate2 = 17.5;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = true;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getTotalTaxes(), 2.4);
|
||||||
|
$this->assertEquals($item_calc->getSubTotal(), 10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleWithDiscountWithDoubleInclusiveTax()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 1;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->is_amount_discount = true;
|
||||||
|
$item->discount = 1;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_rate2 = 17.5;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = false;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getSubTotal(), 9);
|
||||||
|
$this->assertEquals($item_calc->getTotalTaxes(), 2.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleWithDiscountWithDoubleInclusiveTaxMultiQuantity()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 2;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->is_amount_discount = true;
|
||||||
|
$item->discount = 1;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_rate2 = 17.5;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = false;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getSubTotal(), 19);
|
||||||
|
$this->assertEquals($item_calc->getTotalTaxes(), 4.56);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInvoiceItemTotalSimpleWithPercentDiscountWithDoubleInclusiveTaxMultiQuantity()
|
||||||
|
{
|
||||||
|
$item = InvoiceItemFactory::create();
|
||||||
|
$item->quantity = 2;
|
||||||
|
$item->cost =10;
|
||||||
|
$item->is_amount_discount = false;
|
||||||
|
$item->discount = 1;
|
||||||
|
$item->tax_rate1 = 10;
|
||||||
|
$item->tax_rate2 = 17.5;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
$this->invoice->is_amount_discount = false;
|
||||||
|
|
||||||
|
$settings = new \stdClass;
|
||||||
|
$settings->inclusive_taxes = false;
|
||||||
|
$settings->precision = 2;
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSumInclusive($this->invoice, $settings);
|
||||||
|
$item_calc->process();
|
||||||
|
|
||||||
|
$this->assertEquals($item_calc->getSubTotal(), 19.8);
|
||||||
|
$this->assertEquals($item_calc->getTotalTaxes(), 4.75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -3,14 +3,14 @@
|
|||||||
namespace Tests\Unit;
|
namespace Tests\Unit;
|
||||||
|
|
||||||
use App\Factory\InvoiceItemFactory;
|
use App\Factory\InvoiceItemFactory;
|
||||||
use App\Helpers\Invoice\InvoiceItemCalc;
|
use App\Helpers\Invoice\InvoiceItemSum;
|
||||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
use Tests\MockAccountData;
|
use Tests\MockAccountData;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @covers App\Helpers\Invoice\InvoiceItemCalc
|
* @covers App\Helpers\Invoice\InvoiceItemSum
|
||||||
*/
|
*/
|
||||||
class InvoiceItemTest extends TestCase
|
class InvoiceItemTest extends TestCase
|
||||||
{
|
{
|
||||||
@ -38,7 +38,9 @@ class InvoiceItemTest extends TestCase
|
|||||||
$settings->inclusive_taxes = true;
|
$settings->inclusive_taxes = true;
|
||||||
$settings->precision = 2;
|
$settings->precision = 2;
|
||||||
|
|
||||||
$item_calc = new InvoiceItemCalc($item, $settings, $this->invoice);
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSum($this->invoice, $settings);
|
||||||
$item_calc->process();
|
$item_calc->process();
|
||||||
|
|
||||||
$this->assertEquals($item_calc->getLineTotal(), 10);
|
$this->assertEquals($item_calc->getLineTotal(), 10);
|
||||||
@ -52,10 +54,13 @@ class InvoiceItemTest extends TestCase
|
|||||||
$item->is_amount_discount = true;
|
$item->is_amount_discount = true;
|
||||||
$item->discount = 2;
|
$item->discount = 2;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
$settings = new \stdClass;
|
$settings = new \stdClass;
|
||||||
$settings->inclusive_taxes = true;
|
$settings->inclusive_taxes = true;
|
||||||
$settings->precision = 2;
|
$settings->precision = 2;
|
||||||
$item_calc = new InvoiceItemCalc($item, $settings, $this->invoice);
|
|
||||||
|
$item_calc = new InvoiceItemSum($this->invoice, $settings);
|
||||||
$item_calc->process();
|
$item_calc->process();
|
||||||
|
|
||||||
$this->assertEquals($item_calc->getLineTotal(), 8);
|
$this->assertEquals($item_calc->getLineTotal(), 8);
|
||||||
@ -69,11 +74,13 @@ class InvoiceItemTest extends TestCase
|
|||||||
$item->is_amount_discount = true;
|
$item->is_amount_discount = true;
|
||||||
$item->discount = 2.521254522145214511;
|
$item->discount = 2.521254522145214511;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
$settings = new \stdClass;
|
$settings = new \stdClass;
|
||||||
$settings->inclusive_taxes = true;
|
$settings->inclusive_taxes = true;
|
||||||
$settings->precision = 2;
|
$settings->precision = 2;
|
||||||
|
|
||||||
$item_calc = new InvoiceItemCalc($item, $settings, $this->invoice);
|
$item_calc = new InvoiceItemSum($this->invoice, $settings);
|
||||||
$item_calc->process();
|
$item_calc->process();
|
||||||
|
|
||||||
$this->assertEquals($item_calc->getLineTotal(), 7.48);
|
$this->assertEquals($item_calc->getLineTotal(), 7.48);
|
||||||
@ -85,17 +92,20 @@ class InvoiceItemTest extends TestCase
|
|||||||
$item->quantity = 1;
|
$item->quantity = 1;
|
||||||
$item->cost =10;
|
$item->cost =10;
|
||||||
$item->is_amount_discount = true;
|
$item->is_amount_discount = true;
|
||||||
$item->discount = 2.521254522145214511;
|
$item->discount = 2;
|
||||||
$item->tax_rate1 = 10;
|
$item->tax_rate1 = 10;
|
||||||
|
|
||||||
$settings = new \stdClass;
|
$settings = new \stdClass;
|
||||||
$settings->inclusive_taxes = true;
|
$settings->inclusive_taxes = false;
|
||||||
$settings->precision = 2;
|
$settings->precision = 2;
|
||||||
|
|
||||||
$item_calc = new InvoiceItemCalc($item, $settings, $this->invoice);
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
|
||||||
|
$item_calc = new InvoiceItemSum($this->invoice, $settings);
|
||||||
$item_calc->process();
|
$item_calc->process();
|
||||||
|
|
||||||
$this->assertEquals($item_calc->getTotalTaxes(), 0.68);
|
$this->assertEquals($item_calc->getTotalTaxes(), 0.80);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testInvoiceItemTotalSimpleWithDiscountWithPrecisionWithSingleExclusiveTax()
|
public function testInvoiceItemTotalSimpleWithDiscountWithPrecisionWithSingleExclusiveTax()
|
||||||
@ -107,11 +117,14 @@ class InvoiceItemTest extends TestCase
|
|||||||
$item->discount = 2.521254522145214511;
|
$item->discount = 2.521254522145214511;
|
||||||
$item->tax_rate1 = 10;
|
$item->tax_rate1 = 10;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
|
|
||||||
$settings = new \stdClass;
|
$settings = new \stdClass;
|
||||||
$settings->inclusive_taxes = false;
|
$settings->inclusive_taxes = false;
|
||||||
$settings->precision = 2;
|
$settings->precision = 2;
|
||||||
|
|
||||||
$item_calc = new InvoiceItemCalc($item, $settings, $this->invoice);
|
$item_calc = new InvoiceItemSum($this->invoice, $settings);
|
||||||
$item_calc->process();
|
$item_calc->process();
|
||||||
|
|
||||||
$this->assertEquals($item_calc->getTotalTaxes(), 0.75);
|
$this->assertEquals($item_calc->getTotalTaxes(), 0.75);
|
||||||
@ -127,14 +140,16 @@ class InvoiceItemTest extends TestCase
|
|||||||
$item->tax_rate1 = 10;
|
$item->tax_rate1 = 10;
|
||||||
$item->tax_rate2 = 17.5;
|
$item->tax_rate2 = 17.5;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
$settings = new \stdClass;
|
$settings = new \stdClass;
|
||||||
$settings->inclusive_taxes = true;
|
$settings->inclusive_taxes = true;
|
||||||
$settings->precision = 2;
|
$settings->precision = 2;
|
||||||
|
|
||||||
$item_calc = new InvoiceItemCalc($item, $settings, $this->invoice);
|
$item_calc = new InvoiceItemSum($this->invoice, $settings);
|
||||||
$item_calc->process();
|
$item_calc->process();
|
||||||
|
|
||||||
$this->assertEquals($item_calc->getTotalTaxes(), 1.79);
|
$this->assertEquals($item_calc->getTotalTaxes(), 2.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testInvoiceItemTotalSimpleWithDiscountWithPrecisionWithDoubleExclusiveTax()
|
public function testInvoiceItemTotalSimpleWithDiscountWithPrecisionWithDoubleExclusiveTax()
|
||||||
@ -147,11 +162,13 @@ class InvoiceItemTest extends TestCase
|
|||||||
$item->tax_rate1 = 10;
|
$item->tax_rate1 = 10;
|
||||||
$item->tax_rate2 = 17.5;
|
$item->tax_rate2 = 17.5;
|
||||||
|
|
||||||
|
$this->invoice->line_items = [$item];
|
||||||
|
|
||||||
$settings = new \stdClass;
|
$settings = new \stdClass;
|
||||||
$settings->inclusive_taxes = false;
|
$settings->inclusive_taxes = false;
|
||||||
$settings->precision = 2;
|
$settings->precision = 2;
|
||||||
|
|
||||||
$item_calc = new InvoiceItemCalc($item, $settings, $this->invoice);
|
$item_calc = new InvoiceItemSum($this->invoice, $settings);
|
||||||
$item_calc->process();
|
$item_calc->process();
|
||||||
|
|
||||||
$this->assertEquals($item_calc->getTotalTaxes(), 2.06);
|
$this->assertEquals($item_calc->getTotalTaxes(), 2.06);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user