invoiceninja/app/Helpers/Invoice/InvoiceCalc.php

352 lines
6.7 KiB
PHP
Raw Normal View History

2019-04-02 16:16:39 +11:00
<?php
2019-05-11 13:32:07 +10:00
/**
* 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
*/
2019-04-02 16:16:39 +11:00
namespace App\Helpers\Invoice;
use App\Helpers\Invoice\InvoiceItemCalc;
2019-04-02 16:16:39 +11:00
use App\Models\Invoice;
2019-04-04 15:49:13 +11:00
use App\Utils\Traits\NumberFormatter;
2019-04-11 10:35:30 +10:00
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
2019-04-02 16:16:39 +11:00
2019-04-08 14:28:28 +10:00
/**
* Class for invoice calculations.
*/
2019-04-03 11:09:22 +11:00
class InvoiceCalc
2019-04-02 16:16:39 +11:00
{
2019-04-03 11:09:22 +11:00
2019-04-04 15:49:13 +11:00
use NumberFormatter;
protected $invoice;
2019-04-08 14:28:28 +10:00
protected $settings;
2019-04-04 15:49:13 +11:00
2019-04-10 17:57:02 +10:00
private $line_items;
2019-04-08 14:28:28 +10:00
private $balance;
2019-04-04 15:49:13 +11:00
2019-04-08 14:28:28 +10:00
private $paid_to_date;
2019-04-04 15:49:13 +11:00
2019-04-08 14:28:28 +10:00
private $amount;
2019-04-04 15:49:13 +11:00
2019-04-08 14:28:28 +10:00
private $sub_total;
2019-04-10 17:57:02 +10:00
private $total;
2019-04-04 15:49:13 +11:00
2019-04-08 14:28:28 +10:00
private $tax_map;
2019-04-05 15:52:30 +11:00
2019-04-11 14:40:36 +10:00
private $total_item_taxes;
2019-04-08 14:28:28 +10:00
private $total_taxes;
2019-04-05 15:52:30 +11:00
2019-04-08 14:28:28 +10:00
private $total_discount;
2019-04-04 15:49:13 +11:00
2019-04-08 14:28:28 +10:00
/**
* Constructs the object with Invoice and Settings object
*
* @param \App\Models\Invoice $invoice The invoice
*/
public function __construct($invoice, $settings)
2019-04-02 16:16:39 +11:00
{
2019-04-18 15:01:40 +10:00
2019-04-02 16:16:39 +11:00
$this->invoice = $invoice;
$this->settings = $settings;
2019-04-11 10:35:30 +10:00
$this->tax_map = new Collection;
2019-04-18 15:01:40 +10:00
2019-04-02 16:16:39 +11:00
}
2019-04-03 11:09:22 +11:00
2019-04-08 14:28:28 +10:00
/**
* Builds the invoice values
*/
2019-04-04 15:49:13 +11:00
public function build()
{
2019-04-18 15:01:40 +10:00
//Log::error(print_r($this->invoice,1));
2019-04-10 17:57:02 +10:00
$this->calcLineItems()
->calcDiscount()
2019-04-10 19:09:57 +10:00
->calcCustomValues()
->calcBalance()
->calcPartial();
2019-04-10 17:57:02 +10:00
return $this;
}
2019-04-18 15:01:40 +10:00
/**
* Calculates the partial balance.
*
* @return self The partial.
*/
2019-04-10 19:09:57 +10:00
private function calcPartial()
{
2019-04-11 10:35:30 +10:00
if ( !isset($this->invoice->id) && isset($this->invoice->partial) ) {
2019-04-10 19:09:57 +10:00
$this->invoice->partial = max(0, min($this->formatValue($this->invoice->partial, 2), $this->invoice->balance));
}
return $this;
2019-04-10 19:09:57 +10:00
}
2019-04-18 15:01:40 +10:00
/**
* Calculates the discount.
*
* @return self The discount.
*/
2019-04-10 17:57:02 +10:00
private function calcDiscount()
{
if ($this->invoice->discount != 0) {
if ($this->invoice->is_amount_discount) {
$this->total -= $this->invoice->discount;
} else {
$this->total -= round($this->total * ($this->invoice->discount / 100), 2);
}
}
return $this;
2019-04-04 15:49:13 +11:00
}
2019-04-10 19:09:57 +10:00
/**
* Calculates the balance.
*
* @return self The balance.
*/
private function calcBalance()
2019-04-10 17:57:02 +10:00
{
if(isset($this->invoice->id) && $this->invoice->id >= 1)
{
2019-04-11 10:57:06 +10:00
$this->balance = round($this->total - ($this->invoice->amount - $this->invoice->balance), 2);
2019-04-10 17:57:02 +10:00
} else {
2019-04-11 10:57:06 +10:00
$this->balance = $this->total;
2019-04-10 17:57:02 +10:00
}
return $this;
2019-04-04 15:49:13 +11:00
2019-04-10 17:57:02 +10:00
}
2019-04-18 15:01:40 +10:00
/**
* Calculates the custom values.
*
* @return self The custom values.
*/
2019-04-10 19:09:57 +10:00
private function calcCustomValues()
2019-04-10 17:57:02 +10:00
{
// custom fields charged taxes
if (isset($this->invoice->custom_value1) && $this->settings->custom_taxes1) {
2019-04-11 10:35:30 +10:00
$this->total += $this->invoice->custom_value1;
2019-04-10 17:57:02 +10:00
}
2019-04-18 08:00:04 +10:00
if (isset($this->invoice->custom_value2) && $this->settings->custom_taxes2) {
2019-04-11 10:35:30 +10:00
$this->total += $this->invoice->custom_value2;
2019-04-10 17:57:02 +10:00
}
$this->calcTaxes();
// custom fields not charged taxes
if (isset($this->invoice->custom_value1) && ! $this->settings->custom_taxes1) {
2019-04-11 10:35:30 +10:00
$this->total += $this->invoice->custom_value1;
2019-04-10 17:57:02 +10:00
}
if (isset($this->invoice->custom_value2) && ! $this->settings->custom_taxes2) {
2019-04-11 10:35:30 +10:00
$this->total += $this->invoice->custom_value2;
2019-04-10 17:57:02 +10:00
}
2019-04-11 10:35:30 +10:00
return $this;
2019-04-10 17:57:02 +10:00
}
/**
* Calculates the Invoice Level taxes.
*/
private function calcTaxes()
{
2019-04-10 17:57:02 +10:00
if (! $this->settings->inclusive_taxes) {
$taxAmount1 = round($this->total * ($this->invoice->tax_rate1 ? $this->invoice->tax_rate1 : 0) / 100, 2);
$taxAmount2 = round($this->total * ($this->invoice->tax_rate2 ? $this->invoice->tax_rate2 : 0) / 100, 2);
$this->total_taxes = round($taxAmount1 + $taxAmount2, 2) + $this->total_item_taxes;
2019-04-10 17:57:02 +10:00
$this->total += $this->total_taxes;
}
2019-04-11 10:35:30 +10:00
return $this;
}
2019-04-08 14:28:28 +10:00
/**
* Calculates the line items.
*
* @return self The line items.
*/
2019-04-04 15:49:13 +11:00
private function calcLineItems()
{
if(!$this->invoice->line_items || count($this->invoice->line_items) == 0)
return $this;
2019-04-04 15:49:13 +11:00
$new_line_items = [];
foreach($this->invoice->line_items as $item) {
2019-04-11 10:35:30 +10:00
$item_calc = new InvoiceItemCalc($item, $this->settings);
$item_calc->process();
2019-04-04 15:49:13 +11:00
$new_line_items[] = $item_calc->getLineItem();
//set collection of itemised taxes
$this->tax_map->push($item_calc->getGroupedTaxes());
2019-04-05 15:52:30 +11:00
//set running total of taxes
2019-04-11 14:40:36 +10:00
$this->total_item_taxes += $item_calc->getTotalTaxes();
2019-04-05 15:52:30 +11:00
//set running total of discounts
2019-04-05 20:32:59 +11:00
$this->total_discount += $item_calc->getTotalDiscounts();
2019-04-08 14:28:28 +10:00
//set running subtotal
$this->sub_total += $item_calc->getLineTotal();
$this->total += $item_calc->getLineTotal();
2019-04-04 15:49:13 +11:00
}
$this->invoice->line_items = $new_line_items;
2019-04-05 20:32:59 +11:00
return $this;
2019-04-04 15:49:13 +11:00
}
2019-04-05 15:52:30 +11:00
2019-04-08 14:28:28 +10:00
/**
* Getters and Setters
*/
2019-04-11 10:35:30 +10:00
public function getSubTotal()
2019-04-08 14:28:28 +10:00
{
2019-04-11 10:35:30 +10:00
return $this->sub_total;
2019-04-08 14:28:28 +10:00
}
2019-04-05 15:52:30 +11:00
2019-04-11 10:35:30 +10:00
public function setSubTotal($value)
2019-04-08 14:28:28 +10:00
{
$this->sub_total = $value;
return $this;
}
2019-04-05 15:52:30 +11:00
2019-04-11 10:35:30 +10:00
public function getTaxMap()
2019-04-05 15:52:30 +11:00
{
return $this->tax_map;
}
2019-04-11 10:35:30 +10:00
public function setTaxMap($value)
2019-04-05 15:52:30 +11:00
{
$htis->tax_map = $value;
return $this;
}
2019-04-11 10:35:30 +10:00
public function getTotalDiscount()
2019-04-05 15:52:30 +11:00
{
return $this->total_discount;
}
2019-04-11 10:35:30 +10:00
public function setTotalDiscount($value)
2019-04-05 15:52:30 +11:00
{
$this->total_discount = $value;
return $this;
}
2019-04-11 10:35:30 +10:00
public function getTotalTaxes()
2019-04-05 15:52:30 +11:00
{
return $this->total_taxes;
}
2019-04-11 10:35:30 +10:00
public function setTotalTaxes($value)
2019-04-05 15:52:30 +11:00
{
$this->total_taxes = $value;
return $this;
}
2019-04-08 14:28:28 +10:00
2019-04-11 10:57:06 +10:00
public function getTotal()
{
return $this->total;
}
public function setTotal($value)
{
$this->total = $value;
}
public function getBalance()
{
return $this->balance;
}
public function setBalance($value)
{
$this->balance = $value;
}
2019-04-08 14:28:28 +10:00
2019-04-16 15:28:30 +10:00
public function getInvoice()
{
//Build invoice values here and return Invoice
$this->setCalculatedAttributes();
2019-04-16 15:28:30 +10:00
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();
}
/*
2019-04-04 15:49:13 +11:00
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);
}
*/
2019-04-04 15:49:13 +11:00
2019-04-02 16:16:39 +11:00
}