diff --git a/app/Http/Controllers/ExpenseController.php b/app/Http/Controllers/ExpenseController.php index b7f5bdaaccdd..9630fb5ee18c 100644 --- a/app/Http/Controllers/ExpenseController.php +++ b/app/Http/Controllers/ExpenseController.php @@ -172,17 +172,12 @@ class ExpenseController extends BaseController return Redirect::to('expenses'); } - if ($expense->should_be_invoiced == 0) { - Session::flash('error', trans('texts.expense_error_should_not_be_invoiced')); - return Redirect::to('expenses'); - } - $account = Auth::user()->account; $data[] = [ 'publicId' => $expense->public_id, 'description' => $expense->public_notes, 'qty' => 1, - 'cost' => $expense->amount, + 'cost' => $expense->present()->converted_amount, ]; } diff --git a/app/Models/Expense.php b/app/Models/Expense.php index a4340d9b7674..f1bea2625a98 100644 --- a/app/Models/Expense.php +++ b/app/Models/Expense.php @@ -16,6 +16,9 @@ class Expense extends EntityModel protected $presenter = 'App\Ninja\Presenters\ExpensePresenter'; protected $fillable = [ + 'client_id', + 'vendor_id', + 'currency_id', 'amount', 'foreign_amount', 'exchange_rate', diff --git a/app/Ninja/Presenters/ExpensePresenter.php b/app/Ninja/Presenters/ExpensePresenter.php index 3c7237d39d64..9cede24d039e 100644 --- a/app/Ninja/Presenters/ExpensePresenter.php +++ b/app/Ninja/Presenters/ExpensePresenter.php @@ -15,4 +15,9 @@ class ExpensePresenter extends Presenter { { return Utils::fromSqlDate($this->entity->expense_date); } + + public function converted_amount() + { + return round($this->entity->amount * $this->entity->exchange_rate, 2); + } } \ No newline at end of file diff --git a/app/Ninja/Repositories/ExpenseRepository.php b/app/Ninja/Repositories/ExpenseRepository.php index b8083cb0f157..a4d971d56186 100644 --- a/app/Ninja/Repositories/ExpenseRepository.php +++ b/app/Ninja/Repositories/ExpenseRepository.php @@ -50,7 +50,6 @@ class ExpenseRepository extends BaseRepository ->where('expenses.account_id', '=', $accountid) ->select('expenses.account_id', 'expenses.amount', - 'expenses.converted_amount', 'expenses.currency_id', 'expenses.deleted_at', 'expenses.exchange_rate', @@ -94,48 +93,15 @@ class ExpenseRepository extends BaseRepository // First auto fill $expense->fill($input); - // We can have an expense without a vendor - if (isset($input['vendor_id'])) { - $expense->vendor_id = $input['vendor_id']; - } - $expense->expense_date = Utils::toSqlDate($input['expense_date']); - $expense->amount = Utils::parseFloat($input['amount']); - - if (isset($input['converted_amount'])) { - $expense->converted_amount = Utils::parseFloat($input['converted_amount']); - } - $expense->private_notes = trim($input['private_notes']); $expense->public_notes = trim($input['public_notes']); - - if (isset($input['exchange_rate'])) { - $expense->exchange_rate = Utils::parseFloat($input['exchange_rate']); - } else { - $expense->exchange_rate = 100; - } - - if ($expense->exchange_rate == 0) { - $expense->exchange_rate = 100; - } - - // set the currency - if (isset($input['currency_id'])) { - $expense->currency_id = $input['currency_id']; - } - - if ($expense->currency_id == 0) { - $expense->currency_id = Session::get(SESSION_CURRENCY, DEFAULT_CURRENCY); - } - - // Calculate the amount cur - $expense->converted_amount = ($expense->amount / 100) * $expense->exchange_rate; - $expense->should_be_invoiced = isset($input['should_be_invoiced']) || $expense->client_id ? true : false; - if (isset($input['client_id'])) { - $expense->client_id = $input['client_id']; - } + $rate = isset($input['exchange_rate']) ? Utils::parseFloat($input['exchange_rate']) : 1; + $expense->exchange_rate = round($rate, 4); + $expense->amount = round(Utils::parseFloat($input['amount']), 2); + $expense->save(); return $expense; diff --git a/database/migrations/2016_01_04_175228_create_vendors_table.php b/database/migrations/2016_01_04_175228_create_vendors_table.php index 7c63933c00dd..8bc26c59efd4 100644 --- a/database/migrations/2016_01_04_175228_create_vendors_table.php +++ b/database/migrations/2016_01_04_175228_create_vendors_table.php @@ -75,7 +75,7 @@ class CreateVendorsTable extends Migration $table->boolean('is_deleted')->default(false); $table->decimal('amount', 13, 2); $table->decimal('foreign_amount', 13, 2); - $table->decimal('exchange_rate', 13, 2); + $table->decimal('exchange_rate', 13, 4); $table->date('expense_date')->nullable(); $table->text('private_notes'); $table->text('public_notes'); diff --git a/public/js/built.js b/public/js/built.js index 0fc348bfa966..f6b8bc173938 100644 --- a/public/js/built.js +++ b/public/js/built.js @@ -30260,19 +30260,6 @@ if (window.ko) { } }; - ko.bindingHandlers.fadeVisible = { - init: function(element, valueAccessor) { - // Initially set the element to be instantly visible/hidden depending on the value - var value = valueAccessor(); - $(element).toggle(ko.unwrap(value)); // Use "unwrapObservable" so we can handle values that may or may not be observable - }, - update: function(element, valueAccessor) { - // Whenever the value subsequently changes, slowly fade the element in or out - var value = valueAccessor(); - ko.unwrap(value) ? $(element).fadeIn() : $(element).fadeOut(); - } - }; - ko.bindingHandlers.datePicker = { init: function (element, valueAccessor, allBindingsAccessor) { var value = ko.utils.unwrapObservable(valueAccessor()); @@ -30841,6 +30828,11 @@ function roundToTwo(num, toString) { return toString ? val.toFixed(2) : (val || 0); } +function roundToFour(num, toString) { + var val = +(Math.round(num + "e+4") + "e-4"); + return toString ? val.toFixed(4) : (val || 0); +} + function truncate(str, length) { return (str && str.length > length) ? (str.substr(0, length-1) + '...') : str; } diff --git a/public/js/script.js b/public/js/script.js index 02dbc4b0c462..f1d32879302d 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -950,6 +950,11 @@ function roundToTwo(num, toString) { return toString ? val.toFixed(2) : (val || 0); } +function roundToFour(num, toString) { + var val = +(Math.round(num + "e+4") + "e-4"); + return toString ? val.toFixed(4) : (val || 0); +} + function truncate(str, length) { return (str && str.length > length) ? (str.substr(0, length-1) + '...') : str; } diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index a152021756c4..b2d035a0c4d2 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -1055,7 +1055,6 @@ return array( 'invoice_expense' => 'Invoice Expense', 'expense_error_multiple_clients' =>'The expenses can\'t belong to different clients', 'expense_error_invoiced' => 'Expense have already been invoiced', - 'expense_error_should_not_be_invoiced' => 'Expense maked not to be invoiced', 'convert_currency' => 'Convert currency', // Payment terms diff --git a/resources/views/expenses/edit.blade.php b/resources/views/expenses/edit.blade.php index 2ad3559650b8..6eb092af3670 100644 --- a/resources/views/expenses/edit.blade.php +++ b/resources/views/expenses/edit.blade.php @@ -27,6 +27,7 @@ {!! Former::text('amount') ->label(trans('texts.amount')) + ->data_bind("value: amount, valueUpdate: 'afterkeydown'") ->addGroupClass('amount') ->append($account->present()->currencyCode) !!} @@ -42,10 +43,12 @@ ->data_bind('combobox: client_id') ->addGroupClass('client-select') !!} - {!! Former::checkbox('should_be_invoiced') - ->text(trans('texts.should_be_invoiced')) - ->data_bind('checked: should_be_invoiced() || client_id(), enable: !client_id()') - ->label(' ') !!}
+ @if (!$expense || ($expense && !$expense->invoice_id)) + {!! Former::checkbox('should_be_invoiced') + ->text(trans('texts.should_be_invoiced')) + ->data_bind('checked: should_be_invoiced() || client_id(), enable: !client_id()') + ->label(' ') !!}
+ @endif {!! Former::select('currency_id')->addOption('','') @@ -60,11 +63,11 @@ {!! Former::text('exchange_rate') - ->data_bind('enable: enableExchangeRate') !!} + ->data_bind("value: exchange_rate, enable: enableExchangeRate, valueUpdate: 'afterkeydown'") !!} {!! Former::text('converted_amount') ->addGroupClass('converted-amount') - ->data_bind('enable: enableExchangeRate') + ->data_bind("value: convertedAmount, enable: enableExchangeRate") ->append('') !!} @@ -127,8 +130,15 @@ onClientChange(); }); - window.model = new ViewModel(); - ko.applyBindings(model); + @if ($data) + // this means we failed so we'll reload the previous state + window.model = new ViewModel({!! $data !!}); + @else + // otherwise create blank model + window.model = new ViewModel({!! $expense !!}); + + ko.applyBindings(model); + @endif @if (!$expense && $clientPublicId) onClientChange(); @@ -141,15 +151,30 @@ @endif }); - var ViewModel = function() { + var ViewModel = function(data) { var self = this; self.client_id = ko.observable({{ $clientPublicId }}); self.vendor_id = ko.observable({{ $vendorPublicId }}); - self.currency_id = ko.observable({{ $expense && $expense->currency_id ? $expense->currency_id : null }}); - self.should_be_invoiced = ko.observable({{ $expense && ($expense->should_be_invoiced || $expense->client_id) ? 'true' : 'false' }}); + self.currency_id = ko.observable(); + self.amount = ko.observable(); + self.exchange_rate = ko.observable(1); + self.should_be_invoiced = ko.observable(); self.account_currency_id = ko.observable({{ $account->getCurrencyId() }}); + if (data) { + ko.mapping.fromJS(data, {}, this); + } + + self.convertedAmount = ko.computed({ + read: function () { + return roundToTwo(self.amount() * self.exchange_rate()).toFixed(2); + }, + write: function(value) { + self.exchange_rate(roundToFour(value / self.amount())); + } + }, self); + self.currencyCode = ko.computed(function() { var currencyId = self.currency_id() || self.account_currency_id(); var currency = currencyMap[currencyId]; @@ -159,6 +184,7 @@ self.currencyName = ko.computed(function() { var currencyId = self.currency_id() || self.account_currency_id(); var currency = currencyMap[currencyId]; + console.log(currencyId); return currency.name; });