diff --git a/.env.development.php b/.env.development.php index a3a31df7b4f5..adeed69f24fa 100644 --- a/.env.development.php +++ b/.env.development.php @@ -4,6 +4,6 @@ return array( //'TAG_MANAGER_KEY' => '', //'ANALYTICS_KEY' => '', - 'NINJA_PROD' => true, + //'NINJA_PROD' => true, ); diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index 926b47f0bce6..7c257753e440 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -273,12 +273,16 @@ class AccountController extends \BaseController { if (Auth::user()->account->isPro()) { $account = Auth::user()->account; - $account->custom_label1 = Input::get('custom_label1'); - $account->custom_value1 = Input::get('custom_value1'); - $account->custom_label2 = Input::get('custom_label2'); - $account->custom_value2 = Input::get('custom_value2'); - $account->custom_client_label1 = Input::get('custom_client_label1'); - $account->custom_client_label2 = Input::get('custom_client_label2'); + $account->custom_label1 = trim(Input::get('custom_label1')); + $account->custom_value1 = trim(Input::get('custom_value1')); + $account->custom_label2 = trim(Input::get('custom_label2')); + $account->custom_value2 = trim(Input::get('custom_value2')); + $account->custom_client_label1 = trim(Input::get('custom_client_label1')); + $account->custom_client_label2 = trim(Input::get('custom_client_label2')); + $account->custom_invoice_label1 = trim(Input::get('custom_invoice_label1')); + $account->custom_invoice_label2 = trim(Input::get('custom_invoice_label2')); + $account->custom_invoice_taxes1 = Input::get('custom_invoice_taxes1') ? true : false; + $account->custom_invoice_taxes2 = Input::get('custom_invoice_taxes2') ? true : false; $account->save(); Session::flash('message', trans('texts.updated_settings')); @@ -292,6 +296,8 @@ class AccountController extends \BaseController { if (Auth::user()->account->isPro()) { $account = Auth::user()->account; + $account->hide_quantity = Input::get('hide_quantity') ? true : false; + $account->hide_paid_to_date = Input::get('hide_paid_to_date') ? true : false; $account->primary_color = Input::get('primary_color');// ? Input::get('primary_color') : null; $account->secondary_color = Input::get('secondary_color');// ? Input::get('secondary_color') : null; $account->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 b5a5c31e2443..3ddc66d16b89 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 @@ -244,8 +244,8 @@ class ConfideSetupUsersTable extends Migration { $t->unsignedInteger('country_id')->nullable(); $t->string('work_phone'); $t->text('private_notes'); - $t->decimal('balance', 13, 4); - $t->decimal('paid_to_date', 13, 4); + $t->decimal('balance', 13, 2); + $t->decimal('paid_to_date', 13, 2); $t->timestamp('last_login')->nullable(); $t->string('website'); $t->unsignedInteger('industry_id')->nullable(); @@ -326,10 +326,10 @@ class ConfideSetupUsersTable extends Migration { $t->unsignedInteger('recurring_invoice_id')->index()->nullable(); $t->string('tax_name'); - $t->decimal('tax_rate', 13, 4); + $t->decimal('tax_rate', 13, 2); - $t->decimal('amount', 13, 4); - $t->decimal('balance', 13, 4); + $t->decimal('amount', 13, 2); + $t->decimal('balance', 13, 2); $t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); $t->foreign('account_id')->references('id')->on('accounts'); @@ -375,7 +375,7 @@ class ConfideSetupUsersTable extends Migration { $t->softDeletes(); $t->string('name'); - $t->decimal('rate', 13, 4); + $t->decimal('rate', 13, 2); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');; @@ -394,8 +394,8 @@ class ConfideSetupUsersTable extends Migration { $t->string('product_key'); $t->text('notes'); - $t->decimal('cost', 13, 4); - $t->decimal('qty', 13, 4); + $t->decimal('cost', 13, 2); + $t->decimal('qty', 13, 2); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('user_id')->references('id')->on('users')->onDelete('cascade');; @@ -417,11 +417,11 @@ class ConfideSetupUsersTable extends Migration { $t->string('product_key'); $t->text('notes'); - $t->decimal('cost', 13, 4); - $t->decimal('qty', 13, 4); + $t->decimal('cost', 13, 2); + $t->decimal('qty', 13, 2); $t->string('tax_name'); - $t->decimal('tax_rate', 13, 4); + $t->decimal('tax_rate', 13, 2); $t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); $t->foreign('product_id')->references('id')->on('products'); @@ -446,7 +446,7 @@ class ConfideSetupUsersTable extends Migration { $t->softDeletes(); $t->boolean('is_deleted'); - $t->decimal('amount', 13, 4); + $t->decimal('amount', 13, 2); $t->date('payment_date'); $t->string('transaction_reference'); $t->string('payer_id'); @@ -473,8 +473,8 @@ class ConfideSetupUsersTable extends Migration { $t->softDeletes(); $t->boolean('is_deleted'); - $t->decimal('amount', 13, 4); - $t->decimal('balance', 13, 4); + $t->decimal('amount', 13, 2); + $t->decimal('balance', 13, 2); $t->date('credit_date')->nullable(); $t->string('credit_number'); $t->text('private_notes'); @@ -504,8 +504,8 @@ class ConfideSetupUsersTable extends Migration { $t->text('message'); $t->text('json_backup'); $t->integer('activity_type_id'); - $t->decimal('adjustment', 13, 4); - $t->decimal('balance', 13, 4); + $t->decimal('adjustment', 13, 2); + $t->decimal('balance', 13, 2); $t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade'); $t->foreign('client_id')->references('id')->on('clients')->onDelete('cascade'); diff --git a/app/database/migrations/2014_07_17_205900_support_hiding_quantity.php b/app/database/migrations/2014_07_17_205900_support_hiding_quantity.php new file mode 100644 index 000000000000..d055e4e908cb --- /dev/null +++ b/app/database/migrations/2014_07_17_205900_support_hiding_quantity.php @@ -0,0 +1,66 @@ +boolean('hide_quantity'); + $table->boolean('hide_paid_to_date'); + + $table->string('custom_invoice_label1'); + $table->string('custom_invoice_label2'); + + $table->boolean('custom_invoice_taxes1'); + $table->boolean('custom_invoice_taxes2'); + }); + + Schema::table('invoices', function($table) + { + $table->decimal('custom_value1', 13, 2); + $table->decimal('custom_value2', 13, 2); + + $table->boolean('custom_taxes1'); + $table->boolean('custom_taxes2'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accounts', function($table) + { + $table->dropColumn('hide_quantity'); + $table->dropColumn('hide_paid_to_date'); + + $table->dropColumn('custom_invoice_label1'); + $table->dropColumn('custom_invoice_label2'); + + $table->dropColumn('custom_invoice_taxes1'); + $table->dropColumn('custom_invoice_taxes2'); + }); + + Schema::table('invoices', function($table) + { + $table->dropColumn('custom_value1'); + $table->dropColumn('custom_value2'); + + $table->dropColumn('custom_taxes1'); + $table->dropColumn('custom_taxes2'); + }); + } + +} diff --git a/app/filters.php b/app/filters.php index ec8e64a3d218..0b28abcca26a 100755 --- a/app/filters.php +++ b/app/filters.php @@ -69,13 +69,17 @@ App::after(function($request, $response) Route::filter('auth', function() { - if (Auth::guest()) { - if(Utils::isNinja()) { - return Redirect::guest('/'); - } else { - return Redirect::guest('/login'); - } + if (Auth::guest()) + { + if (Utils::isNinja() || Account::count() == 0) + { + return Redirect::guest('/'); + } + else + { + return Redirect::guest('/login'); } + } }); diff --git a/app/lang/de/texts.php b/app/lang/de/texts.php index 50907c1a0976..2b81c45fb67c 100644 --- a/app/lang/de/texts.php +++ b/app/lang/de/texts.php @@ -45,7 +45,7 @@ return array( 'quantity' => 'Menge', 'line_total' => 'Summe', 'subtotal' => 'Zwischensumme', - 'paid_to_date' => 'Zahlungsdatum', + 'paid_to_date' => 'Bereits gezahlt', 'balance_due' => 'Rechnungsbetrag', 'invoice_design_id' => 'Design', 'terms' => 'Bedingungen', diff --git a/app/lang/en/texts.php b/app/lang/en/texts.php index 2a254a89be30..b6504be860e1 100644 --- a/app/lang/en/texts.php +++ b/app/lang/en/texts.php @@ -397,6 +397,14 @@ return array( 'session_expired' => 'Your session has expired.', + 'invoice_fields' => 'Invoice Fields', + 'invoice_options' => 'Invoice Options', + 'hide_quantity' => 'Hide quantity', + 'hide_quantity_help' => 'All line items will have a quantity of one', + 'hide_paid_to_date' => 'Hide paid to date', + 'hide_paid_to_date_help' => 'Hide until a payment is made', + + 'charge_taxes' => 'Charge taxes', ); diff --git a/app/models/Invoice.php b/app/models/Invoice.php index 29ac65b3a2ec..32a9dd0a7917 100755 --- a/app/models/Invoice.php +++ b/app/models/Invoice.php @@ -82,7 +82,11 @@ class Invoice extends EntityModel 'account', 'invoice_design_id', 'is_pro', - 'is_quote']); + 'is_quote', + 'custom_value1', + 'custom_value2', + 'custom_taxes1', + 'custom_taxes2']); $this->client->setVisible([ 'name', @@ -117,7 +121,9 @@ class Invoice extends EntityModel 'custom_client_label1', 'custom_client_label2', 'primary_color', - 'secondary_color']); + 'secondary_color', + 'hide_quantity', + 'hide_paid_to_date']); foreach ($this->invoice_items as $invoiceItem) { diff --git a/app/ninja/repositories/InvoiceRepository.php b/app/ninja/repositories/InvoiceRepository.php index 1566b7f1c6a4..8dd1b80a7d39 100755 --- a/app/ninja/repositories/InvoiceRepository.php +++ b/app/ninja/repositories/InvoiceRepository.php @@ -237,7 +237,7 @@ class InvoiceRepository foreach ($data['invoice_items'] as $item) { - if (!$item->cost && !$item->qty && !$item->product_key && !$item->notes) + if (!$item->cost && !$item->product_key && !$item->notes) { continue; } @@ -261,9 +261,30 @@ class InvoiceRepository $total *= (100 - $invoice->discount) / 100; } + $invoice->custom_value1 = $data['custom_value1']; + $invoice->custom_value2 = $data['custom_value2']; + $invoice->custom_taxes1 = $data['custom_taxes1'] ? true : false; + $invoice->custom_taxes2 = $data['custom_taxes2'] ? true : false; + + // custom fields charged taxes + if ($invoice->custom_value1 && $invoice->custom_taxes1) { + $total += $invoice->custom_value1; + } + if ($invoice->custom_value2 && $invoice->custom_taxes2) { + $total += $invoice->custom_value2; + } + $total += $total * $invoice->tax_rate / 100; $total = round($total, 2); + // custom fields not charged taxes + if ($invoice->custom_value1 && !$invoice->custom_taxes1) { + $total += $invoice->custom_value1; + } + if ($invoice->custom_value2 && !$invoice->custom_taxes2) { + $total += $invoice->custom_value2; + } + if ($publicId) { $invoice->balance = $total - ($invoice->amount - $invoice->balance); @@ -280,7 +301,7 @@ class InvoiceRepository foreach ($data['invoice_items'] as $item) { - if (!$item->cost && !$item->qty && !$item->product_key && !$item->notes) + if (!$item->cost && !$item->product_key && !$item->notes) { continue; } diff --git a/app/views/accounts/custom_fields.blade.php b/app/views/accounts/custom_fields.blade.php index c791d23e1432..b856a5337995 100644 --- a/app/views/accounts/custom_fields.blade.php +++ b/app/views/accounts/custom_fields.blade.php @@ -6,6 +6,20 @@ {{ Former::open()->addClass('col-md-8 col-md-offset-2 warn-on-exit') }} {{ Former::populate($account) }} + {{ Former::populateField('custom_invoice_taxes1', intval($account->custom_invoice_taxes1)) }} + {{ Former::populateField('custom_invoice_taxes2', intval($account->custom_invoice_taxes2)) }} + + {{ Former::legend('invoice_fields') }} + {{ Former::text('custom_invoice_label1')->label(trans('texts.field_label')) + ->append(Former::checkbox('custom_invoice_taxes1')->raw() . ' ' . trans('texts.charge_taxes')) }} + {{ Former::text('custom_invoice_label2')->label(trans('texts.field_label')) + ->append(Former::checkbox('custom_invoice_taxes2')->raw() . ' ' . trans('texts.charge_taxes')) }} +

 

+ + {{ Former::legend('client_fields') }} + {{ Former::text('custom_client_label1')->label(trans('texts.field_label')) }} + {{ Former::text('custom_client_label2')->label(trans('texts.field_label')) }} +

 

{{ Former::legend('company_fields') }} {{ Former::text('custom_label1')->label(trans('texts.field_label')) }} @@ -14,10 +28,6 @@ {{ Former::text('custom_label2')->label(trans('texts.field_label')) }} {{ Former::text('custom_value2')->label(trans('texts.field_value')) }} - {{ Former::legend('client_fields') }} - {{ Former::text('custom_client_label1')->label(trans('texts.field_label')) }} - {{ Former::text('custom_client_label2')->label(trans('texts.field_label')) }} - @if (Auth::user()->isPro()) {{ Former::actions( Button::lg_success_submit(trans('texts.save'))->append_with_icon('floppy-disk') ) }} @else diff --git a/app/views/accounts/invoice_design.blade.php b/app/views/accounts/invoice_design.blade.php index 8839c3281a23..31c122e59ca4 100644 --- a/app/views/accounts/invoice_design.blade.php +++ b/app/views/accounts/invoice_design.blade.php @@ -6,6 +6,13 @@ {{ Former::open()->addClass('col-md-8 col-md-offset-2 warn-on-exit') }} {{ Former::populate($account) }} + {{ Former::populateField('hide_quantity', intval($account->hide_quantity)) }} + {{ Former::populateField('hide_paid_to_date', intval($account->hide_paid_to_date)) }} + + {{ Former::legend('invoice_options') }} + {{ Former::checkbox('hide_quantity')->text(trans('texts.hide_quantity_help')) }} + {{ Former::checkbox('hide_paid_to_date')->text(trans('texts.hide_paid_to_date_help')) }} +

 

{{ Former::legend('invoice_design') }} {{ Former::text('primary_color') }} diff --git a/app/views/invoices/edit.blade.php b/app/views/invoices/edit.blade.php index fe85616128c2..ad9270a0fed9 100755 --- a/app/views/invoices/edit.blade.php +++ b/app/views/invoices/edit.blade.php @@ -119,7 +119,7 @@ {{ trans('texts.item') }} {{ trans('texts.description') }} {{ trans('texts.unit_cost') }} - {{ trans('texts.quantity') }} + {{ trans('texts.quantity') }} {{ trans('texts.tax') }} {{ trans('texts.line_total') }} @@ -140,7 +140,7 @@ - + @@ -154,10 +154,12 @@ + + - +
{{ Former::textarea('public_notes')->data_bind("value: wrapped_notes, valueUpdate: 'afterkeydown'") ->label(false)->placeholder(trans('texts.note_to_client'))->style('resize: none') }} @@ -169,35 +171,82 @@ - {{ trans('texts.subtotal') }} + {{ trans('texts.subtotal') }} + - {{ trans('texts.discount') }} + {{ trans('texts.discount') }} + + @if (($account->custom_invoice_label1 || ($invoice && floatval($invoice->custom_value1)) != 0) && $account->custom_invoice_taxes1) + + + + {{ $account->custom_invoice_label1 }} + + + @endif + + @if (($account->custom_invoice_label2 || ($invoice && floatval($invoice->custom_value2)) != 0) && $account->custom_invoice_taxes2) + + + + {{ $account->custom_invoice_label2 }} + + + @endif + - {{ trans('texts.tax') }} + @if (!$account->hide_quantity) + {{ trans('texts.tax') }} + @endif + + @if (($account->custom_invoice_label1 || ($invoice && floatval($invoice->custom_value1)) != 0) && !$account->custom_invoice_taxes1) + + + + {{ $account->custom_invoice_label1 }} + + + @endif + + @if (($account->custom_invoice_label2 || ($invoice && floatval($invoice->custom_value2)) != 0) && !$account->custom_invoice_taxes2) + + + + {{ $account->custom_invoice_label2 }} + + + @endif + + @if (!$account->hide_paid_to_date) + + + + {{ trans('texts.paid_to_date') }} + + + @endif + - {{ trans('texts.paid_to_date') }} - - - - - - {{ trans($entityType == ENTITY_INVOICE ? 'texts.balance_due' : 'texts.total') }} + {{ trans($entityType == ENTITY_INVOICE ? 'texts.balance_due' : 'texts.total') }} + + + @@ -1017,6 +1066,11 @@ self.balance = ko.observable(0); self.invoice_design_id = ko.observable({{ $account->invoice_design_id }}); + self.custom_value1 = ko.observable(0); + self.custom_value2 = ko.observable(0); + self.custom_taxes1 = ko.observable(false); + self.custom_taxes2 = ko.observable(false); + self.mapping = { 'client': { create: function(options) { @@ -1037,6 +1091,9 @@ self.addItem = function() { var itemModel = new ItemModel(); + @if ($account->hide_quantity) + itemModel.qty(1); + @endif self.invoice_items.push(itemModel); applyComboboxListeners(); } @@ -1044,6 +1101,8 @@ if (data) { ko.mapping.fromJS(data, self.mapping, self); self.is_recurring(parseInt(data.is_recurring)); + self.is_recurring(parseInt(data.is_recurring) == 1); + self.is_recurring(parseInt(data.is_recurring) == 1); } else { self.addItem(); } @@ -1125,12 +1184,24 @@ }); self.totals.taxAmount = ko.computed(function() { - var total = self.totals.rawSubtotal(); + var total = self.totals.rawSubtotal(); - var discount = parseFloat(self.discount()); - if (discount > 0) { - total = roundToTwo(total * ((100 - discount)/100)); - } + var discount = parseFloat(self.discount()); + if (discount > 0) { + total = roundToTwo(total * ((100 - discount)/100)); + } + + var customValue1 = roundToTwo(self.custom_value1()); + var customValue2 = roundToTwo(self.custom_value2()); + var customTaxes1 = self.custom_taxes1() == 1; + var customTaxes2 = self.custom_taxes2() == 1; + + if (customValue1 && customTaxes1) { + total = NINJA.parseFloat(total) + customValue1; + } + if (customValue2 && customTaxes2) { + total = NINJA.parseFloat(total) + customValue2; + } var taxRate = parseFloat(self.tax_rate()); if (taxRate > 0) { @@ -1158,11 +1229,30 @@ total = roundToTwo(total * ((100 - discount)/100)); } + var customValue1 = roundToTwo(self.custom_value1()); + var customValue2 = roundToTwo(self.custom_value2()); + var customTaxes1 = self.custom_taxes1() == 1; + var customTaxes2 = self.custom_taxes2() == 1; + + if (customValue1 && customTaxes1) { + total = NINJA.parseFloat(total) + customValue1; + } + if (customValue2 && customTaxes2) { + total = NINJA.parseFloat(total) + customValue2; + } + var taxRate = parseFloat(self.tax_rate()); if (taxRate > 0) { total = NINJA.parseFloat(total) + roundToTwo((total * (taxRate/100))); } + if (customValue1 && !customTaxes1) { + total = NINJA.parseFloat(total) + customValue1; + } + if (customValue2 && !customTaxes2) { + total = NINJA.parseFloat(total) + customValue2; + } + var paid = self.totals.rawPaidToDate(); if (paid > 0) { total -= paid; @@ -1428,7 +1518,7 @@ } this.isEmpty = function() { - return !self.product_key() && !self.notes() && !self.cost() && !self.qty(); + return !self.product_key() && !self.notes() && !self.cost() && (!self.qty() || {{ $account->hide_quantity ? 'true' : 'false' }}); } this.onSelect = function(){ @@ -1508,6 +1598,9 @@ } model.invoice().addItem(); //model.addTaxRate(); + @else + model.invoice().custom_taxes1({{ $account->custom_invoice_taxes1 ? 'true' : 'false' }}); + model.invoice().custom_taxes2({{ $account->custom_invoice_taxes2 ? 'true' : 'false' }}); @endif // Add the first tax rate for new invoices //if(model.invoice_taxes() && model.tax_rates().length > 0) { @@ -1524,7 +1617,10 @@ } onTaxRateChange(); + // display blank instead of '0' if (!model.invoice().discount()) model.invoice().discount(''); + if (!model.invoice().custom_value1()) model.invoice().custom_value1(''); + if (!model.invoice().custom_value2()) model.invoice().custom_value2(''); ko.applyBindings(model); onItemChange(); diff --git a/public/built.css b/public/built.css index e2c2b89ee4b6..7be4d1223df2 100644 --- a/public/built.css +++ b/public/built.css @@ -2269,6 +2269,12 @@ border-bottom-width: 1px; .dashboard .table-striped>tbody>tr>td:first-child { padding-left: 15px; } .dashboard .table-striped>thead>tr>th:first-child { padding-left: 15px; } + +.invoice-table tfoot input { + text-align: right; +} + + /*********************************************** New/edit invoice page ************************************************/ diff --git a/public/built.js b/public/built.js index 63ad06573b34..27f2c933a153 100644 --- a/public/built.js +++ b/public/built.js @@ -47256,14 +47256,32 @@ function displaySubtotals(doc, layout, invoice, y, rightAlignTitleX) return; } - //var taxTitle = 'Tax ' + getInvoiceTaxRate(invoice) + '%'; var data = [ {'subtotal': formatMoney(invoice.subtotal_amount, invoice.client.currency_id)}, - {'discount': invoice.discount_amount > 0 ? formatMoney(invoice.discount_amount, invoice.client.currency_id) : false}, - {'tax': invoice.tax_amount > 0 ? formatMoney(invoice.tax_amount, invoice.client.currency_id) : false}, - {'paid_to_date': formatMoney(invoice.amount - invoice.balance, invoice.client.currency_id)} + {'discount': invoice.discount_amount > 0 ? formatMoney(invoice.discount_amount, invoice.client.currency_id) : false} ]; + if (NINJA.parseFloat(invoice.custom_value1) && NINJA.parseFloat(invoice.custom_taxes1)) { + data.push({'custom_invoice_label1': formatMoney(invoice.custom_value1, invoice.client.currency_id) }) + } + if (NINJA.parseFloat(invoice.custom_value2) && NINJA.parseFloat(invoice.custom_taxes2)) { + data.push({'custom_invoice_label2': formatMoney(invoice.custom_value2, invoice.client.currency_id) }) + } + + data.push({'tax': invoice.tax_amount > 0 ? formatMoney(invoice.tax_amount, invoice.client.currency_id) : false}); + + if (NINJA.parseFloat(invoice.custom_value1) && !NINJA.parseFloat(invoice.custom_taxes1)) { + data.push({'custom_invoice_label1': formatMoney(invoice.custom_value1, invoice.client.currency_id) }) + } + if (NINJA.parseFloat(invoice.custom_value2) && !NINJA.parseFloat(invoice.custom_taxes2)) { + data.push({'custom_invoice_label2': formatMoney(invoice.custom_value2, invoice.client.currency_id) }) + } + + var paid = invoice.amount - invoice.balance; + if (invoice.account.hide_paid_to_date === '0' || paid) { + data.push({'paid_to_date': formatMoney(paid, invoice.client.currency_id)}); + } + return displayGrid(doc, invoice, data, 300, y, layout, true, 550, rightAlignTitleX) + 10; } @@ -47410,11 +47428,18 @@ function calculateAmounts(invoice) { invoice.subtotal_amount = total; if (invoice.discount > 0) { - var discount = roundToTwo(total * (invoice.discount/100)); total -= discount; } + // custom fields with taxes + if (NINJA.parseFloat(invoice.custom_value1) && NINJA.parseFloat(invoice.custom_taxes1)) { + total += roundToTwo(invoice.custom_value1); + } + if (NINJA.parseFloat(invoice.custom_value2) && NINJA.parseFloat(invoice.custom_taxes2)) { + total += roundToTwo(invoice.custom_value2); + } + var tax = 0; if (invoice.tax && parseFloat(invoice.tax.rate)) { tax = parseFloat(invoice.tax.rate); @@ -47427,9 +47452,17 @@ function calculateAmounts(invoice) { total = parseFloat(total) + parseFloat(tax); } + // custom fields w/o with taxes + if (NINJA.parseFloat(invoice.custom_value1) && !NINJA.parseFloat(invoice.custom_taxes1)) { + total += roundToTwo(invoice.custom_value1); + } + if (NINJA.parseFloat(invoice.custom_value2) && !NINJA.parseFloat(invoice.custom_taxes2)) { + total += roundToTwo(invoice.custom_value2); + } + invoice.balance_amount = roundToTwo(total) - (roundToTwo(invoice.amount) - roundToTwo(invoice.balance)); - invoice.tax_amount = tax; invoice.discount_amount = discount; + invoice.tax_amount = tax; invoice.has_taxes = hasTaxes; return invoice; @@ -47455,7 +47488,9 @@ function displayInvoiceHeader(doc, invoice, layout) { doc.text(layout.marginLeft, layout.tableTop, invoiceLabels.item); doc.text(layout.descriptionLeft, layout.tableTop, invoiceLabels.description); doc.text(costX, layout.tableTop, invoiceLabels.unit_cost); - doc.text(qtyX, layout.tableTop, invoiceLabels.quantity); + if (invoice.account.hide_quantity === '0') { + doc.text(qtyX, layout.tableTop, invoiceLabels.quantity); + } doc.text(totalX, layout.tableTop, invoiceLabels.line_total); if (invoice.has_taxes) @@ -47470,8 +47505,9 @@ function displayInvoiceItems(doc, invoice, layout) { var line = 1; var total = 0; var shownItem = false; - var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1; + var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1; var tableTop = layout.tableTop; + var hideQuantity = invoice.account.hide_quantity === '1'; doc.setFontSize(8); for (var i=0; itbody>tr>td:first-child { padding-left: 15px; } .dashboard .table-striped>thead>tr>th:first-child { padding-left: 15px; } + +.invoice-table tfoot input { + text-align: right; +} + + /*********************************************** New/edit invoice page ************************************************/ diff --git a/public/js/script.js b/public/js/script.js index 39e39bb472d3..f4e5b3a7deed 100644 --- a/public/js/script.js +++ b/public/js/script.js @@ -1331,14 +1331,32 @@ function displaySubtotals(doc, layout, invoice, y, rightAlignTitleX) return; } - //var taxTitle = 'Tax ' + getInvoiceTaxRate(invoice) + '%'; var data = [ {'subtotal': formatMoney(invoice.subtotal_amount, invoice.client.currency_id)}, - {'discount': invoice.discount_amount > 0 ? formatMoney(invoice.discount_amount, invoice.client.currency_id) : false}, - {'tax': invoice.tax_amount > 0 ? formatMoney(invoice.tax_amount, invoice.client.currency_id) : false}, - {'paid_to_date': formatMoney(invoice.amount - invoice.balance, invoice.client.currency_id)} + {'discount': invoice.discount_amount > 0 ? formatMoney(invoice.discount_amount, invoice.client.currency_id) : false} ]; + if (NINJA.parseFloat(invoice.custom_value1) && NINJA.parseFloat(invoice.custom_taxes1)) { + data.push({'custom_invoice_label1': formatMoney(invoice.custom_value1, invoice.client.currency_id) }) + } + if (NINJA.parseFloat(invoice.custom_value2) && NINJA.parseFloat(invoice.custom_taxes2)) { + data.push({'custom_invoice_label2': formatMoney(invoice.custom_value2, invoice.client.currency_id) }) + } + + data.push({'tax': invoice.tax_amount > 0 ? formatMoney(invoice.tax_amount, invoice.client.currency_id) : false}); + + if (NINJA.parseFloat(invoice.custom_value1) && !NINJA.parseFloat(invoice.custom_taxes1)) { + data.push({'custom_invoice_label1': formatMoney(invoice.custom_value1, invoice.client.currency_id) }) + } + if (NINJA.parseFloat(invoice.custom_value2) && !NINJA.parseFloat(invoice.custom_taxes2)) { + data.push({'custom_invoice_label2': formatMoney(invoice.custom_value2, invoice.client.currency_id) }) + } + + var paid = invoice.amount - invoice.balance; + if (invoice.account.hide_paid_to_date === '0' || paid) { + data.push({'paid_to_date': formatMoney(paid, invoice.client.currency_id)}); + } + return displayGrid(doc, invoice, data, 300, y, layout, true, 550, rightAlignTitleX) + 10; } @@ -1485,11 +1503,18 @@ function calculateAmounts(invoice) { invoice.subtotal_amount = total; if (invoice.discount > 0) { - var discount = roundToTwo(total * (invoice.discount/100)); total -= discount; } + // custom fields with taxes + if (NINJA.parseFloat(invoice.custom_value1) && NINJA.parseFloat(invoice.custom_taxes1)) { + total += roundToTwo(invoice.custom_value1); + } + if (NINJA.parseFloat(invoice.custom_value2) && NINJA.parseFloat(invoice.custom_taxes2)) { + total += roundToTwo(invoice.custom_value2); + } + var tax = 0; if (invoice.tax && parseFloat(invoice.tax.rate)) { tax = parseFloat(invoice.tax.rate); @@ -1502,9 +1527,17 @@ function calculateAmounts(invoice) { total = parseFloat(total) + parseFloat(tax); } + // custom fields w/o with taxes + if (NINJA.parseFloat(invoice.custom_value1) && !NINJA.parseFloat(invoice.custom_taxes1)) { + total += roundToTwo(invoice.custom_value1); + } + if (NINJA.parseFloat(invoice.custom_value2) && !NINJA.parseFloat(invoice.custom_taxes2)) { + total += roundToTwo(invoice.custom_value2); + } + invoice.balance_amount = roundToTwo(total) - (roundToTwo(invoice.amount) - roundToTwo(invoice.balance)); - invoice.tax_amount = tax; invoice.discount_amount = discount; + invoice.tax_amount = tax; invoice.has_taxes = hasTaxes; return invoice; @@ -1530,7 +1563,9 @@ function displayInvoiceHeader(doc, invoice, layout) { doc.text(layout.marginLeft, layout.tableTop, invoiceLabels.item); doc.text(layout.descriptionLeft, layout.tableTop, invoiceLabels.description); doc.text(costX, layout.tableTop, invoiceLabels.unit_cost); - doc.text(qtyX, layout.tableTop, invoiceLabels.quantity); + if (invoice.account.hide_quantity === '0') { + doc.text(qtyX, layout.tableTop, invoiceLabels.quantity); + } doc.text(totalX, layout.tableTop, invoiceLabels.line_total); if (invoice.has_taxes) @@ -1545,8 +1580,9 @@ function displayInvoiceItems(doc, invoice, layout) { var line = 1; var total = 0; var shownItem = false; - var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1; + var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1; var tableTop = layout.tableTop; + var hideQuantity = invoice.account.hide_quantity === '1'; doc.setFontSize(8); for (var i=0; i