Merge pull request #977 from denisdulici/master
Improved invoice/bill jobs
This commit is contained in:
		
							
								
								
									
										22
									
								
								app/Events/Expense/BillCreating.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Events/Expense/BillCreating.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Events\Expense;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Queue\SerializesModels;
 | 
			
		||||
 | 
			
		||||
class BillCreating
 | 
			
		||||
{
 | 
			
		||||
    use SerializesModels;
 | 
			
		||||
 | 
			
		||||
    public $request;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new event instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @param $request
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($request)
 | 
			
		||||
    {
 | 
			
		||||
        $this->request = $request;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								app/Events/Expense/BillUpdating.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								app/Events/Expense/BillUpdating.php
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
namespace App\Events\Expense;
 | 
			
		||||
 | 
			
		||||
use Illuminate\Queue\SerializesModels;
 | 
			
		||||
 | 
			
		||||
class BillUpdating
 | 
			
		||||
{
 | 
			
		||||
    use SerializesModels;
 | 
			
		||||
 | 
			
		||||
    public $bill;
 | 
			
		||||
 | 
			
		||||
    public $request;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new event instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @param $bill
 | 
			
		||||
     * @param $request
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($bill, $request)
 | 
			
		||||
    {
 | 
			
		||||
        $this->bill = $bill;
 | 
			
		||||
        $this->request = $request;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -291,12 +291,12 @@ class Items extends Controller
 | 
			
		||||
            $currency_code = setting('default.currency');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $json = new \stdClass;
 | 
			
		||||
        $json = new \stdClass();
 | 
			
		||||
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
        $tax_total = 0;
 | 
			
		||||
 | 
			
		||||
        $items = array();
 | 
			
		||||
        $items = [];
 | 
			
		||||
 | 
			
		||||
        if ($input_items) {
 | 
			
		||||
            foreach ($input_items as $key => $item) {
 | 
			
		||||
@@ -307,15 +307,15 @@ class Items extends Controller
 | 
			
		||||
                $item_tax_amount = 0;
 | 
			
		||||
 | 
			
		||||
                $item_sub_total = ($price * $quantity);
 | 
			
		||||
                $item_discount_total = $item_sub_total;
 | 
			
		||||
                $item_discounted_total = $item_sub_total;
 | 
			
		||||
 | 
			
		||||
                // Apply discount to item
 | 
			
		||||
                // Apply discount to amount
 | 
			
		||||
                if ($discount) {
 | 
			
		||||
                    $item_discount_total = $item_sub_total - ($item_sub_total * ($discount / 100));
 | 
			
		||||
                    $item_discounted_total = $item_sub_total - ($item_sub_total * ($discount / 100));
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (!empty($item['tax_id'])) {
 | 
			
		||||
                    $inclusives = $compounds = $taxes = $fixed_taxes = [];
 | 
			
		||||
                    $inclusives = $compounds = [];
 | 
			
		||||
 | 
			
		||||
                    foreach ($item['tax_id'] as $tax_id) {
 | 
			
		||||
                        $tax = Tax::find($tax_id);
 | 
			
		||||
@@ -328,15 +328,10 @@ class Items extends Controller
 | 
			
		||||
                                $compounds[] = $tax;
 | 
			
		||||
                                break;
 | 
			
		||||
                            case 'fixed':
 | 
			
		||||
                                $fixed_taxes[] = $tax;
 | 
			
		||||
 | 
			
		||||
                                $item_tax_total += $tax->rate;
 | 
			
		||||
                                $item_tax_total += $tax->rate * $quantity;
 | 
			
		||||
                                break;
 | 
			
		||||
                            case 'normal':
 | 
			
		||||
                            default:
 | 
			
		||||
                                $taxes[] = $tax;
 | 
			
		||||
 | 
			
		||||
                                $item_tax_amount = ($item_discount_total / 100) * $tax->rate;
 | 
			
		||||
                                $item_tax_amount = ($item_discounted_total / 100) * $tax->rate;
 | 
			
		||||
 | 
			
		||||
                                $item_tax_total += $item_tax_amount;
 | 
			
		||||
                                break;
 | 
			
		||||
@@ -344,9 +339,9 @@ class Items extends Controller
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if ($inclusives) {
 | 
			
		||||
                        $item_sub_and_tax_total = $item_discount_total + $item_tax_total;
 | 
			
		||||
                        $item_sub_and_tax_total = $item_discounted_total + $item_tax_total;
 | 
			
		||||
 | 
			
		||||
                        $item_base_rate = $item_sub_and_tax_total / (1 + collect($inclusives)->sum('rate')/100);
 | 
			
		||||
                        $item_base_rate = $item_sub_and_tax_total / (1 + collect($inclusives)->sum('rate') / 100);
 | 
			
		||||
                        $item_tax_total = $item_sub_and_tax_total - $item_base_rate;
 | 
			
		||||
 | 
			
		||||
                        $item_sub_total = $item_base_rate + $discount;
 | 
			
		||||
@@ -354,7 +349,7 @@ class Items extends Controller
 | 
			
		||||
 | 
			
		||||
                    if ($compounds) {
 | 
			
		||||
                        foreach ($compounds as $compound) {
 | 
			
		||||
                            $item_tax_total += (($item_discount_total + $item_tax_total) / 100) * $compound->rate;
 | 
			
		||||
                            $item_tax_total += (($item_discounted_total + $item_tax_total) / 100) * $compound->rate;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -370,14 +365,14 @@ class Items extends Controller
 | 
			
		||||
 | 
			
		||||
        $json->sub_total = money($sub_total, $currency_code, true)->format();
 | 
			
		||||
 | 
			
		||||
        $json->discount_text= trans('invoices.add_discount');
 | 
			
		||||
        $json->discount_text = trans('invoices.add_discount');
 | 
			
		||||
        $json->discount_total = '';
 | 
			
		||||
 | 
			
		||||
        $json->tax_total = money($tax_total, $currency_code, true)->format();
 | 
			
		||||
 | 
			
		||||
        // Apply discount to total
 | 
			
		||||
        if ($discount) {
 | 
			
		||||
            $json->discount_text= trans('invoices.show_discount', ['discount' => $discount]);
 | 
			
		||||
            $json->discount_text = trans('invoices.show_discount', ['discount' => $discount]);
 | 
			
		||||
            $json->discount_total = money($sub_total * ($discount / 100), $currency_code, true)->format();
 | 
			
		||||
 | 
			
		||||
            $sub_total = $sub_total - ($sub_total * ($discount / 100));
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ namespace App\Jobs\Expense;
 | 
			
		||||
 | 
			
		||||
use App\Abstracts\Job;
 | 
			
		||||
use App\Events\Expense\BillCreated;
 | 
			
		||||
use App\Events\Expense\BillCreating;
 | 
			
		||||
use App\Models\Expense\Bill;
 | 
			
		||||
use App\Models\Expense\BillTotal;
 | 
			
		||||
use App\Traits\Currencies;
 | 
			
		||||
@@ -15,6 +16,8 @@ class CreateBill extends Job
 | 
			
		||||
 | 
			
		||||
    protected $request;
 | 
			
		||||
 | 
			
		||||
    protected $bill;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     *
 | 
			
		||||
@@ -28,153 +31,165 @@ class CreateBill extends Job
 | 
			
		||||
    /**
 | 
			
		||||
     * Execute the job.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Invoice
 | 
			
		||||
     * @return Bill
 | 
			
		||||
     */
 | 
			
		||||
    public function handle()
 | 
			
		||||
    {
 | 
			
		||||
        $bill = Bill::create($this->request->all());
 | 
			
		||||
        if (empty($this->request['amount'])) {
 | 
			
		||||
            $this->request['amount'] = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        event(new BillCreating($this->request));
 | 
			
		||||
 | 
			
		||||
        $this->bill = Bill::create($this->request->all());
 | 
			
		||||
 | 
			
		||||
        // Upload attachment
 | 
			
		||||
        if ($this->request->file('attachment')) {
 | 
			
		||||
            $media = $this->getMedia($this->request->file('attachment'), 'bills');
 | 
			
		||||
 | 
			
		||||
            $bill->attachMedia($media, 'attachment');
 | 
			
		||||
            $this->bill->attachMedia($media, 'attachment');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $taxes = [];
 | 
			
		||||
        $this->createItemsAndTotals();
 | 
			
		||||
 | 
			
		||||
        $tax_total = 0;
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
        $discount_total = 0;
 | 
			
		||||
        $discount = $this->request['discount'];
 | 
			
		||||
        $this->bill->update($this->request->input());
 | 
			
		||||
 | 
			
		||||
        if ($this->request['items']) {
 | 
			
		||||
            foreach ($this->request['items'] as $item) {
 | 
			
		||||
                $bill_item = $this->dispatch(new CreateBillItem($item, $bill, $discount));
 | 
			
		||||
        $this->bill->createRecurring();
 | 
			
		||||
 | 
			
		||||
                // Calculate totals
 | 
			
		||||
                $tax_total += $bill_item->tax;
 | 
			
		||||
                $sub_total += $bill_item->total;
 | 
			
		||||
        event(new BillCreated($this->bill));
 | 
			
		||||
 | 
			
		||||
                // Set taxes
 | 
			
		||||
                if ($bill_item->item_taxes) {
 | 
			
		||||
                    foreach ($bill_item->item_taxes as $item_tax) {
 | 
			
		||||
                        if (isset($taxes) && array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                            $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                        } else {
 | 
			
		||||
                            $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                                'name' => $item_tax['name'],
 | 
			
		||||
                                'amount' => $item_tax['amount']
 | 
			
		||||
                            ];
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $s_total = $sub_total;
 | 
			
		||||
 | 
			
		||||
        // Apply discount to total
 | 
			
		||||
        if ($discount) {
 | 
			
		||||
            $s_discount = $s_total * ($discount / 100);
 | 
			
		||||
            $discount_total += $s_discount;
 | 
			
		||||
            $s_total = $s_total - $s_discount;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $amount = $s_total + $tax_total;
 | 
			
		||||
 | 
			
		||||
        $this->request['amount'] = money($amount, $this->request['currency_code'])->getAmount();
 | 
			
		||||
 | 
			
		||||
        $bill->update($this->request->input());
 | 
			
		||||
 | 
			
		||||
        // Add bill totals
 | 
			
		||||
        $this->addTotals($bill, $this->request, $taxes, $sub_total, $discount_total, $tax_total);
 | 
			
		||||
 | 
			
		||||
        // Recurring
 | 
			
		||||
        $bill->createRecurring();
 | 
			
		||||
 | 
			
		||||
        // Fire the event to make it extendible
 | 
			
		||||
        event(new BillCreated($bill));
 | 
			
		||||
 | 
			
		||||
        return $bill;
 | 
			
		||||
        return $this->bill;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function addTotals($bill, $request, $taxes, $sub_total, $discount_total, $tax_total)
 | 
			
		||||
    protected function createItemsAndTotals()
 | 
			
		||||
    {
 | 
			
		||||
        // Check if totals are in request, i.e. api
 | 
			
		||||
        if (!empty($request['totals'])) {
 | 
			
		||||
            $sort_order = 1;
 | 
			
		||||
 | 
			
		||||
            foreach ($request['totals'] as $total) {
 | 
			
		||||
                $total['bill_id'] = $bill->id;
 | 
			
		||||
 | 
			
		||||
                if (empty($total['sort_order'])) {
 | 
			
		||||
                    $total['sort_order'] = $sort_order;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                BillTotal::create($total);
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // Create items
 | 
			
		||||
        list($sub_total, $taxes) = $this->createItems();
 | 
			
		||||
 | 
			
		||||
        $sort_order = 1;
 | 
			
		||||
 | 
			
		||||
        // Added bill sub total
 | 
			
		||||
        // Add sub total
 | 
			
		||||
        BillTotal::create([
 | 
			
		||||
            'company_id' => $request['company_id'],
 | 
			
		||||
            'bill_id' => $bill->id,
 | 
			
		||||
            'company_id' => $this->bill->company_id,
 | 
			
		||||
            'bill_id' => $this->bill->id,
 | 
			
		||||
            'code' => 'sub_total',
 | 
			
		||||
            'name' => 'bills.sub_total',
 | 
			
		||||
            'amount' => $sub_total,
 | 
			
		||||
            'sort_order' => $sort_order,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $this->request['amount'] += $sub_total;
 | 
			
		||||
 | 
			
		||||
        $sort_order++;
 | 
			
		||||
 | 
			
		||||
        // Added bill discount
 | 
			
		||||
        if ($discount_total) {
 | 
			
		||||
        // Add discount
 | 
			
		||||
        if (!empty($this->request['discount'])) {
 | 
			
		||||
            $discount_total = $sub_total * ($this->request['discount'] / 100);
 | 
			
		||||
 | 
			
		||||
            BillTotal::create([
 | 
			
		||||
                'company_id' => $request['company_id'],
 | 
			
		||||
                'bill_id' => $bill->id,
 | 
			
		||||
                'company_id' => $this->bill->company_id,
 | 
			
		||||
                'bill_id' => $this->bill->id,
 | 
			
		||||
                'code' => 'discount',
 | 
			
		||||
                'name' => 'bills.discount',
 | 
			
		||||
                'amount' => $discount_total,
 | 
			
		||||
                'sort_order' => $sort_order,
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
            // This is for total
 | 
			
		||||
            $sub_total = $sub_total - $discount_total;
 | 
			
		||||
            $this->request['amount'] -= $discount_total;
 | 
			
		||||
 | 
			
		||||
            $sort_order++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Added bill taxes
 | 
			
		||||
        if (isset($taxes)) {
 | 
			
		||||
        // Add taxes
 | 
			
		||||
        if (!empty($taxes)) {
 | 
			
		||||
            foreach ($taxes as $tax) {
 | 
			
		||||
                BillTotal::create([
 | 
			
		||||
                    'company_id' => $request['company_id'],
 | 
			
		||||
                    'bill_id' => $bill->id,
 | 
			
		||||
                    'company_id' => $this->bill->company_id,
 | 
			
		||||
                    'bill_id' => $this->bill->id,
 | 
			
		||||
                    'code' => 'tax',
 | 
			
		||||
                    'name' => $tax['name'],
 | 
			
		||||
                    'amount' => $tax['amount'],
 | 
			
		||||
                    'sort_order' => $sort_order,
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                $this->request['amount'] += $tax['amount'];
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Added bill total
 | 
			
		||||
        // Add extra totals, i.e. shipping fee
 | 
			
		||||
        if (!empty($this->request['totals'])) {
 | 
			
		||||
            foreach ($this->request['totals'] as $total) {
 | 
			
		||||
                $total['company_id'] = $this->bill->company_id;
 | 
			
		||||
                $total['bill_id'] = $this->bill->id;
 | 
			
		||||
                $total['sort_order'] = $sort_order;
 | 
			
		||||
 | 
			
		||||
                if (empty($total['code'])) {
 | 
			
		||||
                    $total['code'] = 'extra';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                BillTotal::create($total);
 | 
			
		||||
 | 
			
		||||
                if (empty($total['operator']) || ($total['operator'] == 'addition')) {
 | 
			
		||||
                    $this->request['amount'] += $total['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    // subtraction
 | 
			
		||||
                    $this->request['amount'] -= $total['amount'];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add total
 | 
			
		||||
        BillTotal::create([
 | 
			
		||||
            'company_id' => $request['company_id'],
 | 
			
		||||
            'bill_id' => $bill->id,
 | 
			
		||||
            'company_id' => $this->bill->company_id,
 | 
			
		||||
            'bill_id' => $this->bill->id,
 | 
			
		||||
            'code' => 'total',
 | 
			
		||||
            'name' => 'bills.total',
 | 
			
		||||
            'amount' => $sub_total + $tax_total,
 | 
			
		||||
            'amount' => $this->request['amount'],
 | 
			
		||||
            'sort_order' => $sort_order,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function createItems()
 | 
			
		||||
    {
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
 | 
			
		||||
        $taxes = [];
 | 
			
		||||
 | 
			
		||||
        if (empty($this->request['items'])) {
 | 
			
		||||
            return [$sub_total, $taxes];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ((array) $this->request['items'] as $item) {
 | 
			
		||||
            if (empty($item['discount'])) {
 | 
			
		||||
                $item['discount'] = !empty($this->request['discount']) ? !empty($this->request['discount']) : 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $bill_item = $this->dispatch(new CreateBillItem($item, $this->bill));
 | 
			
		||||
 | 
			
		||||
            // Calculate totals
 | 
			
		||||
            $sub_total += $bill_item->total;
 | 
			
		||||
 | 
			
		||||
            if (!$bill_item->item_taxes) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Set taxes
 | 
			
		||||
            foreach ((array) $bill_item->item_taxes as $item_tax) {
 | 
			
		||||
                if (array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                        'name' => $item_tax['name'],
 | 
			
		||||
                        'amount' => $item_tax['amount']
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [$sub_total, $taxes];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,24 +10,20 @@ use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class CreateBillItem extends Job
 | 
			
		||||
{
 | 
			
		||||
    protected $data;
 | 
			
		||||
    protected $request;
 | 
			
		||||
 | 
			
		||||
    protected $bill;
 | 
			
		||||
 | 
			
		||||
    protected $discount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $data
 | 
			
		||||
     * @param  $request
 | 
			
		||||
     * @param  $bill
 | 
			
		||||
     * @param  $discount
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($data, $bill, $discount = null)
 | 
			
		||||
    public function __construct($request, $bill)
 | 
			
		||||
    {
 | 
			
		||||
        $this->data = $data;
 | 
			
		||||
        $this->request = $request;
 | 
			
		||||
        $this->bill = $bill;
 | 
			
		||||
        $this->discount = $discount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -37,36 +33,37 @@ class CreateBillItem extends Job
 | 
			
		||||
     */
 | 
			
		||||
    public function handle()
 | 
			
		||||
    {
 | 
			
		||||
        $item_id = !empty($this->data['item_id']) ? $this->data['item_id'] : 0;
 | 
			
		||||
        $item_amount = (double) $this->data['price'] * (double) $this->data['quantity'];
 | 
			
		||||
        $item_id = !empty($this->request['item_id']) ? $this->request['item_id'] : 0;
 | 
			
		||||
        $item_amount = (double) $this->request['price'] * (double) $this->request['quantity'];
 | 
			
		||||
 | 
			
		||||
        $item_discount_amount = $item_amount;
 | 
			
		||||
        $item_discounted_amount = $item_amount;
 | 
			
		||||
 | 
			
		||||
        // Apply discount to tax
 | 
			
		||||
        if ($this->discount) {
 | 
			
		||||
            $item_discount_amount = $item_amount - ($item_amount * ($this->discount / 100));
 | 
			
		||||
        // Apply discount to amount
 | 
			
		||||
        if (!empty($this->request['discount'])) {
 | 
			
		||||
            $item_discounted_amount = $item_amount - ($item_amount * ($this->request['discount'] / 100));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $tax_amount = 0;
 | 
			
		||||
        $item_taxes = [];
 | 
			
		||||
        $item_tax_total = 0;
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->data['tax_id'])) {
 | 
			
		||||
            $inclusives = $compounds = $taxes = [];
 | 
			
		||||
        if (!empty($this->request['tax_id'])) {
 | 
			
		||||
            $inclusives = $compounds = [];
 | 
			
		||||
 | 
			
		||||
            foreach ((array) $this->data['tax_id'] as $tax_id) {
 | 
			
		||||
            foreach ((array) $this->request['tax_id'] as $tax_id) {
 | 
			
		||||
                $tax = Tax::find($tax_id);
 | 
			
		||||
 | 
			
		||||
                switch ($tax->type) {
 | 
			
		||||
                    case 'inclusive':
 | 
			
		||||
                        $inclusives[] = $tax;
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'compound':
 | 
			
		||||
                        $compounds[] = $tax;
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'fixed':
 | 
			
		||||
                        $fixed_taxes[] = $tax;
 | 
			
		||||
                        $tax_amount = $tax->rate;
 | 
			
		||||
                        $tax_amount = $tax->rate * (double) $this->request['quantity'];
 | 
			
		||||
 | 
			
		||||
                        $item_taxes[] = [
 | 
			
		||||
                            'company_id' => $this->invoice->company_id,
 | 
			
		||||
@@ -77,12 +74,10 @@ class CreateBillItem extends Job
 | 
			
		||||
                        ];
 | 
			
		||||
 | 
			
		||||
                        $item_tax_total += $tax_amount;
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'normal':
 | 
			
		||||
                    default:
 | 
			
		||||
                        $taxes[] = $tax;
 | 
			
		||||
 | 
			
		||||
                        $tax_amount = ($item_discount_amount / 100) * $tax->rate;
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        $tax_amount = ($item_discounted_amount / 100) * $tax->rate;
 | 
			
		||||
 | 
			
		||||
                        $item_taxes[] = [
 | 
			
		||||
                            'company_id' => $this->bill->company_id,
 | 
			
		||||
@@ -93,12 +88,13 @@ class CreateBillItem extends Job
 | 
			
		||||
                        ];
 | 
			
		||||
 | 
			
		||||
                        $item_tax_total += $tax_amount;
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($inclusives) {
 | 
			
		||||
                $item_amount = $item_discount_amount + $item_tax_total;
 | 
			
		||||
                $item_amount = $item_discounted_amount + $item_tax_total;
 | 
			
		||||
 | 
			
		||||
                $item_base_rate = $item_amount / (1 + collect($inclusives)->sum('rate') / 100);
 | 
			
		||||
 | 
			
		||||
@@ -114,12 +110,12 @@ class CreateBillItem extends Job
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $item_amount = ($item_amount - $item_tax_total) / (1 - $this->discount / 100);
 | 
			
		||||
                $item_amount = ($item_amount - $item_tax_total) / (1 - $this->request['discount'] / 100);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($compounds) {
 | 
			
		||||
                foreach ($compounds as $compound) {
 | 
			
		||||
                    $tax_amount = (($item_discount_amount + $item_tax_total) / 100) * $compound->rate;
 | 
			
		||||
                    $tax_amount = (($item_discounted_amount + $item_tax_total) / 100) * $compound->rate;
 | 
			
		||||
 | 
			
		||||
                    $item_tax_total += $tax_amount;
 | 
			
		||||
 | 
			
		||||
@@ -138,9 +134,9 @@ class CreateBillItem extends Job
 | 
			
		||||
            'company_id' => $this->bill->company_id,
 | 
			
		||||
            'bill_id' => $this->bill->id,
 | 
			
		||||
            'item_id' => $item_id,
 | 
			
		||||
            'name' => Str::limit($this->data['name'], 180, ''),
 | 
			
		||||
            'quantity' => (double) $this->data['quantity'],
 | 
			
		||||
            'price' => (double) $this->data['price'],
 | 
			
		||||
            'name' => Str::limit($this->request['name'], 180, ''),
 | 
			
		||||
            'quantity' => (double) $this->request['quantity'],
 | 
			
		||||
            'price' => (double) $this->request['price'],
 | 
			
		||||
            'tax' => $item_tax_total,
 | 
			
		||||
            'total' => $item_amount,
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -149,28 +145,15 @@ class CreateBillItem extends Job
 | 
			
		||||
        $bill_item->inclusives = false;
 | 
			
		||||
        $bill_item->compounds = false;
 | 
			
		||||
 | 
			
		||||
        // set item_taxes for
 | 
			
		||||
        if (!empty($this->data['tax_id'])) {
 | 
			
		||||
        if (!empty($item_taxes)) {
 | 
			
		||||
            $bill_item->item_taxes = $item_taxes;
 | 
			
		||||
            $bill_item->inclusives = $inclusives;
 | 
			
		||||
            $bill_item->compounds = $compounds;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($item_taxes) {
 | 
			
		||||
            foreach ($item_taxes as $item_tax) {
 | 
			
		||||
                $item_tax['bill_item_id'] = $bill_item->id;
 | 
			
		||||
 | 
			
		||||
                BillItemTax::create($item_tax);
 | 
			
		||||
 | 
			
		||||
                // Set taxes
 | 
			
		||||
                if (isset($taxes) && array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                        'name' => $item_tax['name'],
 | 
			
		||||
                        'amount' => $item_tax['amount']
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,16 +3,17 @@
 | 
			
		||||
namespace App\Jobs\Expense;
 | 
			
		||||
 | 
			
		||||
use App\Abstracts\Job;
 | 
			
		||||
use App\Models\Common\Item;
 | 
			
		||||
use App\Events\Expense\BillUpdated;
 | 
			
		||||
use App\Events\Expense\BillUpdating;
 | 
			
		||||
use App\Models\Expense\Bill;
 | 
			
		||||
use App\Models\Expense\BillTotal;
 | 
			
		||||
use App\Traits\Currencies;
 | 
			
		||||
use App\Traits\DateTime;
 | 
			
		||||
use Illuminate\Database\Eloquent\Collection;
 | 
			
		||||
use App\Traits\Relationships;
 | 
			
		||||
 | 
			
		||||
class UpdateBill extends Job
 | 
			
		||||
{
 | 
			
		||||
    use Currencies, DateTime;
 | 
			
		||||
    use Currencies, DateTime, Relationships;
 | 
			
		||||
 | 
			
		||||
    protected $bill;
 | 
			
		||||
 | 
			
		||||
@@ -36,6 +37,12 @@ class UpdateBill extends Job
 | 
			
		||||
     */
 | 
			
		||||
    public function handle()
 | 
			
		||||
    {
 | 
			
		||||
        if (empty($this->request['amount'])) {
 | 
			
		||||
            $this->request['amount'] = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        event(new BillUpdating($this->bill, $this->request));
 | 
			
		||||
 | 
			
		||||
        // Upload attachment
 | 
			
		||||
        if ($this->request->file('attachment')) {
 | 
			
		||||
            $media = $this->getMedia($this->request->file('attachment'), 'bills');
 | 
			
		||||
@@ -43,51 +50,7 @@ class UpdateBill extends Job
 | 
			
		||||
            $this->bill->attachMedia($media, 'attachment');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $taxes = [];
 | 
			
		||||
 | 
			
		||||
        $tax_total = 0;
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
        $discount_total = 0;
 | 
			
		||||
        $discount = $this->request['discount'];
 | 
			
		||||
 | 
			
		||||
        if ($this->request['items']) {
 | 
			
		||||
            $this->deleteRelationships($this->bill, ['items', 'item_taxes']);
 | 
			
		||||
 | 
			
		||||
            foreach ($this->request['items'] as $item) {
 | 
			
		||||
                $bill_item = dispatch_now(new CreateBillItem($item, $this->bill, $discount));
 | 
			
		||||
 | 
			
		||||
                // Calculate totals
 | 
			
		||||
                $tax_total += $bill_item->tax;
 | 
			
		||||
                $sub_total += $bill_item->total;
 | 
			
		||||
 | 
			
		||||
                // Set taxes
 | 
			
		||||
                if ($bill_item->item_taxes) {
 | 
			
		||||
                    foreach ($bill_item->item_taxes as $item_tax) {
 | 
			
		||||
                        if (isset($taxes) && array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                            $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                        } else {
 | 
			
		||||
                            $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                                'name' => $item_tax['name'],
 | 
			
		||||
                                'amount' => $item_tax['amount']
 | 
			
		||||
                            ];
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $s_total = $sub_total;
 | 
			
		||||
 | 
			
		||||
        // Apply discount to total
 | 
			
		||||
        if ($discount) {
 | 
			
		||||
            $s_discount = $s_total * ($discount / 100);
 | 
			
		||||
            $discount_total += $s_discount;
 | 
			
		||||
            $s_total = $s_total - $s_discount;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $amount = $s_total + $tax_total;
 | 
			
		||||
 | 
			
		||||
        $this->request['amount'] = money($amount, $this->request['currency_code'])->getAmount();
 | 
			
		||||
        $this->createItemsAndTotals();
 | 
			
		||||
 | 
			
		||||
        $bill_paid = $this->bill->paid;
 | 
			
		||||
 | 
			
		||||
@@ -99,124 +62,148 @@ class UpdateBill extends Job
 | 
			
		||||
 | 
			
		||||
        $this->bill->update($this->request->input());
 | 
			
		||||
 | 
			
		||||
        // Delete previous bill totals
 | 
			
		||||
        $this->deleteRelationships($this->bill, 'totals');
 | 
			
		||||
 | 
			
		||||
        // Add bill totals
 | 
			
		||||
        $this->addTotals($this->bill, $this->request, $taxes, $sub_total, $discount_total, $tax_total);
 | 
			
		||||
 | 
			
		||||
        // Recurring
 | 
			
		||||
        $this->bill->updateRecurring();
 | 
			
		||||
 | 
			
		||||
        // Fire the event to make it extensible
 | 
			
		||||
        event(new \App\Events\Expense\BillUpdated($this->bill));
 | 
			
		||||
        event(new BillUpdated($this->bill));
 | 
			
		||||
 | 
			
		||||
        return $this->bill;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function addTotals($bill, $request, $taxes, $sub_total, $discount_total, $tax_total)
 | 
			
		||||
    protected function createItemsAndTotals()
 | 
			
		||||
    {
 | 
			
		||||
        // Check if totals are in request, i.e. api
 | 
			
		||||
        if (!empty($request['totals'])) {
 | 
			
		||||
            $sort_order = 1;
 | 
			
		||||
        // Create items
 | 
			
		||||
        list($sub_total, $taxes) = $this->createItems();
 | 
			
		||||
 | 
			
		||||
            foreach ($request['totals'] as $total) {
 | 
			
		||||
                $total['bill_id'] = $bill->id;
 | 
			
		||||
 | 
			
		||||
                if (empty($total['sort_order'])) {
 | 
			
		||||
                    $total['sort_order'] = $sort_order;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                BillTotal::create($total);
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // Delete current totals
 | 
			
		||||
        $this->deleteRelationships($this->bill, 'totals');
 | 
			
		||||
 | 
			
		||||
        $sort_order = 1;
 | 
			
		||||
 | 
			
		||||
        // Added bill sub total
 | 
			
		||||
        // Add sub total
 | 
			
		||||
        BillTotal::create([
 | 
			
		||||
            'company_id' => $request['company_id'],
 | 
			
		||||
            'bill_id' => $bill->id,
 | 
			
		||||
            'company_id' => $this->bill->company_id,
 | 
			
		||||
            'bill_id' => $this->bill->id,
 | 
			
		||||
            'code' => 'sub_total',
 | 
			
		||||
            'name' => 'bills.sub_total',
 | 
			
		||||
            'amount' => $sub_total,
 | 
			
		||||
            'sort_order' => $sort_order,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $this->request['amount'] += $sub_total;
 | 
			
		||||
 | 
			
		||||
        $sort_order++;
 | 
			
		||||
 | 
			
		||||
        // Added bill discount
 | 
			
		||||
        if ($discount_total) {
 | 
			
		||||
        // Add discount
 | 
			
		||||
        if (!empty($this->request['discount'])) {
 | 
			
		||||
            $discount_total = $sub_total * ($this->request['discount'] / 100);
 | 
			
		||||
 | 
			
		||||
            BillTotal::create([
 | 
			
		||||
                'company_id' => $request['company_id'],
 | 
			
		||||
                'bill_id' => $bill->id,
 | 
			
		||||
                'company_id' => $this->bill->company_id,
 | 
			
		||||
                'bill_id' => $this->bill->id,
 | 
			
		||||
                'code' => 'discount',
 | 
			
		||||
                'name' => 'bills.discount',
 | 
			
		||||
                'amount' => $discount_total,
 | 
			
		||||
                'sort_order' => $sort_order,
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
            // This is for total
 | 
			
		||||
            $sub_total = $sub_total - $discount_total;
 | 
			
		||||
            $this->request['amount'] -= $discount_total;
 | 
			
		||||
 | 
			
		||||
            $sort_order++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Added bill taxes
 | 
			
		||||
        if (isset($taxes)) {
 | 
			
		||||
        // Add taxes
 | 
			
		||||
        if (!empty($taxes)) {
 | 
			
		||||
            foreach ($taxes as $tax) {
 | 
			
		||||
                BillTotal::create([
 | 
			
		||||
                    'company_id' => $request['company_id'],
 | 
			
		||||
                    'bill_id' => $bill->id,
 | 
			
		||||
                    'company_id' => $this->bill->company_id,
 | 
			
		||||
                    'bill_id' => $this->bill->id,
 | 
			
		||||
                    'code' => 'tax',
 | 
			
		||||
                    'name' => $tax['name'],
 | 
			
		||||
                    'amount' => $tax['amount'],
 | 
			
		||||
                    'sort_order' => $sort_order,
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                $this->request['amount'] += $tax['amount'];
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Added bill total
 | 
			
		||||
        // Add extra totals, i.e. shipping fee
 | 
			
		||||
        if (!empty($this->request['totals'])) {
 | 
			
		||||
            foreach ($this->request['totals'] as $total) {
 | 
			
		||||
                $total['company_id'] = $this->bill->company_id;
 | 
			
		||||
                $total['bill_id'] = $this->bill->id;
 | 
			
		||||
                $total['sort_order'] = $sort_order;
 | 
			
		||||
 | 
			
		||||
                if (empty($total['code'])) {
 | 
			
		||||
                    $total['code'] = 'extra';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                BillTotal::create($total);
 | 
			
		||||
 | 
			
		||||
                if (empty($total['operator']) || ($total['operator'] == 'addition')) {
 | 
			
		||||
                    $this->request['amount'] += $total['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    // subtraction
 | 
			
		||||
                    $this->request['amount'] -= $total['amount'];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add total
 | 
			
		||||
        BillTotal::create([
 | 
			
		||||
            'company_id' => $request['company_id'],
 | 
			
		||||
            'bill_id' => $bill->id,
 | 
			
		||||
            'company_id' => $this->bill->company_id,
 | 
			
		||||
            'bill_id' => $this->bill->id,
 | 
			
		||||
            'code' => 'total',
 | 
			
		||||
            'name' => 'bills.total',
 | 
			
		||||
            'amount' => $sub_total + $tax_total,
 | 
			
		||||
            'amount' => $this->request['amount'],
 | 
			
		||||
            'sort_order' => $sort_order,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Mass delete relationships with events being fired.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $model
 | 
			
		||||
     * @param  $relationships
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function deleteRelationships($model, $relationships)
 | 
			
		||||
    protected function createItems()
 | 
			
		||||
    {
 | 
			
		||||
        foreach ((array) $relationships as $relationship) {
 | 
			
		||||
            if (empty($model->$relationship)) {
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
 | 
			
		||||
        $taxes = [];
 | 
			
		||||
 | 
			
		||||
        if (empty($this->request['items'])) {
 | 
			
		||||
            return [$sub_total, $taxes];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Delete current items
 | 
			
		||||
        $this->deleteRelationships($this->bill, ['items', 'item_taxes']);
 | 
			
		||||
 | 
			
		||||
        foreach ((array) $this->request['items'] as $item) {
 | 
			
		||||
            if (empty($item['discount'])) {
 | 
			
		||||
                $item['discount'] = !empty($this->request['discount']) ? !empty($this->request['discount']) : 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $bill_item = $this->dispatch(new CreateBillItem($item, $this->bill));
 | 
			
		||||
 | 
			
		||||
            // Calculate totals
 | 
			
		||||
            $sub_total += $bill_item->total;
 | 
			
		||||
 | 
			
		||||
            if (!$bill_item->item_taxes) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $items = $model->$relationship->all();
 | 
			
		||||
 | 
			
		||||
            if ($items instanceof Collection) {
 | 
			
		||||
                $items = $items->all();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach ((array) $items as $item) {
 | 
			
		||||
                $item->delete();
 | 
			
		||||
            // Set taxes
 | 
			
		||||
            foreach ((array) $bill_item->item_taxes as $item_tax) {
 | 
			
		||||
                if (array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                        'name' => $item_tax['name'],
 | 
			
		||||
                        'amount' => $item_tax['amount']
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [$sub_total, $taxes];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,14 +9,15 @@ use App\Models\Income\Invoice;
 | 
			
		||||
use App\Models\Income\InvoiceTotal;
 | 
			
		||||
use App\Traits\Currencies;
 | 
			
		||||
use App\Traits\DateTime;
 | 
			
		||||
use App\Traits\Incomes;
 | 
			
		||||
 | 
			
		||||
class CreateInvoice extends Job
 | 
			
		||||
{
 | 
			
		||||
    use Currencies, DateTime, Incomes;
 | 
			
		||||
    use Currencies, DateTime;
 | 
			
		||||
 | 
			
		||||
    protected $request;
 | 
			
		||||
 | 
			
		||||
    protected $invoice;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     *
 | 
			
		||||
@@ -40,148 +41,155 @@ class CreateInvoice extends Job
 | 
			
		||||
 | 
			
		||||
        event(new InvoiceCreating($this->request));
 | 
			
		||||
 | 
			
		||||
        $invoice = Invoice::create($this->request->all());
 | 
			
		||||
        $this->invoice = Invoice::create($this->request->all());
 | 
			
		||||
 | 
			
		||||
        // Upload attachment
 | 
			
		||||
        if ($this->request->file('attachment')) {
 | 
			
		||||
            $media = $this->getMedia($this->request->file('attachment'), 'invoices');
 | 
			
		||||
 | 
			
		||||
            $invoice->attachMedia($media, 'attachment');
 | 
			
		||||
            $this->invoice->attachMedia($media, 'attachment');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $taxes = [];
 | 
			
		||||
        $this->createItemsAndTotals();
 | 
			
		||||
 | 
			
		||||
        $tax_total = 0;
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
        $discount_total = 0;
 | 
			
		||||
        $discount = $this->request['discount'];
 | 
			
		||||
        $this->invoice->update($this->request->all());
 | 
			
		||||
 | 
			
		||||
        if ($this->request['items']) {
 | 
			
		||||
            foreach ($this->request['items'] as $item) {
 | 
			
		||||
                $invoice_item = $this->dispatch(new CreateInvoiceItem($item, $invoice, $discount));
 | 
			
		||||
        $this->invoice->createRecurring();
 | 
			
		||||
 | 
			
		||||
                // Calculate totals
 | 
			
		||||
                $tax_total += $invoice_item->tax;
 | 
			
		||||
                $sub_total += $invoice_item->total;
 | 
			
		||||
        event(new InvoiceCreated($this->invoice));
 | 
			
		||||
 | 
			
		||||
                // Set taxes
 | 
			
		||||
                if ($invoice_item->item_taxes) {
 | 
			
		||||
                    foreach ($invoice_item->item_taxes as $item_tax) {
 | 
			
		||||
                        if (isset($taxes) && array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                            $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                        } else {
 | 
			
		||||
                            $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                                'name' => $item_tax['name'],
 | 
			
		||||
                                'amount' => $item_tax['amount']
 | 
			
		||||
                            ];
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $s_total = $sub_total;
 | 
			
		||||
 | 
			
		||||
        // Apply discount to total
 | 
			
		||||
        if ($discount) {
 | 
			
		||||
            $s_discount = $s_total * ($discount / 100);
 | 
			
		||||
            $discount_total += $s_discount;
 | 
			
		||||
            $s_total = $s_total - $s_discount;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $amount = $s_total + $tax_total;
 | 
			
		||||
 | 
			
		||||
        $this->request['amount'] = money($amount, $this->request['currency_code'])->getAmount();
 | 
			
		||||
 | 
			
		||||
        $invoice->update($this->request->all());
 | 
			
		||||
 | 
			
		||||
        // Add invoice totals
 | 
			
		||||
        $this->addTotals($invoice, $this->request, $taxes, $sub_total, $discount_total, $tax_total);
 | 
			
		||||
 | 
			
		||||
        // Recurring
 | 
			
		||||
        $invoice->createRecurring();
 | 
			
		||||
 | 
			
		||||
        event(new InvoiceCreated($invoice));
 | 
			
		||||
 | 
			
		||||
        return $invoice;
 | 
			
		||||
        return $this->invoice;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function addTotals($invoice, $request, $taxes, $sub_total, $discount_total, $tax_total)
 | 
			
		||||
    protected function createItemsAndTotals()
 | 
			
		||||
    {
 | 
			
		||||
        // Check if totals are in request, i.e. api
 | 
			
		||||
        if (!empty($request['totals'])) {
 | 
			
		||||
            $sort_order = 1;
 | 
			
		||||
 | 
			
		||||
            foreach ($request['totals'] as $total) {
 | 
			
		||||
                $total['invoice_id'] = $invoice->id;
 | 
			
		||||
 | 
			
		||||
                if (empty($total['sort_order'])) {
 | 
			
		||||
                    $total['sort_order'] = $sort_order;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                InvoiceTotal::create($total);
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // Create items
 | 
			
		||||
        list($sub_total, $taxes) = $this->createItems();
 | 
			
		||||
 | 
			
		||||
        $sort_order = 1;
 | 
			
		||||
 | 
			
		||||
        // Added invoice sub total
 | 
			
		||||
        // Add sub total
 | 
			
		||||
        InvoiceTotal::create([
 | 
			
		||||
            'company_id' => $request['company_id'],
 | 
			
		||||
            'invoice_id' => $invoice->id,
 | 
			
		||||
            'company_id' => $this->invoice->company_id,
 | 
			
		||||
            'invoice_id' => $this->invoice->id,
 | 
			
		||||
            'code' => 'sub_total',
 | 
			
		||||
            'name' => 'invoices.sub_total',
 | 
			
		||||
            'amount' => $sub_total,
 | 
			
		||||
            'sort_order' => $sort_order,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $this->request['amount'] += $sub_total;
 | 
			
		||||
 | 
			
		||||
        $sort_order++;
 | 
			
		||||
 | 
			
		||||
        // Added invoice discount
 | 
			
		||||
        if ($discount_total) {
 | 
			
		||||
        // Add discount
 | 
			
		||||
        if (!empty($this->request['discount'])) {
 | 
			
		||||
            $discount_total = $sub_total * ($this->request['discount'] / 100);
 | 
			
		||||
 | 
			
		||||
            InvoiceTotal::create([
 | 
			
		||||
                'company_id' => $request['company_id'],
 | 
			
		||||
                'invoice_id' => $invoice->id,
 | 
			
		||||
                'company_id' => $this->invoice->company_id,
 | 
			
		||||
                'invoice_id' => $this->invoice->id,
 | 
			
		||||
                'code' => 'discount',
 | 
			
		||||
                'name' => 'invoices.discount',
 | 
			
		||||
                'amount' => $discount_total,
 | 
			
		||||
                'sort_order' => $sort_order,
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
            // This is for total
 | 
			
		||||
            $sub_total = $sub_total - $discount_total;
 | 
			
		||||
            $this->request['amount'] -= $discount_total;
 | 
			
		||||
 | 
			
		||||
            $sort_order++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Added invoice taxes
 | 
			
		||||
        if (isset($taxes)) {
 | 
			
		||||
        // Add taxes
 | 
			
		||||
        if (!empty($taxes)) {
 | 
			
		||||
            foreach ($taxes as $tax) {
 | 
			
		||||
                InvoiceTotal::create([
 | 
			
		||||
                    'company_id' => $request['company_id'],
 | 
			
		||||
                    'invoice_id' => $invoice->id,
 | 
			
		||||
                    'company_id' => $this->invoice->company_id,
 | 
			
		||||
                    'invoice_id' => $this->invoice->id,
 | 
			
		||||
                    'code' => 'tax',
 | 
			
		||||
                    'name' => $tax['name'],
 | 
			
		||||
                    'amount' => $tax['amount'],
 | 
			
		||||
                    'sort_order' => $sort_order,
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                $this->request['amount'] += $tax['amount'];
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Added invoice total
 | 
			
		||||
        // Add extra totals, i.e. shipping fee
 | 
			
		||||
        if (!empty($this->request['totals'])) {
 | 
			
		||||
            foreach ($this->request['totals'] as $total) {
 | 
			
		||||
                $total['company_id'] = $this->invoice->company_id;
 | 
			
		||||
                $total['invoice_id'] = $this->invoice->id;
 | 
			
		||||
                $total['sort_order'] = $sort_order;
 | 
			
		||||
 | 
			
		||||
                if (empty($total['code'])) {
 | 
			
		||||
                    $total['code'] = 'extra';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                InvoiceTotal::create($total);
 | 
			
		||||
 | 
			
		||||
                if (empty($total['operator']) || ($total['operator'] == 'addition')) {
 | 
			
		||||
                    $this->request['amount'] += $total['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    // subtraction
 | 
			
		||||
                    $this->request['amount'] -= $total['amount'];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add total
 | 
			
		||||
        InvoiceTotal::create([
 | 
			
		||||
            'company_id' => $request['company_id'],
 | 
			
		||||
            'invoice_id' => $invoice->id,
 | 
			
		||||
            'company_id' => $this->invoice->company_id,
 | 
			
		||||
            'invoice_id' => $this->invoice->id,
 | 
			
		||||
            'code' => 'total',
 | 
			
		||||
            'name' => 'invoices.total',
 | 
			
		||||
            'amount' => $sub_total + $tax_total,
 | 
			
		||||
            'amount' => $this->request['amount'],
 | 
			
		||||
            'sort_order' => $sort_order,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function createItems()
 | 
			
		||||
    {
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
 | 
			
		||||
        $taxes = [];
 | 
			
		||||
 | 
			
		||||
        if (empty($this->request['items'])) {
 | 
			
		||||
            return [$sub_total, $taxes];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        foreach ((array) $this->request['items'] as $item) {
 | 
			
		||||
            if (empty($item['discount'])) {
 | 
			
		||||
                $item['discount'] = !empty($this->request['discount']) ? !empty($this->request['discount']) : 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $invoice_item = $this->dispatch(new CreateInvoiceItem($item, $this->invoice));
 | 
			
		||||
 | 
			
		||||
            // Calculate totals
 | 
			
		||||
            $sub_total += $invoice_item->total;
 | 
			
		||||
 | 
			
		||||
            if (!$invoice_item->item_taxes) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Set taxes
 | 
			
		||||
            foreach ((array) $invoice_item->item_taxes as $item_tax) {
 | 
			
		||||
                if (array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                        'name' => $item_tax['name'],
 | 
			
		||||
                        'amount' => $item_tax['amount']
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [$sub_total, $taxes];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,24 +10,20 @@ use Illuminate\Support\Str;
 | 
			
		||||
 | 
			
		||||
class CreateInvoiceItem extends Job
 | 
			
		||||
{
 | 
			
		||||
    protected $data;
 | 
			
		||||
    protected $request;
 | 
			
		||||
 | 
			
		||||
    protected $invoice;
 | 
			
		||||
 | 
			
		||||
    protected $discount;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a new job instance.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $data
 | 
			
		||||
     * @param  $request
 | 
			
		||||
     * @param  $invoice
 | 
			
		||||
     * @param  $discount
 | 
			
		||||
     */
 | 
			
		||||
    public function __construct($data, $invoice, $discount = null)
 | 
			
		||||
    public function __construct($request, $invoice)
 | 
			
		||||
    {
 | 
			
		||||
        $this->data = $data;
 | 
			
		||||
        $this->request = $request;
 | 
			
		||||
        $this->invoice = $invoice;
 | 
			
		||||
        $this->discount = $discount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -37,36 +33,37 @@ class CreateInvoiceItem extends Job
 | 
			
		||||
     */
 | 
			
		||||
    public function handle()
 | 
			
		||||
    {
 | 
			
		||||
        $item_id = !empty($this->data['item_id']) ? $this->data['item_id'] : 0;
 | 
			
		||||
        $item_amount = (double) $this->data['price'] * (double) $this->data['quantity'];
 | 
			
		||||
        $item_id = !empty($this->request['item_id']) ? $this->request['item_id'] : 0;
 | 
			
		||||
        $item_amount = (double) $this->request['price'] * (double) $this->request['quantity'];
 | 
			
		||||
 | 
			
		||||
        $item_discount_amount = $item_amount;
 | 
			
		||||
        $item_discounted_amount = $item_amount;
 | 
			
		||||
 | 
			
		||||
        // Apply discount to tax
 | 
			
		||||
        if ($this->discount) {
 | 
			
		||||
            $item_discount_amount = $item_amount - ($item_amount * ($this->discount / 100));
 | 
			
		||||
        // Apply discount to amount
 | 
			
		||||
        if (!empty($this->request['discount'])) {
 | 
			
		||||
            $item_discounted_amount = $item_amount - ($item_amount * ($this->request['discount'] / 100));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $tax_amount = 0;
 | 
			
		||||
        $item_taxes = [];
 | 
			
		||||
        $item_tax_total = 0;
 | 
			
		||||
 | 
			
		||||
        if (!empty($this->data['tax_id'])) {
 | 
			
		||||
            $inclusives = $compounds = $taxes = $fixed_taxes = [];
 | 
			
		||||
        if (!empty($this->request['tax_id'])) {
 | 
			
		||||
            $inclusives = $compounds = [];
 | 
			
		||||
 | 
			
		||||
            foreach ((array)$this->data['tax_id'] as $tax_id) {
 | 
			
		||||
            foreach ((array) $this->request['tax_id'] as $tax_id) {
 | 
			
		||||
                $tax = Tax::find($tax_id);
 | 
			
		||||
 | 
			
		||||
                switch ($tax->type) {
 | 
			
		||||
                    case 'inclusive':
 | 
			
		||||
                        $inclusives[] = $tax;
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'compound':
 | 
			
		||||
                        $compounds[] = $tax;
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'fixed':
 | 
			
		||||
                        $fixed_taxes[] = $tax;
 | 
			
		||||
                        $tax_amount = $tax->rate;
 | 
			
		||||
                        $tax_amount = $tax->rate * (double) $this->request['quantity'];
 | 
			
		||||
 | 
			
		||||
                        $item_taxes[] = [
 | 
			
		||||
                            'company_id' => $this->invoice->company_id,
 | 
			
		||||
@@ -77,12 +74,10 @@ class CreateInvoiceItem extends Job
 | 
			
		||||
                        ];
 | 
			
		||||
 | 
			
		||||
                        $item_tax_total += $tax_amount;
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                    case 'normal':
 | 
			
		||||
                    default:
 | 
			
		||||
                        $taxes[] = $tax;
 | 
			
		||||
 | 
			
		||||
                        $tax_amount = ($item_discount_amount / 100) * $tax->rate;
 | 
			
		||||
                        $tax_amount = ($item_discounted_amount / 100) * $tax->rate;
 | 
			
		||||
 | 
			
		||||
                        $item_taxes[] = [
 | 
			
		||||
                            'company_id' => $this->invoice->company_id,
 | 
			
		||||
@@ -93,12 +88,13 @@ class CreateInvoiceItem extends Job
 | 
			
		||||
                        ];
 | 
			
		||||
 | 
			
		||||
                        $item_tax_total += $tax_amount;
 | 
			
		||||
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($inclusives) {
 | 
			
		||||
                $item_amount = $item_discount_amount + $item_tax_total;
 | 
			
		||||
                $item_amount = $item_discounted_amount + $item_tax_total;
 | 
			
		||||
 | 
			
		||||
                $item_base_rate = $item_amount / (1 + collect($inclusives)->sum('rate') / 100);
 | 
			
		||||
 | 
			
		||||
@@ -114,12 +110,12 @@ class CreateInvoiceItem extends Job
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $item_amount = ($item_amount - $item_tax_total) / (1 - $this->discount / 100);
 | 
			
		||||
                $item_amount = ($item_amount - $item_tax_total) / (1 - $this->request['discount'] / 100);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if ($compounds) {
 | 
			
		||||
                foreach ($compounds as $compound) {
 | 
			
		||||
                    $tax_amount = (($item_discount_amount + $item_tax_total) / 100) * $compound->rate;
 | 
			
		||||
                    $tax_amount = (($item_discounted_amount + $item_tax_total) / 100) * $compound->rate;
 | 
			
		||||
 | 
			
		||||
                    $item_tax_total += $tax_amount;
 | 
			
		||||
 | 
			
		||||
@@ -138,9 +134,9 @@ class CreateInvoiceItem extends Job
 | 
			
		||||
            'company_id' => $this->invoice->company_id,
 | 
			
		||||
            'invoice_id' => $this->invoice->id,
 | 
			
		||||
            'item_id' => $item_id,
 | 
			
		||||
            'name' => Str::limit($this->data['name'], 180, ''),
 | 
			
		||||
            'quantity' => (double) $this->data['quantity'],
 | 
			
		||||
            'price' => (double) $this->data['price'],
 | 
			
		||||
            'name' => Str::limit($this->request['name'], 180, ''),
 | 
			
		||||
            'quantity' => (double) $this->request['quantity'],
 | 
			
		||||
            'price' => (double) $this->request['price'],
 | 
			
		||||
            'tax' => $item_tax_total,
 | 
			
		||||
            'total' => $item_amount,
 | 
			
		||||
        ]);
 | 
			
		||||
@@ -149,28 +145,15 @@ class CreateInvoiceItem extends Job
 | 
			
		||||
        $invoice_item->inclusives = false;
 | 
			
		||||
        $invoice_item->compounds = false;
 | 
			
		||||
 | 
			
		||||
        // set item_taxes for
 | 
			
		||||
        if (!empty($this->data['tax_id'])) {
 | 
			
		||||
        if (!empty($item_taxes)) {
 | 
			
		||||
            $invoice_item->item_taxes = $item_taxes;
 | 
			
		||||
            $invoice_item->inclusives = $inclusives;
 | 
			
		||||
            $invoice_item->compounds = $compounds;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ($item_taxes) {
 | 
			
		||||
            foreach ($item_taxes as $item_tax) {
 | 
			
		||||
                $item_tax['invoice_item_id'] = $invoice_item->id;
 | 
			
		||||
 | 
			
		||||
                InvoiceItemTax::create($item_tax);
 | 
			
		||||
 | 
			
		||||
                // Set taxes
 | 
			
		||||
                if (isset($taxes) && array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                        'name' => $item_tax['name'],
 | 
			
		||||
                        'amount' => $item_tax['amount']
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,17 +3,17 @@
 | 
			
		||||
namespace App\Jobs\Income;
 | 
			
		||||
 | 
			
		||||
use App\Abstracts\Job;
 | 
			
		||||
use App\Models\Common\Item;
 | 
			
		||||
use App\Events\Income\InvoiceUpdated;
 | 
			
		||||
use App\Events\Income\InvoiceUpdating;
 | 
			
		||||
use App\Models\Income\Invoice;
 | 
			
		||||
use App\Models\Income\InvoiceTotal;
 | 
			
		||||
use App\Traits\Currencies;
 | 
			
		||||
use App\Traits\DateTime;
 | 
			
		||||
use App\Traits\Incomes;
 | 
			
		||||
use Illuminate\Database\Eloquent\Collection;
 | 
			
		||||
use App\Traits\Relationships;
 | 
			
		||||
 | 
			
		||||
class UpdateInvoice extends Job
 | 
			
		||||
{
 | 
			
		||||
    use Currencies, DateTime, Incomes;
 | 
			
		||||
    use Currencies, DateTime, Relationships;
 | 
			
		||||
 | 
			
		||||
    protected $invoice;
 | 
			
		||||
 | 
			
		||||
@@ -37,7 +37,11 @@ class UpdateInvoice extends Job
 | 
			
		||||
     */
 | 
			
		||||
    public function handle()
 | 
			
		||||
    {
 | 
			
		||||
        event(new \App\Events\Income\InvoiceUpdating($this->invoice, $this->request));
 | 
			
		||||
        if (empty($this->request['amount'])) {
 | 
			
		||||
            $this->request['amount'] = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        event(new InvoiceUpdating($this->invoice, $this->request));
 | 
			
		||||
 | 
			
		||||
        // Upload attachment
 | 
			
		||||
        if ($this->request->file('attachment')) {
 | 
			
		||||
@@ -46,51 +50,7 @@ class UpdateInvoice extends Job
 | 
			
		||||
            $this->invoice->attachMedia($media, 'attachment');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $taxes = [];
 | 
			
		||||
 | 
			
		||||
        $tax_total = 0;
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
        $discount_total = 0;
 | 
			
		||||
        $discount = $this->request['discount'];
 | 
			
		||||
 | 
			
		||||
        if ($this->request['items']) {
 | 
			
		||||
            $this->deleteRelationships($this->invoice, ['items', 'item_taxes']);
 | 
			
		||||
 | 
			
		||||
            foreach ($this->request['items'] as $item) {
 | 
			
		||||
                $invoice_item = dispatch_now(new CreateInvoiceItem($item, $this->invoice, $discount));
 | 
			
		||||
 | 
			
		||||
                // Calculate totals
 | 
			
		||||
                $tax_total += $invoice_item->tax;
 | 
			
		||||
                $sub_total += $invoice_item->total;
 | 
			
		||||
 | 
			
		||||
                // Set taxes
 | 
			
		||||
                if ($invoice_item->item_taxes) {
 | 
			
		||||
                    foreach ($invoice_item->item_taxes as $item_tax) {
 | 
			
		||||
                        if (isset($taxes) && array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                            $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                        } else {
 | 
			
		||||
                            $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                                'name' => $item_tax['name'],
 | 
			
		||||
                                'amount' => $item_tax['amount']
 | 
			
		||||
                            ];
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $s_total = $sub_total;
 | 
			
		||||
 | 
			
		||||
        // Apply discount to total
 | 
			
		||||
        if ($discount) {
 | 
			
		||||
            $s_discount = $s_total * ($discount / 100);
 | 
			
		||||
            $discount_total += $s_discount;
 | 
			
		||||
            $s_total = $s_total - $s_discount;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $amount = $s_total + $tax_total;
 | 
			
		||||
 | 
			
		||||
        $this->request['amount'] = money($amount, $this->request['currency_code'])->getAmount();
 | 
			
		||||
        $this->createItemsAndTotals();
 | 
			
		||||
 | 
			
		||||
        $invoice_paid = $this->invoice->paid;
 | 
			
		||||
 | 
			
		||||
@@ -100,125 +60,150 @@ class UpdateInvoice extends Job
 | 
			
		||||
            $this->request['invoice_status_code'] = 'partial';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $this->invoice->update($this->request->input());
 | 
			
		||||
        $this->invoice->update($this->request->all());
 | 
			
		||||
 | 
			
		||||
        // Delete previous invoice totals
 | 
			
		||||
        $this->deleteRelationships($this->invoice, 'totals');
 | 
			
		||||
 | 
			
		||||
        // Add invoice totals
 | 
			
		||||
        $this->addTotals($this->invoice, $this->request, $taxes, $sub_total, $discount_total, $tax_total);
 | 
			
		||||
 | 
			
		||||
        // Recurring
 | 
			
		||||
        $this->invoice->updateRecurring();
 | 
			
		||||
 | 
			
		||||
        event(new \App\Events\Income\InvoiceUpdated($this->invoice, $this->request));
 | 
			
		||||
        event(new InvoiceUpdated($this->invoice, $this->request));
 | 
			
		||||
 | 
			
		||||
        return $this->invoice;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected function addTotals($invoice, $request, $taxes, $sub_total, $discount_total, $tax_total)
 | 
			
		||||
    protected function createItemsAndTotals()
 | 
			
		||||
    {
 | 
			
		||||
        // Check if totals are in request, i.e. api
 | 
			
		||||
        if (!empty($request['totals'])) {
 | 
			
		||||
            $sort_order = 1;
 | 
			
		||||
        // Create items
 | 
			
		||||
        list($sub_total, $taxes) = $this->createItems();
 | 
			
		||||
 | 
			
		||||
            foreach ($request['totals'] as $total) {
 | 
			
		||||
                $total['invoice_id'] = $invoice->id;
 | 
			
		||||
 | 
			
		||||
                if (empty($total['sort_order'])) {
 | 
			
		||||
                    $total['sort_order'] = $sort_order;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                InvoiceTotal::create($total);
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        // Delete current totals
 | 
			
		||||
        $this->deleteRelationships($this->invoice, 'totals');
 | 
			
		||||
 | 
			
		||||
        $sort_order = 1;
 | 
			
		||||
 | 
			
		||||
        // Added invoice sub total
 | 
			
		||||
        // Add sub total
 | 
			
		||||
        InvoiceTotal::create([
 | 
			
		||||
            'company_id' => $request['company_id'],
 | 
			
		||||
            'invoice_id' => $invoice->id,
 | 
			
		||||
            'company_id' => $this->invoice->company_id,
 | 
			
		||||
            'invoice_id' => $this->invoice->id,
 | 
			
		||||
            'code' => 'sub_total',
 | 
			
		||||
            'name' => 'invoices.sub_total',
 | 
			
		||||
            'amount' => $sub_total,
 | 
			
		||||
            'sort_order' => $sort_order,
 | 
			
		||||
        ]);
 | 
			
		||||
 | 
			
		||||
        $this->request['amount'] += $sub_total;
 | 
			
		||||
 | 
			
		||||
        $sort_order++;
 | 
			
		||||
 | 
			
		||||
        // Added invoice discount
 | 
			
		||||
        if ($discount_total) {
 | 
			
		||||
        // Add discount
 | 
			
		||||
        if (!empty($this->request['discount'])) {
 | 
			
		||||
            $discount_total = $sub_total * ($this->request['discount'] / 100);
 | 
			
		||||
 | 
			
		||||
            InvoiceTotal::create([
 | 
			
		||||
                'company_id' => $request['company_id'],
 | 
			
		||||
                'invoice_id' => $invoice->id,
 | 
			
		||||
                'company_id' => $this->invoice->company_id,
 | 
			
		||||
                'invoice_id' => $this->invoice->id,
 | 
			
		||||
                'code' => 'discount',
 | 
			
		||||
                'name' => 'invoices.discount',
 | 
			
		||||
                'amount' => $discount_total,
 | 
			
		||||
                'sort_order' => $sort_order,
 | 
			
		||||
            ]);
 | 
			
		||||
 | 
			
		||||
            // This is for total
 | 
			
		||||
            $sub_total = $sub_total - $discount_total;
 | 
			
		||||
            $this->request['amount'] -= $discount_total;
 | 
			
		||||
 | 
			
		||||
            $sort_order++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Added invoice taxes
 | 
			
		||||
        if (isset($taxes)) {
 | 
			
		||||
        // Add taxes
 | 
			
		||||
        if (!empty($taxes)) {
 | 
			
		||||
            foreach ($taxes as $tax) {
 | 
			
		||||
                InvoiceTotal::create([
 | 
			
		||||
                    'company_id' => $request['company_id'],
 | 
			
		||||
                    'invoice_id' => $invoice->id,
 | 
			
		||||
                    'company_id' => $this->invoice->company_id,
 | 
			
		||||
                    'invoice_id' => $this->invoice->id,
 | 
			
		||||
                    'code' => 'tax',
 | 
			
		||||
                    'name' => $tax['name'],
 | 
			
		||||
                    'amount' => $tax['amount'],
 | 
			
		||||
                    'sort_order' => $sort_order,
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                $this->request['amount'] += $tax['amount'];
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Added invoice total
 | 
			
		||||
        // Add extra totals, i.e. shipping fee
 | 
			
		||||
        if (!empty($this->request['totals'])) {
 | 
			
		||||
            foreach ($this->request['totals'] as $total) {
 | 
			
		||||
                $total['company_id'] = $this->invoice->company_id;
 | 
			
		||||
                $total['invoice_id'] = $this->invoice->id;
 | 
			
		||||
                $total['sort_order'] = $sort_order;
 | 
			
		||||
 | 
			
		||||
                if (empty($total['code'])) {
 | 
			
		||||
                    $total['code'] = 'extra';
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                InvoiceTotal::create($total);
 | 
			
		||||
 | 
			
		||||
                if (empty($total['operator']) || ($total['operator'] == 'addition')) {
 | 
			
		||||
                    $this->request['amount'] += $total['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    // subtraction
 | 
			
		||||
                    $this->request['amount'] -= $total['amount'];
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                $sort_order++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Add total
 | 
			
		||||
        InvoiceTotal::create([
 | 
			
		||||
            'company_id' => $request['company_id'],
 | 
			
		||||
            'invoice_id' => $invoice->id,
 | 
			
		||||
            'company_id' => $this->invoice->company_id,
 | 
			
		||||
            'invoice_id' => $this->invoice->id,
 | 
			
		||||
            'code' => 'total',
 | 
			
		||||
            'name' => 'invoices.total',
 | 
			
		||||
            'amount' => $sub_total + $tax_total,
 | 
			
		||||
            'amount' => $this->request['amount'],
 | 
			
		||||
            'sort_order' => $sort_order,
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Mass delete relationships with events being fired.
 | 
			
		||||
     *
 | 
			
		||||
     * @param  $model
 | 
			
		||||
     * @param  $relationships
 | 
			
		||||
     *
 | 
			
		||||
     * @return void
 | 
			
		||||
     */
 | 
			
		||||
    public function deleteRelationships($model, $relationships)
 | 
			
		||||
    protected function createItems()
 | 
			
		||||
    {
 | 
			
		||||
        foreach ((array) $relationships as $relationship) {
 | 
			
		||||
            if (empty($model->$relationship)) {
 | 
			
		||||
        $sub_total = 0;
 | 
			
		||||
 | 
			
		||||
        $taxes = [];
 | 
			
		||||
 | 
			
		||||
        if (empty($this->request['items'])) {
 | 
			
		||||
            return [$sub_total, $taxes];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Delete current items
 | 
			
		||||
        $this->deleteRelationships($this->invoice, ['items', 'item_taxes']);
 | 
			
		||||
 | 
			
		||||
        foreach ((array) $this->request['items'] as $item) {
 | 
			
		||||
            if (empty($item['discount'])) {
 | 
			
		||||
                $item['discount'] = !empty($this->request['discount']) ? !empty($this->request['discount']) : 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $invoice_item = $this->dispatch(new CreateInvoiceItem($item, $this->invoice));
 | 
			
		||||
 | 
			
		||||
            // Calculate totals
 | 
			
		||||
            $sub_total += $invoice_item->total;
 | 
			
		||||
 | 
			
		||||
            if (!$invoice_item->item_taxes) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            $items = $model->$relationship->all();
 | 
			
		||||
 | 
			
		||||
            if ($items instanceof Collection) {
 | 
			
		||||
                $items = $items->all();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            foreach ((array) $items as $item) {
 | 
			
		||||
                $item->delete();
 | 
			
		||||
            // Set taxes
 | 
			
		||||
            foreach ((array) $invoice_item->item_taxes as $item_tax) {
 | 
			
		||||
                if (array_key_exists($item_tax['tax_id'], $taxes)) {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount'];
 | 
			
		||||
                } else {
 | 
			
		||||
                    $taxes[$item_tax['tax_id']] = [
 | 
			
		||||
                        'name' => $item_tax['name'],
 | 
			
		||||
                        'amount' => $item_tax['amount']
 | 
			
		||||
                    ];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return [$sub_total, $taxes];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ $factory->define(Item::class, function (Faker $faker) {
 | 
			
		||||
		'purchase_price' => $faker->randomFloat(2, 10, 20),
 | 
			
		||||
		'sale_price' => $faker->randomFloat(2, 10, 20),
 | 
			
		||||
		'category_id' => $company->categories()->type('item')->pluck('id')->first(),
 | 
			
		||||
		'tax_id' => 0,
 | 
			
		||||
		'enabled' => $faker->boolean ? 1 : 0
 | 
			
		||||
		'tax_id' => null,
 | 
			
		||||
		'enabled' => $faker->boolean ? 1 : 0,
 | 
			
		||||
	];
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user