From 79ebd9d025cf4fbb740993d7b1f38609daec6d00 Mon Sep 17 00:00:00 2001 From: cuneytsenturk Date: Tue, 6 Nov 2018 17:55:31 +0300 Subject: [PATCH] Tax rate change workflow. --- app/Http/Controllers/Common/Items.php | 68 ++++++++++- app/Http/Controllers/Settings/Taxes.php | 16 ++- app/Jobs/Income/CreateInvoice.php | 2 +- app/Jobs/Income/CreateInvoiceItem.php | 113 +++++++++++++----- app/Models/Income/Invoice.php | 4 + app/Models/Setting/Tax.php | 2 +- .../2018_11_05_000000_add_tax_columns.php | 6 +- resources/lang/en-GB/taxes.php | 1 + .../views/settings/taxes/create.blade.php | 14 +-- resources/views/settings/taxes/edit.blade.php | 12 +- 10 files changed, 176 insertions(+), 62 deletions(-) diff --git a/app/Http/Controllers/Common/Items.php b/app/Http/Controllers/Common/Items.php index 67966cbc4..04bb2ebfe 100644 --- a/app/Http/Controllers/Common/Items.php +++ b/app/Http/Controllers/Common/Items.php @@ -323,20 +323,78 @@ class Items extends Controller $quantity = (double) $item['quantity']; $item_tax_total = 0; + $item_tax_amount = 0; + $item_sub_total = ($price * $quantity); + $item_discount_total = $item_sub_total; + + // Apply discount to item + if ($discount) { + $item_discount_total = $item_sub_total - ($item_sub_total * ($discount / 100)); + } if (!empty($item['tax_id'])) { + $calculates = $compounds = $taxes = []; + foreach ($item['tax_id'] as $tax_id) { $tax = Tax::find($tax_id); - $item_tax = (($price * $quantity) / 100) * $tax->rate; + switch ($tax->type) { + case 'calculate': + $calculates[] = $tax; + break; + case 'compound': + $compounds[] = $tax; + break; + case 'normal': + default: + $taxes[] = $tax; - // Apply discount to tax - if ($discount) { - $item_tax = $item_tax - ($item_tax * ($discount / 100)); + $item_tax_amount = ($item_discount_total / 100) * $tax->rate; + + $item_tax_total += $item_tax_amount; + break; } + } - $item_tax_total += $item_tax; + if ($calculates) { + if ($discount) { + $item_tax_total = 0; + + if ($taxes) { + foreach ($taxes as $tax) { + $item_tax_amount = ($item_sub_total / 100) * $tax->rate; + + $item_tax_total += $item_tax_amount; + } + } + + foreach ($calculates as $calculate) { + $item_sub_and_tax_total = $item_sub_total + $item_tax_total; + + $item_tax_total = $item_sub_and_tax_total - (($item_sub_and_tax_total * (100 - $calculate->rate)) / 100); + + $item_sub_total = $item_sub_and_tax_total - $item_tax_total; + + $item_discount_total = $item_sub_total - ($item_sub_total * ($discount / 100)); + } + } else { + foreach ($calculates as $calculate) { + $item_sub_and_tax_total = $item_discount_total + $item_tax_total; + + $item_tax_total = $item_sub_and_tax_total - (($item_sub_and_tax_total * (100 - $calculate->rate)) / 100); + + $item_sub_total = $item_sub_and_tax_total - $item_tax_total; + + $item_discount_total = $item_sub_total - ($item_sub_total * ($discount / 100)); + } + } + } + + if ($compounds) { + foreach ($compounds as $compound) { + $item_tax_total += (($item_discount_total + $item_tax_total) / 100) * $compound->rate; + } } } diff --git a/app/Http/Controllers/Settings/Taxes.php b/app/Http/Controllers/Settings/Taxes.php index 89cfa594c..688dd99ef 100644 --- a/app/Http/Controllers/Settings/Taxes.php +++ b/app/Http/Controllers/Settings/Taxes.php @@ -38,7 +38,13 @@ class Taxes extends Controller */ public function create() { - return view('settings.taxes.create'); + $types = [ + 'normal' => trans('taxes.normal'), + 'calculate' => trans('taxes.calculate'), + 'compound' => trans('taxes.compound'), + ]; + + return view('settings.taxes.create', compact('types')); } /** @@ -68,7 +74,13 @@ class Taxes extends Controller */ public function edit(Tax $tax) { - return view('settings.taxes.edit', compact('tax')); + $types = [ + 'normal' => trans('taxes.normal'), + 'calculate' => trans('taxes.calculate'), + 'compound' => trans('taxes.compound'), + ]; + + return view('settings.taxes.edit', compact('tax', 'types')); } /** diff --git a/app/Jobs/Income/CreateInvoice.php b/app/Jobs/Income/CreateInvoice.php index 2bfe33453..936750bb3 100644 --- a/app/Jobs/Income/CreateInvoice.php +++ b/app/Jobs/Income/CreateInvoice.php @@ -159,4 +159,4 @@ class CreateInvoice 'sort_order' => $sort_order, ]); } -} \ No newline at end of file +} diff --git a/app/Jobs/Income/CreateInvoiceItem.php b/app/Jobs/Income/CreateInvoiceItem.php index ce1aec5cf..bbaf539df 100644 --- a/app/Jobs/Income/CreateInvoiceItem.php +++ b/app/Jobs/Income/CreateInvoiceItem.php @@ -44,6 +44,14 @@ class CreateInvoiceItem $item_sku = ''; $item_id = !empty($this->data['item_id']) ? $this->data['item_id'] : 0; + $item_amount = (double) $this->data['price'] * (double) $this->data['quantity']; + + $item_discount_amount = $item_amount; + + // Apply discount to tax + if ($this->discount) { + $item_discount_amount = $item_amount * ($this->discount / 100); + } if (!empty($item_id)) { $item_object = Item::find($item_id); @@ -85,32 +93,72 @@ class CreateInvoiceItem $item_sku = $this->data['sku']; } - $item_tax = 0; + $tax_amount = 0; $item_taxes = []; - $invoice_item_taxes = []; + $item_tax_total = 0; if (!empty($this->data['tax_id'])) { + $calculates = $compounds = []; + foreach ((array) $this->data['tax_id'] as $tax_id) { - $tax_object = Tax::find($tax_id); + $tax = Tax::find($tax_id); - $item_taxes[] = $tax_id; + switch ($tax->type) { + case 'calculate': + $calculates[] = $tax; + break; + case 'compound': + $compounds[] = $tax; + break; + case 'normal': + default: + $tax_amount = ($item_discount_amount / 100) * $tax->rate; - $tax = (((double) $this->data['price'] * (double) $this->data['quantity']) / 100) * $tax_object->rate; + $item_taxes[] = [ + 'company_id' => $this->invoice->company_id, + 'invoice_id' => $this->invoice->id, + 'tax_id' => $tax_id, + 'name' => $tax->name, + 'amount' => $tax_amount, + ]; - // Apply discount to tax - if ($this->discount) { - $tax = $tax - ($tax * ($this->discount / 100)); + $item_tax_total += $tax_amount; + break; } + } - $invoice_item_taxes[] = [ - 'company_id' => $this->invoice->company_id, - 'invoice_id' => $this->invoice->id, - 'tax_id' => $tax_id, - 'name' => $tax_object->name, - 'amount' => $tax, - ]; + if ($calculates) { + foreach ($calculates as $calculate) { + $item_sub_and_tax_total = $item_discount_amount + $item_tax_total; - $item_tax += $tax; + $item_tax_total = $tax_amount = $item_sub_and_tax_total - ($item_sub_and_tax_total / (1 + ($calculate->rate / 100))); + + $item_taxes[] = [ + 'company_id' => $this->invoice->company_id, + 'invoice_id' => $this->invoice->id, + 'tax_id' => $calculate->id, + 'name' => $calculate->name, + 'amount' => $tax_amount, + ]; + + $item_amount = $item_sub_and_tax_total - $item_tax_total; + } + } + + if ($compounds) { + foreach ($compounds as $compound) { + $tax_amount = (($item_discount_amount + $item_tax_total) / 100) * $compound->rate; + + $item_tax_total += $tax_amount; + + $item_taxes[] = [ + 'company_id' => $this->invoice->company_id, + 'invoice_id' => $this->invoice->id, + 'tax_id' => $compound->id, + 'name' => $compound->name, + 'amount' => $tax_amount, + ]; + } } } @@ -122,24 +170,31 @@ class CreateInvoiceItem 'sku' => $item_sku, 'quantity' => (double) $this->data['quantity'], 'price' => (double) $this->data['price'], - 'tax' => $item_tax, - 'tax_id' => 0, // (int) $item_taxes; - 'total' => (double) $this->data['price'] * (double) $this->data['quantity'], + 'tax' => $item_tax_total, + 'tax_id' => 0, + 'total' => $item_amount, ]); - if ($invoice_item_taxes) { - foreach ($invoice_item_taxes as $invoice_item_tax) { - $invoice_item_tax['invoice_item_id'] = $invoice_item->id; + if (!empty($this->data['tax_id'])) { + // set item_taxes for + $invoice_item->item_taxes = $item_taxes; + $invoice_item->calculates = $calculates; + $invoice_item->compounds = $compounds; + } - InvoiceItemTax::create($invoice_item_tax); + 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($invoice_item_tax['tax_id'], $taxes)) { - $taxes[$invoice_item_tax['tax_id']]['amount'] += $invoice_item_tax['amount']; + if (isset($taxes) && array_key_exists($item_tax['tax_id'], $taxes)) { + $taxes[$item_tax['tax_id']]['amount'] += $item_tax['amount']; } else { - $taxes[$invoice_item_tax['tax_id']] = [ - 'name' => $invoice_item_tax['name'], - 'amount' => $invoice_item_tax['amount'] + $taxes[$item_tax['tax_id']] = [ + 'name' => $item_tax['name'], + 'amount' => $item_tax['amount'] ]; } } @@ -147,4 +202,4 @@ class CreateInvoiceItem return $invoice_item; } -} \ No newline at end of file +} diff --git a/app/Models/Income/Invoice.php b/app/Models/Income/Invoice.php index ca992084a..5b6ec8aff 100644 --- a/app/Models/Income/Invoice.php +++ b/app/Models/Income/Invoice.php @@ -212,6 +212,10 @@ class Invoice extends Model */ public function getPaidAttribute() { + if (empty($this->amount)) { + return false; + } + $paid = 0; $reconciled = $reconciled_amount = 0; diff --git a/app/Models/Setting/Tax.php b/app/Models/Setting/Tax.php index 6ecaff7b5..f3a1ae00c 100644 --- a/app/Models/Setting/Tax.php +++ b/app/Models/Setting/Tax.php @@ -21,7 +21,7 @@ class Tax extends Model * * @var array */ - protected $fillable = ['company_id', 'name', 'rate', 'calculate', 'compound', 'enabled']; + protected $fillable = ['company_id', 'name', 'rate', 'type', 'enabled']; /** * Sortable columns. diff --git a/database/migrations/2018_11_05_000000_add_tax_columns.php b/database/migrations/2018_11_05_000000_add_tax_columns.php index 1952d882b..9edb97750 100644 --- a/database/migrations/2018_11_05_000000_add_tax_columns.php +++ b/database/migrations/2018_11_05_000000_add_tax_columns.php @@ -12,8 +12,7 @@ class AddTaxColumns extends Migration public function up() { Schema::table('taxes', function ($table) { - $table->boolean('calculate')->default(0); - $table->boolean('compound')->default(0); + $table->string('type')->default('normal'); }); } @@ -26,8 +25,7 @@ class AddTaxColumns extends Migration { Schema::table('taxes', function ($table) { $table->dropColumn([ - 'calculate', - 'compound', + 'type', ]); }); } diff --git a/resources/lang/en-GB/taxes.php b/resources/lang/en-GB/taxes.php index 229a6c2c3..180c8b0e1 100644 --- a/resources/lang/en-GB/taxes.php +++ b/resources/lang/en-GB/taxes.php @@ -4,6 +4,7 @@ return [ 'rate' => 'Rate', 'rate_percent' => 'Rate (%)', + 'normal' => 'Normal', 'calculate' => 'Calculate as VAT/GST', 'compound' => 'Compound', diff --git a/resources/views/settings/taxes/create.blade.php b/resources/views/settings/taxes/create.blade.php index d3a8e0863..3c72c35f5 100644 --- a/resources/views/settings/taxes/create.blade.php +++ b/resources/views/settings/taxes/create.blade.php @@ -12,9 +12,7 @@ {{ Form::textGroup('rate', trans('taxes.rate'), 'percent') }} - {{ Form::radioGroup('calculate', trans('taxes.calculate')) }} - - {{ Form::radioGroup('compound', trans('taxes.compound')) }} + {{ Form::selectGroup('type', trans_choice('general.types', 1), 'bars', $types, null, []) }} {{ Form::radioGroup('enabled', trans('general.enabled')) }} @@ -36,17 +34,11 @@ $(document).ready(function() { $('#enabled_1').trigger('click'); - $('#calculate_0').trigger('click'); - $('#compound_0').trigger('click'); $('#name').focus(); - $("#calculate").select2({ - placeholder: "{{ trans('general.form.select.field', ['field' => trans('taxes.calculate')]) }}" - }); - - $("#compound").select2({ - placeholder: "{{ trans('general.form.select.field', ['field' => trans('taxes.compound')]) }}" + $("#type").select2({ + placeholder: "{{ trans('general.form.select.field', ['field' => trans('general.type')]) }}" }); }); diff --git a/resources/views/settings/taxes/edit.blade.php b/resources/views/settings/taxes/edit.blade.php index 8bef1bf26..964fca602 100644 --- a/resources/views/settings/taxes/edit.blade.php +++ b/resources/views/settings/taxes/edit.blade.php @@ -17,9 +17,7 @@ {{ Form::textGroup('rate', trans('taxes.rate'), 'percent') }} - {{ Form::radioGroup('calculate', trans('taxes.calculate')) }} - - {{ Form::radioGroup('compound', trans('taxes.compound')) }} + {{ Form::selectGroup('type', trans('general.type'), 'bars', $types, null, []) }} {{ Form::radioGroup('enabled', trans('general.enabled')) }} @@ -44,12 +42,8 @@ $(document).ready(function() { $('#name').focus(); - $("#calculate").select2({ - placeholder: "{{ trans('general.form.select.field', ['field' => trans('taxes.calculate')]) }}" - }); - - $("#compound").select2({ - placeholder: "{{ trans('general.form.select.field', ['field' => trans('taxes.compound')]) }}" + $("#type").select2({ + placeholder: "{{ trans('general.form.select.field', ['field' => trans('general.type')]) }}" }); });