From 309442cab3003d6203e08cab759d610ca5e642d9 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Tue, 31 Dec 2013 21:49:54 +0200 Subject: [PATCH] Working on taxes --- app/controllers/InvoiceController.php | 30 ++-- ...11_05_180133_confide_setup_users_table.php | 6 + app/libraries/utils.php | 6 + app/models/Invoice.php | 8 +- app/ninja/repositories/InvoiceRepository.php | 43 +++--- app/views/error.blade.php | 7 + app/views/invoices/edit.blade.php | 138 +++++++++++++++--- public/js/script.js | 35 ++++- 8 files changed, 212 insertions(+), 61 deletions(-) create mode 100755 app/views/error.blade.php diff --git a/app/controllers/InvoiceController.php b/app/controllers/InvoiceController.php index b4b4d22cc419..a44d869f9215 100755 --- a/app/controllers/InvoiceController.php +++ b/app/controllers/InvoiceController.php @@ -134,7 +134,7 @@ class InvoiceController extends \BaseController { return View::make('invoices.deleted'); } - if ($invoice->invoice_status_id < INVOICE_STATUS_VIEWED) + if (!$invoice->isViewed()) { $invoice->invoice_status_id = INVOICE_STATUS_VIEWED; $invoice->save(); @@ -241,15 +241,13 @@ class InvoiceController extends \BaseController { } else { - + return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.

'); } } catch (\Exception $e) { - exit('Sorry, there was an error processing your payment. Please try again later.

'.$e); + return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.

'.$e); } - - exit; } public function do_payment() @@ -274,9 +272,12 @@ class InvoiceController extends \BaseController { $payment->transaction_reference = $ref; $payment->save(); - if ($payment->amount >= $invoice->amount) { + if ($payment->amount >= $invoice->amount) + { $invoice->invoice_status_id = INVOICE_STATUS_PAID; - } else { + } + else + { $invoice->invoice_status_id = INVOICE_STATUS_PARTIAL; } $invoice->save(); @@ -286,12 +287,12 @@ class InvoiceController extends \BaseController { } else { - exit($response->getMessage()); + return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.

'.$response->getMessage()); } } catch (\Exception $e) { - exit('Sorry, there was an error processing your payment. Please try again later.' . $e); + return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.

'.$e); } } @@ -404,11 +405,16 @@ class InvoiceController extends \BaseController { $invoiceData['client_id'] = $client->id; $invoice = $this->invoiceRepo->save($publicId, $invoiceData); + $account = Auth::user()->account; + if ($account->invoice_taxes != $input->invoice_taxes || $account->invoice_item_taxes != $input->invoice_item_taxes) + { + $account->invoice_taxes = $input->invoice_taxes; + $account->invoice_item_taxes = $input->invoice_item_taxes; + $account->save(); + } + if ($action == 'email' && $invoice->invoice_status_id == INVOICE_STATUS_DRAFT) { - $invoice->invoice_status_id = INVOICE_STATUS_SENT; - $invoice->save(); - $client->balance = $client->balance + $invoice->amount; $client->save(); } diff --git a/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php b/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php index 68586ff5b374..7467daa49a63 100755 --- a/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php +++ b/app/database/migrations/2013_11_05_180133_confide_setup_users_table.php @@ -125,6 +125,9 @@ class ConfideSetupUsersTable extends Migration { $t->unsignedInteger('country_id')->nullable(); $t->text('invoice_terms'); + $t->boolean('invoice_taxes')->default(true); + $t->boolean('invoice_item_taxes')->default(false); + $t->foreign('timezone_id')->references('id')->on('timezones'); $t->foreign('date_format_id')->references('id')->on('date_formats'); $t->foreign('datetime_format_id')->references('id')->on('datetime_formats'); @@ -303,6 +306,9 @@ class ConfideSetupUsersTable extends Migration { $t->timestamp('last_sent_date')->nullable(); $t->unsignedInteger('recurring_invoice_id')->index()->nullable(); + $t->string('tax_name'); + $t->decimal('tax_rate', 13, 4); + $t->decimal('amount', 13, 4); $t->decimal('balance', 13, 4); diff --git a/app/libraries/utils.php b/app/libraries/utils.php index 15620ac3f1e0..d79c0e611310 100755 --- a/app/libraries/utils.php +++ b/app/libraries/utils.php @@ -2,6 +2,12 @@ class Utils { + public static function fatalError($error) + { + Log::error($error); + return View::make('error')->with('error', $error); + } + public static function formatPhoneNumber($phoneNumber) { $phoneNumber = preg_replace('/[^0-9]/','',$phoneNumber); diff --git a/app/models/Invoice.php b/app/models/Invoice.php index 8893a8e4a6ad..e6c7f64b33f4 100755 --- a/app/models/Invoice.php +++ b/app/models/Invoice.php @@ -42,9 +42,15 @@ class Invoice extends EntityModel return $this->invoice_status_id >= INVOICE_STATUS_SENT; } + public function isViewed() + { + return $this->invoice_status_id >= INVOICE_STATUS_VIEWED; + } + public function hidePrivateFields() { - $this->setVisible(['invoice_number', 'discount', 'po_number', 'invoice_date', 'due_date', 'terms', 'currency_id', 'public_notes', 'amount', 'balance', 'invoice_items', 'client']); + $this->setVisible(['invoice_number', 'discount', 'po_number', 'invoice_date', 'due_date', 'terms', 'currency_id', 'public_notes', 'amount', 'balance', 'invoice_items', 'client', 'tax_name', 'tax_rate']); + $this->client->setVisible(['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'work_phone', 'payment_terms', 'contacts']); foreach ($this->invoice_items as $invoiceItem) diff --git a/app/ninja/repositories/InvoiceRepository.php b/app/ninja/repositories/InvoiceRepository.php index 5c7a21e768aa..1daaff723189 100755 --- a/app/ninja/repositories/InvoiceRepository.php +++ b/app/ninja/repositories/InvoiceRepository.php @@ -80,7 +80,7 @@ class InvoiceRepository } $invoice->client_id = $data['client_id']; - $invoice->discount = $data['discount']; + $invoice->discount = floatval($data['discount']); $invoice->invoice_number = trim($data['invoice_number']); $invoice->invoice_date = Utils::toSqlDate($data['invoice_date']); $invoice->due_date = Utils::toSqlDate($data['due_date']); @@ -93,30 +93,19 @@ class InvoiceRepository $invoice->public_notes = trim($data['public_notes']); $invoice->po_number = trim($data['po_number']); $invoice->currency_id = $data['currency_id']; + $invoice->tax_rate = 0; - $total = 0; - - foreach ($data['invoice_items'] as $item) + if (isset($data['tax']) && isset($data['tax']->rate) && floatval($data['tax']->rate) > 0) { - if (!isset($item->cost)) - { - $item->cost = 0; - } - - if (!isset($item->qty)) - { - $item->qty = 0; - } - - $total += floatval($item->qty) * floatval($item->cost); + $invoice->tax_rate = floatval($data['tax']->rate); + $invoice->tax_name = trim($data['tax']->name); } - $invoice->amount = $total; - $invoice->balance = $total; $invoice->save(); - $invoice->invoice_items()->forceDelete(); + $total = 0; + foreach ($data['invoice_items'] as $item) { if (!$item->cost && !$item->qty && !$item->product_key && !$item->notes) @@ -149,17 +138,31 @@ class InvoiceRepository $invoiceItem->notes = trim($item->notes); $invoiceItem->cost = floatval($item->cost); $invoiceItem->qty = floatval($item->qty); + $invoiceItem->tax_rate = 0; - if ($item->tax && isset($item->tax->rate) && isset($item->tax->name)) + if ($item->tax && isset($item->tax->rate) && floatval($item->tax->rate) > 0) { $invoiceItem->tax_rate = floatval($item->tax->rate); $invoiceItem->tax_name = trim($item->tax->name); } $invoice->invoice_items()->save($invoiceItem); - $total += floatval($item->qty) * floatval($item->cost); + + $lineTotal = $invoiceItem->cost * $invoiceItem->qty; + $total += $lineTotal + ($lineTotal * $invoiceItem->tax_rate / 100); } + if ($invoice->discount > 0) + { + $total *= (100 - $invoice->discount) / 100; + } + + $total += $total * $invoice->tax_rate / 100; + + $invoice->amount = $total; + $invoice->balance = $total; + $invoice->save(); + return $invoice; } } diff --git a/app/views/error.blade.php b/app/views/error.blade.php new file mode 100755 index 000000000000..c24ac38fed60 --- /dev/null +++ b/app/views/error.blade.php @@ -0,0 +1,7 @@ +@extends('header') + +@section('content') + + {{ $error }} + +@stop \ No newline at end of file diff --git a/app/views/invoices/edit.blade.php b/app/views/invoices/edit.blade.php index e20dcaa13090..06cdd172aaac 100755 --- a/app/views/invoices/edit.blade.php +++ b/app/views/invoices/edit.blade.php @@ -16,7 +16,7 @@ 'email' => 'required', 'product_key' => 'max:14', )); }} - +

@@ -108,59 +108,70 @@ Description Unit Cost Quantity - Tax + Tax Line Total - + - + {{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'key')->onkeyup('onItemChange()') ->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') }} - + - + - + - + - + - +   - - + + - + + Subtotal - + + Discount + + + + Tax + + + - + + Paid to Date - + + Balance Due @@ -319,6 +330,12 @@   + + {{ Former::checkbox('invoice_taxes')->text('Enable specifying an invoice tax') + ->label('Settings')->data_bind('checked: invoice_taxes, enable: tax_rates().length > 1') }} + {{ Former::checkbox('invoice_item_taxes')->text('Enable specifying line item taxes') + ->label(' ')->data_bind('checked: invoice_item_taxes, enable: tax_rates().length > 1') }} +