Moved line item tax amounts to invoice subtotals section

This commit is contained in:
Hillel Coren 2015-08-12 22:16:02 +03:00
parent 8afd68fe23
commit dc8bd36e76
29 changed files with 278 additions and 186 deletions

View File

@ -110,7 +110,8 @@ class AccountController extends BaseController
Auth::login($user, true); Auth::login($user, true);
Event::fire(new UserLoggedIn()); Event::fire(new UserLoggedIn());
return Redirect::to('invoices/create')->with('sign_up', Input::get('sign_up')); $redirectTo = Input::get('redirect_to', 'invoices/create');
return Redirect::to($redirectTo)->with('sign_up', Input::get('sign_up'));
} }
public function enableProPlan() public function enableProPlan()
@ -235,7 +236,7 @@ class AccountController extends BaseController
$data['invoice'] = $invoice; $data['invoice'] = $invoice;
$data['invoiceLabels'] = json_decode($account->invoice_labels) ?: []; $data['invoiceLabels'] = json_decode($account->invoice_labels) ?: [];
$data['title'] = trans('texts.invoice_design'); $data['title'] = trans('texts.invoice_design');
$data['invoiceDesigns'] = InvoiceDesign::getDesigns($subSection == ACCOUNT_CUSTOMIZE_DESIGN); $data['invoiceDesigns'] = InvoiceDesign::getDesigns();
$design = false; $design = false;
foreach ($data['invoiceDesigns'] as $item) { foreach ($data['invoiceDesigns'] as $item) {
@ -301,11 +302,6 @@ class AccountController extends BaseController
$account = Auth::user()->account; $account = Auth::user()->account;
$account->custom_design = Input::get('custom_design'); $account->custom_design = Input::get('custom_design');
$account->invoice_design_id = CUSTOM_DESIGN; $account->invoice_design_id = CUSTOM_DESIGN;
if (!$account->utf8_invoices) {
$account->utf8_invoices = true;
}
$account->save(); $account->save();
Session::flash('message', trans('texts.updated_settings')); Session::flash('message', trans('texts.updated_settings'));
@ -365,7 +361,6 @@ class AccountController extends BaseController
$account->share_counter = Input::get('share_counter') ? true : false; $account->share_counter = Input::get('share_counter') ? true : false;
$account->pdf_email_attachment = Input::get('pdf_email_attachment') ? true : false; $account->pdf_email_attachment = Input::get('pdf_email_attachment') ? true : false;
$account->utf8_invoices = Input::get('utf8_invoices') ? true : false;
$account->auto_wrap = Input::get('auto_wrap') ? true : false; $account->auto_wrap = Input::get('auto_wrap') ? true : false;
if (!$account->share_counter) { if (!$account->share_counter) {
@ -706,9 +701,9 @@ class AccountController extends BaseController
$image = Image::make($path); $image = Image::make($path);
$mimeType = $file->getMimeType(); $mimeType = $file->getMimeType();
if ($mimeType == 'image/jpeg' && $account->utf8_invoices) { if ($mimeType == 'image/jpeg') {
$file->move('logo/', $account->account_key . '.jpg'); $file->move('logo/', $account->account_key . '.jpg');
} else if ($mimeType == 'image/png' && $account->utf8_invoices) { } else if ($mimeType == 'image/png') {
$file->move('logo/', $account->account_key . '.png'); $file->move('logo/', $account->account_key . '.png');
} else { } else {
$image->resize(200, 120, function ($constraint) { $image->resize(200, 120, function ($constraint) {

View File

@ -50,7 +50,8 @@ class HomeController extends BaseController
} }
if (Auth::check()) { if (Auth::check()) {
return Redirect::to('invoices/create')->with('sign_up', Input::get('sign_up')); $redirectTo = Input::get('redirect_to', 'invoices/create');
return Redirect::to($redirectTo)->with('sign_up', Input::get('sign_up'));
} else { } else {
return View::make('public.header', ['invoiceNow' => true]); return View::make('public.header', ['invoiceNow' => true]);
} }

View File

@ -214,7 +214,7 @@ class InvoiceController extends BaseController
if ($invoice->invoice_design_id == CUSTOM_DESIGN) { if ($invoice->invoice_design_id == CUSTOM_DESIGN) {
$invoice->invoice_design->javascript = $account->custom_design; $invoice->invoice_design->javascript = $account->custom_design;
} elseif ($account->utf8_invoices) { } else {
$invoice->invoice_design->javascript = $invoice->invoice_design->pdfmake; $invoice->invoice_design->javascript = $invoice->invoice_design->pdfmake;
} }

View File

@ -12,10 +12,12 @@ class Account extends Eloquent
use SoftDeletes; use SoftDeletes;
protected $dates = ['deleted_at']; protected $dates = ['deleted_at'];
/*
protected $casts = [ protected $casts = [
'utf8_invoice' => 'boolean', 'hide_quantity' => 'boolean',
]; ];
*/
public function users() public function users()
{ {
return $this->hasMany('App\Models\User'); return $this->hasMany('App\Models\User');
@ -153,7 +155,7 @@ class Account extends Eloquent
{ {
$fileName = 'logo/' . $this->account_key; $fileName = 'logo/' . $this->account_key;
return file_exists($fileName.'.png') && $this->utf8_invoices ? $fileName.'.png' : $fileName.'.jpg'; return file_exists($fileName.'.png') ? $fileName.'.png' : $fileName.'.jpg';
} }
public function getLogoWidth() public function getLogoWidth()
@ -427,11 +429,4 @@ class Account extends Eloquent
{ {
return $this->token_billing_type_id == TOKEN_BILLING_OPT_OUT; return $this->token_billing_type_id == TOKEN_BILLING_OPT_OUT;
} }
} }
Account::updating(function ($account) {
// Lithuanian requires UTF8 support
if (!Utils::isPro() && $account->language_id == 13) {
$account->utf8_invoices = true;
}
});

View File

@ -9,24 +9,21 @@ class InvoiceDesign extends Eloquent
{ {
public $timestamps = false; public $timestamps = false;
public static function getDesigns($forceUtf8 = false) public static function getDesigns()
{ {
$account = Auth::user()->account; $account = Auth::user()->account;
$designs = Cache::get('invoiceDesigns'); $designs = Cache::get('invoiceDesigns');
$utf8 = $forceUtf8 || $account->utf8_invoices;
foreach ($designs as $design) { foreach ($designs as $design) {
if ($design->id > Auth::user()->maxInvoiceDesignId()) { if ($design->id > Auth::user()->maxInvoiceDesignId()) {
$designs->pull($design->id); $designs->pull($design->id);
} }
if ($utf8) { $design->javascript = $design->pdfmake;
$design->javascript = $design->pdfmake;
}
$design->pdfmake = null; $design->pdfmake = null;
if ($design->id == CUSTOM_DESIGN) { if ($design->id == CUSTOM_DESIGN) {
if ($utf8 && $account->custom_design) { if ($account->custom_design) {
$design->javascript = $account->custom_design; $design->javascript = $account->custom_design;
} else { } else {
$designs->pop(); $designs->pop();

View File

@ -315,6 +315,7 @@ class InvoiceRepository
} }
$total = 0; $total = 0;
$itemTax = 0;
foreach ($data['invoice_items'] as $item) { foreach ($data['invoice_items'] as $item) {
$item = (array) $item; $item = (array) $item;
@ -324,15 +325,29 @@ class InvoiceRepository
$invoiceItemCost = round(Utils::parseFloat($item['cost']), 2); $invoiceItemCost = round(Utils::parseFloat($item['cost']), 2);
$invoiceItemQty = round(Utils::parseFloat($item['qty']), 2); $invoiceItemQty = round(Utils::parseFloat($item['qty']), 2);
$invoiceItemTaxRate = 0;
if (isset($item['tax_rate']) && Utils::parseFloat($item['tax_rate']) > 0) {
$invoiceItemTaxRate = Utils::parseFloat($item['tax_rate']);
}
$lineTotal = $invoiceItemCost * $invoiceItemQty; $lineTotal = $invoiceItemCost * $invoiceItemQty;
$total += round($lineTotal, 2);
}
$total += round($lineTotal + ($lineTotal * $invoiceItemTaxRate / 100), 2); foreach ($data['invoice_items'] as $item) {
$item = (array) $item;
if (isset($item['tax_rate']) && Utils::parseFloat($item['tax_rate']) > 0) {
$invoiceItemCost = round(Utils::parseFloat($item['cost']), 2);
$invoiceItemQty = round(Utils::parseFloat($item['qty']), 2);
$invoiceItemTaxRate = Utils::parseFloat($item['tax_rate']);
$lineTotal = $invoiceItemCost * $invoiceItemQty;
if ($invoice->discount > 0) {
if ($invoice->is_amount_discount) {
$lineTotal -= round(($lineTotal/$total) * $invoice->discount, 2);
} else {
$lineTotal -= round($lineTotal * ($invoice->discount/100), 2);
}
}
$itemTax += round($lineTotal * $invoiceItemTaxRate / 100, 2);
}
} }
if ($invoice->discount > 0) { if ($invoice->discount > 0) {
@ -358,6 +373,7 @@ class InvoiceRepository
$total += $total * $invoice->tax_rate / 100; $total += $total * $invoice->tax_rate / 100;
$total = round($total, 2); $total = round($total, 2);
$total += $itemTax;
// custom fields not charged taxes // custom fields not charged taxes
if ($invoice->custom_value1 && !$invoice->custom_taxes1) { if ($invoice->custom_value1 && !$invoice->custom_taxes1) {

View File

@ -30799,22 +30799,49 @@ function displayNotesAndTerms(doc, layout, invoice, y)
function calculateAmounts(invoice) { function calculateAmounts(invoice) {
var total = 0; var total = 0;
var hasTaxes = false; var hasTaxes = false;
var taxes = {};
// sum line item
for (var i=0; i<invoice.invoice_items.length; i++) {
var item = invoice.invoice_items[i];
var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty));
if (lineTotal) {
total += lineTotal;
}
}
for (var i=0; i<invoice.invoice_items.length; i++) { for (var i=0; i<invoice.invoice_items.length; i++) {
var item = invoice.invoice_items[i]; var item = invoice.invoice_items[i];
var tax = 0; var taxRate = 0;
var taxName = '';
// the object structure differs if it's read from the db or created by knockoutJS
if (item.tax && parseFloat(item.tax.rate)) { if (item.tax && parseFloat(item.tax.rate)) {
tax = parseFloat(item.tax.rate); taxRate = parseFloat(item.tax.rate);
taxName = item.tax.name;
} else if (item.tax_rate && parseFloat(item.tax_rate)) { } else if (item.tax_rate && parseFloat(item.tax_rate)) {
tax = parseFloat(item.tax_rate); taxRate = parseFloat(item.tax_rate);
taxName = item.tax_name;
} }
// calculate line item tax
var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty)); var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty));
if (tax) { if (invoice.discount != 0) {
lineTotal += roundToTwo(lineTotal * tax / 100); if (parseInt(invoice.is_amount_discount)) {
lineTotal -= roundToTwo((lineTotal/total) * invoice.discount);
} else {
lineTotal -= roundToTwo(lineTotal * (invoice.discount/100));
}
} }
if (lineTotal) { var taxAmount = roundToTwo(lineTotal * taxRate / 100);
total += lineTotal;
if (taxRate) {
var key = taxName + taxRate;
if (taxes.hasOwnProperty(key)) {
taxes[key].amount += taxAmount;
} else {
taxes[key] = {name: taxName, rate:taxRate, amount:taxAmount};
}
} }
if ((item.tax && item.tax.name) || item.tax_name) { if ((item.tax && item.tax.name) || item.tax_name) {
@ -30854,6 +30881,12 @@ function calculateAmounts(invoice) {
total = parseFloat(total) + parseFloat(tax); total = parseFloat(total) + parseFloat(tax);
} }
for (var key in taxes) {
if (taxes.hasOwnProperty(key)) {
total += taxes[key].amount;
}
}
// custom fields w/o with taxes // custom fields w/o with taxes
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') { if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') {
total += roundToTwo(invoice.custom_value1); total += roundToTwo(invoice.custom_value1);
@ -30865,6 +30898,7 @@ function calculateAmounts(invoice) {
invoice.total_amount = roundToTwo(total) - (roundToTwo(invoice.amount) - roundToTwo(invoice.balance)); invoice.total_amount = roundToTwo(total) - (roundToTwo(invoice.amount) - roundToTwo(invoice.balance));
invoice.discount_amount = discount; invoice.discount_amount = discount;
invoice.tax_amount = tax; invoice.tax_amount = tax;
invoice.item_taxes = taxes;
invoice.has_taxes = hasTaxes; invoice.has_taxes = hasTaxes;
if (NINJA.parseFloat(invoice.partial)) { if (NINJA.parseFloat(invoice.partial)) {
@ -31655,30 +31689,31 @@ NINJA.notesAndTerms = function(invoice)
NINJA.invoiceColumns = function(invoice) NINJA.invoiceColumns = function(invoice)
{ {
if (invoice.has_taxes) { if (invoice.account.hide_quantity == '1') {
return ["15%", "*", "auto", "auto", "auto", "15%"]; return ["15%", "*", "auto", "15%"];
} else { } else {
return ["15%", "*", "auto", "auto", "15%"] return ["15%", "*", "auto", "auto", "15%"];
} }
} }
NINJA.invoiceLines = function(invoice) { NINJA.invoiceLines = function(invoice) {
var grid = [
[
{text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']},
{text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']},
{text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']},
{text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']},
{text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']},
{text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']}
]
];
var total = 0; var total = 0;
var shownItem = false; var shownItem = false;
var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1; var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1;
var hideQuantity = invoice.account.hide_quantity == '1'; var hideQuantity = invoice.account.hide_quantity == '1';
var grid = [[
{text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']},
{text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']},
{text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}
]];
if (!hideQuantity) {
grid[0].push({text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']});
}
grid[0].push({text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']});
for (var i = 0; i < invoice.invoice_items.length; i++) { for (var i = 0; i < invoice.invoice_items.length; i++) {
var row = []; var row = [];
@ -31687,13 +31722,6 @@ NINJA.invoiceLines = function(invoice) {
var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : ''; var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : '';
var notes = item.notes; var notes = item.notes;
var productKey = item.product_key; var productKey = item.product_key;
var tax = '';
if (item.tax && parseFloat(item.tax.rate)) {
tax = parseFloat(item.tax.rate);
} else if (item.tax_rate && parseFloat(item.tax_rate)) {
tax = parseFloat(item.tax_rate);
}
// show at most one blank line // show at most one blank line
if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) { if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) {
@ -31709,12 +31737,6 @@ NINJA.invoiceLines = function(invoice) {
} }
var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty)); var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty));
if (tax) {
lineTotal += lineTotal * tax / 100;
}
if (lineTotal) {
total += lineTotal;
}
lineTotal = formatMoney(lineTotal, currencyId); lineTotal = formatMoney(lineTotal, currencyId);
rowStyle = (i % 2 == 0) ? 'odd' : 'even'; rowStyle = (i % 2 == 0) ? 'odd' : 'even';
@ -31722,12 +31744,9 @@ NINJA.invoiceLines = function(invoice) {
row.push({style:["productKey", rowStyle], text:productKey || ' '}); // product key can be blank when selecting from a datalist row.push({style:["productKey", rowStyle], text:productKey || ' '}); // product key can be blank when selecting from a datalist
row.push({style:["notes", rowStyle], text:notes || ' '}); row.push({style:["notes", rowStyle], text:notes || ' '});
row.push({style:["cost", rowStyle], text:cost}); row.push({style:["cost", rowStyle], text:cost});
row.push({style:["quantity", rowStyle], text:qty || ' '}); if (!hideQuantity) {
row.push({style:["quantity", rowStyle], text:qty || ' '});
if (invoice.has_taxes) {
row.push({style:["tax", rowStyle], text: tax+'' || ''});
} }
row.push({style:["lineTotal", rowStyle], text:lineTotal || ' '}); row.push({style:["lineTotal", rowStyle], text:lineTotal || ' '});
grid.push(row); grid.push(row);
@ -31757,11 +31776,19 @@ NINJA.subtotals = function(invoice, hideBalance)
data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]);
} }
for (var key in invoice.item_taxes) {
if (invoice.item_taxes.hasOwnProperty(key)) {
var taxRate = invoice.item_taxes[key];
var taxStr = taxRate.name + ' ' + (taxRate.rate*1).toString() + '%';
data.push([{text: taxStr}, {text: formatMoney(taxRate.amount, invoice.client.currency_id)}]);
}
}
if (invoice.tax && invoice.tax.name || invoice.tax_name) { if (invoice.tax && invoice.tax.name || invoice.tax_name) {
var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%'; var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%';
data.push([{text: taxStr}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]); data.push([{text: taxStr}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]);
} }
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') { if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') {
data.push([{text: account.custom_invoice_label1}, {text: formatMoney(invoice.custom_value1, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label1}, {text: formatMoney(invoice.custom_value1, invoice.client.currency_id)}]);
} }

View File

@ -181,30 +181,31 @@ NINJA.notesAndTerms = function(invoice)
NINJA.invoiceColumns = function(invoice) NINJA.invoiceColumns = function(invoice)
{ {
if (invoice.has_taxes) { if (invoice.account.hide_quantity == '1') {
return ["15%", "*", "auto", "auto", "auto", "15%"]; return ["15%", "*", "auto", "15%"];
} else { } else {
return ["15%", "*", "auto", "auto", "15%"] return ["15%", "*", "auto", "auto", "15%"];
} }
} }
NINJA.invoiceLines = function(invoice) { NINJA.invoiceLines = function(invoice) {
var grid = [
[
{text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']},
{text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']},
{text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']},
{text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']},
{text: invoice.has_taxes ? invoiceLabels.tax : '', style: ['tableHeader', 'taxTableHeader']},
{text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']}
]
];
var total = 0; var total = 0;
var shownItem = false; var shownItem = false;
var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1; var currencyId = invoice && invoice.client ? invoice.client.currency_id : 1;
var hideQuantity = invoice.account.hide_quantity == '1'; var hideQuantity = invoice.account.hide_quantity == '1';
var grid = [[
{text: invoiceLabels.item, style: ['tableHeader', 'itemTableHeader']},
{text: invoiceLabels.description, style: ['tableHeader', 'descriptionTableHeader']},
{text: invoiceLabels.unit_cost, style: ['tableHeader', 'costTableHeader']}
]];
if (!hideQuantity) {
grid[0].push({text: invoiceLabels.quantity, style: ['tableHeader', 'qtyTableHeader']});
}
grid[0].push({text: invoiceLabels.line_total, style: ['tableHeader', 'lineTotalTableHeader']});
for (var i = 0; i < invoice.invoice_items.length; i++) { for (var i = 0; i < invoice.invoice_items.length; i++) {
var row = []; var row = [];
@ -213,13 +214,6 @@ NINJA.invoiceLines = function(invoice) {
var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : ''; var qty = NINJA.parseFloat(item.qty) ? roundToTwo(NINJA.parseFloat(item.qty)) + '' : '';
var notes = item.notes; var notes = item.notes;
var productKey = item.product_key; var productKey = item.product_key;
var tax = '';
if (item.tax && parseFloat(item.tax.rate)) {
tax = parseFloat(item.tax.rate);
} else if (item.tax_rate && parseFloat(item.tax_rate)) {
tax = parseFloat(item.tax_rate);
}
// show at most one blank line // show at most one blank line
if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) { if (shownItem && (!cost || cost == '0.00') && !notes && !productKey) {
@ -235,12 +229,6 @@ NINJA.invoiceLines = function(invoice) {
} }
var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty)); var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty));
if (tax) {
lineTotal += lineTotal * tax / 100;
}
if (lineTotal) {
total += lineTotal;
}
lineTotal = formatMoney(lineTotal, currencyId); lineTotal = formatMoney(lineTotal, currencyId);
rowStyle = (i % 2 == 0) ? 'odd' : 'even'; rowStyle = (i % 2 == 0) ? 'odd' : 'even';
@ -248,12 +236,9 @@ NINJA.invoiceLines = function(invoice) {
row.push({style:["productKey", rowStyle], text:productKey || ' '}); // product key can be blank when selecting from a datalist row.push({style:["productKey", rowStyle], text:productKey || ' '}); // product key can be blank when selecting from a datalist
row.push({style:["notes", rowStyle], text:notes || ' '}); row.push({style:["notes", rowStyle], text:notes || ' '});
row.push({style:["cost", rowStyle], text:cost}); row.push({style:["cost", rowStyle], text:cost});
row.push({style:["quantity", rowStyle], text:qty || ' '}); if (!hideQuantity) {
row.push({style:["quantity", rowStyle], text:qty || ' '});
if (invoice.has_taxes) {
row.push({style:["tax", rowStyle], text: tax+'' || ''});
} }
row.push({style:["lineTotal", rowStyle], text:lineTotal || ' '}); row.push({style:["lineTotal", rowStyle], text:lineTotal || ' '});
grid.push(row); grid.push(row);
@ -283,11 +268,19 @@ NINJA.subtotals = function(invoice, hideBalance)
data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label2}, {text: formatMoney(invoice.custom_value2, invoice.client.currency_id)}]);
} }
for (var key in invoice.item_taxes) {
if (invoice.item_taxes.hasOwnProperty(key)) {
var taxRate = invoice.item_taxes[key];
var taxStr = taxRate.name + ' ' + (taxRate.rate*1).toString() + '%';
data.push([{text: taxStr}, {text: formatMoney(taxRate.amount, invoice.client.currency_id)}]);
}
}
if (invoice.tax && invoice.tax.name || invoice.tax_name) { if (invoice.tax && invoice.tax.name || invoice.tax_name) {
var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%'; var taxStr = invoice.tax_name + ' ' + (invoice.tax_rate*1).toString() + '%';
data.push([{text: taxStr}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]); data.push([{text: taxStr}, {text: formatMoney(invoice.tax_amount, invoice.client.currency_id)}]);
} }
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') { if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') {
data.push([{text: account.custom_invoice_label1}, {text: formatMoney(invoice.custom_value1, invoice.client.currency_id)}]); data.push([{text: account.custom_invoice_label1}, {text: formatMoney(invoice.custom_value1, invoice.client.currency_id)}]);
} }

View File

@ -76,12 +76,14 @@ function GetPdf(invoice, javascript){
lineTotalRight: 550 lineTotalRight: 550
}; };
/*
if (invoice.has_taxes) if (invoice.has_taxes)
{ {
layout.descriptionLeft -= 20; layout.descriptionLeft -= 20;
layout.unitCostRight -= 40; layout.unitCostRight -= 40;
layout.qtyRight -= 40; layout.qtyRight -= 40;
} }
*/
/* /*
@param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l") @param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l")
@ -928,22 +930,49 @@ function displayNotesAndTerms(doc, layout, invoice, y)
function calculateAmounts(invoice) { function calculateAmounts(invoice) {
var total = 0; var total = 0;
var hasTaxes = false; var hasTaxes = false;
var taxes = {};
// sum line item
for (var i=0; i<invoice.invoice_items.length; i++) {
var item = invoice.invoice_items[i];
var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty));
if (lineTotal) {
total += lineTotal;
}
}
for (var i=0; i<invoice.invoice_items.length; i++) { for (var i=0; i<invoice.invoice_items.length; i++) {
var item = invoice.invoice_items[i]; var item = invoice.invoice_items[i];
var tax = 0; var taxRate = 0;
var taxName = '';
// the object structure differs if it's read from the db or created by knockoutJS
if (item.tax && parseFloat(item.tax.rate)) { if (item.tax && parseFloat(item.tax.rate)) {
tax = parseFloat(item.tax.rate); taxRate = parseFloat(item.tax.rate);
taxName = item.tax.name;
} else if (item.tax_rate && parseFloat(item.tax_rate)) { } else if (item.tax_rate && parseFloat(item.tax_rate)) {
tax = parseFloat(item.tax_rate); taxRate = parseFloat(item.tax_rate);
taxName = item.tax_name;
} }
// calculate line item tax
var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty)); var lineTotal = roundToTwo(NINJA.parseFloat(item.cost)) * roundToTwo(NINJA.parseFloat(item.qty));
if (tax) { if (invoice.discount != 0) {
lineTotal += roundToTwo(lineTotal * tax / 100); if (parseInt(invoice.is_amount_discount)) {
lineTotal -= roundToTwo((lineTotal/total) * invoice.discount);
} else {
lineTotal -= roundToTwo(lineTotal * (invoice.discount/100));
}
} }
if (lineTotal) { var taxAmount = roundToTwo(lineTotal * taxRate / 100);
total += lineTotal;
if (taxRate) {
var key = taxName + taxRate;
if (taxes.hasOwnProperty(key)) {
taxes[key].amount += taxAmount;
} else {
taxes[key] = {name: taxName, rate:taxRate, amount:taxAmount};
}
} }
if ((item.tax && item.tax.name) || item.tax_name) { if ((item.tax && item.tax.name) || item.tax_name) {
@ -983,6 +1012,12 @@ function calculateAmounts(invoice) {
total = parseFloat(total) + parseFloat(tax); total = parseFloat(total) + parseFloat(tax);
} }
for (var key in taxes) {
if (taxes.hasOwnProperty(key)) {
total += taxes[key].amount;
}
}
// custom fields w/o with taxes // custom fields w/o with taxes
if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') { if (NINJA.parseFloat(invoice.custom_value1) && invoice.custom_taxes1 != '1') {
total += roundToTwo(invoice.custom_value1); total += roundToTwo(invoice.custom_value1);
@ -994,8 +1029,8 @@ function calculateAmounts(invoice) {
invoice.total_amount = roundToTwo(total) - (roundToTwo(invoice.amount) - roundToTwo(invoice.balance)); invoice.total_amount = roundToTwo(total) - (roundToTwo(invoice.amount) - roundToTwo(invoice.balance));
invoice.discount_amount = discount; invoice.discount_amount = discount;
invoice.tax_amount = tax; invoice.tax_amount = tax;
invoice.has_taxes = hasTaxes; invoice.item_taxes = taxes;
if (NINJA.parseFloat(invoice.partial)) { if (NINJA.parseFloat(invoice.partial)) {
invoice.balance_amount = roundToTwo(invoice.partial); invoice.balance_amount = roundToTwo(invoice.partial);
} else { } else {
@ -1039,11 +1074,12 @@ function displayInvoiceHeader(doc, invoice, layout) {
} }
doc.text(totalX, layout.tableTop, invoiceLabels.line_total); doc.text(totalX, layout.tableTop, invoiceLabels.line_total);
/*
if (invoice.has_taxes) if (invoice.has_taxes)
{ {
doc.text(taxX, layout.tableTop, invoiceLabels.tax); doc.text(taxX, layout.tableTop, invoiceLabels.tax);
} }
*/
} }
function displayInvoiceItems(doc, invoice, layout) { function displayInvoiceItems(doc, invoice, layout) {
@ -1226,10 +1262,11 @@ function displayInvoiceItems(doc, invoice, layout) {
doc.line(qtyX-45, y-16,qtyX-45, y+55); doc.line(qtyX-45, y-16,qtyX-45, y+55);
/*
if (invoice.has_taxes) { if (invoice.has_taxes) {
doc.line(taxX-15, y-16,taxX-15, y+55); doc.line(taxX-15, y-16,taxX-15, y+55);
} }
*/
doc.line(totalX-27, y-16,totalX-27, y+55); doc.line(totalX-27, y-16,totalX-27, y+55);
} }
@ -1292,9 +1329,11 @@ function displayInvoiceItems(doc, invoice, layout) {
doc.line(layout.descriptionLeft-8, topX,layout.descriptionLeft-8, y); doc.line(layout.descriptionLeft-8, topX,layout.descriptionLeft-8, y);
doc.line(layout.unitCostRight-55, topX,layout.unitCostRight-55, y); doc.line(layout.unitCostRight-55, topX,layout.unitCostRight-55, y);
doc.line(layout.qtyRight-50, topX,layout.qtyRight-50, y); doc.line(layout.qtyRight-50, topX,layout.qtyRight-50, y);
/*
if (invoice.has_taxes) { if (invoice.has_taxes) {
doc.line(layout.taxRight-28, topX,layout.taxRight-28, y); doc.line(layout.taxRight-28, topX,layout.taxRight-28, y);
} }
*/
doc.line(totalX-25, topX,totalX-25, y+90); doc.line(totalX-25, topX,totalX-25, y+90);
doc.line(totalX+45, topX,totalX+45, y+90); doc.line(totalX+45, topX,totalX+45, y+90);
} }

View File

@ -599,7 +599,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -713,7 +713,6 @@ return array(
'add_to_invoice' => 'Zur Rechnung :invoice hinzufügen', 'add_to_invoice' => 'Zur Rechnung :invoice hinzufügen',
'create_new_invoice' => 'Neue Rechnung erstellen', 'create_new_invoice' => 'Neue Rechnung erstellen',
'task_errors' => 'Bitte korrigieren Sie alle überlappenden Zeiten', 'task_errors' => 'Bitte korrigieren Sie alle überlappenden Zeiten',
'utf8_invoices' => 'Neue PDF Engine <sup>Beta</sup>',
'from' => 'Von', 'from' => 'Von',
'to' => 'An', 'to' => 'An',
'font_size' => 'Schriftgrösse', 'font_size' => 'Schriftgrösse',
@ -732,7 +731,7 @@ return array(
'invoice_no' => 'Rechnung Nr.', 'invoice_no' => 'Rechnung Nr.',
'recent_payments' => 'Kürzliche Zahlungen', 'recent_payments' => 'Kürzliche Zahlungen',
'manage_companies' => 'Unternehmen verwalten', 'manage_companies' => 'Unternehmen verwalten',
'total_revenue' => 'Gesamteinnahmen', 'total_revenue' => 'Gesamteinnahmen',
'current_user' => 'Aktueller Benutzer', 'current_user' => 'Aktueller Benutzer',
'new_recurring_invoice' => 'Neue wiederkehrende Rechnung', 'new_recurring_invoice' => 'Neue wiederkehrende Rechnung',

View File

@ -597,7 +597,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -569,7 +569,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -598,7 +598,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -590,7 +590,6 @@ return array(
'less_fields' => 'Moins de champs', 'less_fields' => 'Moins de champs',
'client_name' => 'Nom du client', 'client_name' => 'Nom du client',
'pdf_settings' => 'Réglages PDF', 'pdf_settings' => 'Réglages PDF',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Réglages du produit', 'product_settings' => 'Réglages du produit',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -590,7 +590,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -592,7 +592,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -600,7 +600,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -598,7 +598,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -593,7 +593,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -593,7 +593,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -596,7 +596,6 @@ return array(
'less_fields' => 'Less Fields', 'less_fields' => 'Less Fields',
'client_name' => 'Client Name', 'client_name' => 'Client Name',
'pdf_settings' => 'PDF Settings', 'pdf_settings' => 'PDF Settings',
'utf8_invoices' => 'New PDF Engine <sup>Beta</sup>',
'product_settings' => 'Product Settings', 'product_settings' => 'Product Settings',
'auto_wrap' => 'Auto Line Wrap', 'auto_wrap' => 'Auto Line Wrap',
'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.', 'duplicate_post' => 'Warning: the previous page was submitted twice. The second submission had been ignored.',

View File

@ -3,13 +3,10 @@
@section('head') @section('head')
@parent @parent
<script src="{!! asset('js/pdf_viewer.js') !!}" type="text/javascript"></script> <script src="{{ asset('js/pdf_viewer.js') }}" type="text/javascript"></script>
<script src="{!! asset('js/compatibility.js') !!}" type="text/javascript"></script> <script src="{{ asset('js/compatibility.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/pdfmake.min.js') }}" type="text/javascript"></script>
@if (Auth::user()->account->utf8_invoices) <script src="{{ asset('js/vfs_fonts.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/pdfmake.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/vfs_fonts.js') }}" type="text/javascript"></script>
@endif
@stop @stop
@ -102,10 +99,7 @@
{!! Former::select('invoice_design_id')->style('display:inline;width:120px')->fromQuery($invoiceDesigns, 'name', 'id') !!} {!! Former::select('invoice_design_id')->style('display:inline;width:120px')->fromQuery($invoiceDesigns, 'name', 'id') !!}
@endif @endif
@if (Auth::user()->account->utf8_invoices) {!! Former::text('font_size')->type('number')->min('0')->step('1')->style('width:120px') !!}
{!! Former::text('font_size')->type('number')->min('0')->step('1')->style('width:120px') !!}
@endif
{!! Former::text('primary_color') !!} {!! Former::text('primary_color') !!}
{!! Former::text('secondary_color') !!} {!! Former::text('secondary_color') !!}

View File

@ -23,7 +23,6 @@
{{ Former::populateField('custom_invoice_taxes2', intval($account->custom_invoice_taxes2)) }} {{ Former::populateField('custom_invoice_taxes2', intval($account->custom_invoice_taxes2)) }}
{{ Former::populateField('share_counter', intval($account->share_counter)) }} {{ Former::populateField('share_counter', intval($account->share_counter)) }}
{{ Former::populateField('pdf_email_attachment', intval($account->pdf_email_attachment)) }} {{ Former::populateField('pdf_email_attachment', intval($account->pdf_email_attachment)) }}
{{ Former::populateField('utf8_invoices', intval($account->utf8_invoices)) }}
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
@ -97,7 +96,6 @@
</div> </div>
<div class="panel-body"> <div class="panel-body">
{!! Former::checkbox('pdf_email_attachment')->text(trans('texts.enable')) !!} {!! Former::checkbox('pdf_email_attachment')->text(trans('texts.enable')) !!}
{!! Former::checkbox('utf8_invoices')->text(trans('texts.enable')) !!}
</div> </div>
</div> </div>
</div> </div>

View File

@ -5,11 +5,8 @@
<script src="{{ asset('js/pdf_viewer.js') }}" type="text/javascript"></script> <script src="{{ asset('js/pdf_viewer.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/compatibility.js') }}" type="text/javascript"></script> <script src="{{ asset('js/compatibility.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/pdfmake.min.js') }}" type="text/javascript"></script>
@if (Auth::user()->account->utf8_invoices) <script src="{{ asset('js/vfs_fonts.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/pdfmake.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/vfs_fonts.js') }}" type="text/javascript"></script>
@endif
@stop @stop
@ -138,7 +135,7 @@
<p>&nbsp;</p> <p>&nbsp;</p>
<div class="table-responsive"> <div class="table-responsive">
<table class="table invoice-table" style="margin-bottom: 0px !important"> <table class="table invoice-table">
<thead> <thead>
<tr> <tr>
<th style="min-width:32px;" class="hide-border"></th> <th style="min-width:32px;" class="hide-border"></th>
@ -246,6 +243,15 @@
</tr> </tr>
@endif @endif
<tr style="display:none" data-bind="visible: $root.invoice_item_taxes.show &amp;&amp; totals.hasItemTaxes">
<td class="hide-border" colspan="4"/>
@if (!$account->hide_quantity)
<td>{{ trans('texts.tax') }}</td>
@endif
<td style="min-width:120px"><span data-bind="html: totals.itemTaxRates"/></td>
<td style="text-align: right"><span data-bind="html: totals.itemTaxAmounts"/></td>
</tr>
<tr style="display:none" data-bind="visible: $root.invoice_taxes.show"> <tr style="display:none" data-bind="visible: $root.invoice_taxes.show">
<td class="hide-border" colspan="3"/> <td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/> <td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
@ -1298,13 +1304,6 @@
var discount = self.totals.rawDiscounted(); var discount = self.totals.rawDiscounted();
total -= discount; total -= discount;
/*
var discount = parseFloat(self.discount());
if (discount > 0) {
total = roundToTwo(total * ((100 - discount)/100));
}
*/
var customValue1 = roundToTwo(self.custom_value1()); var customValue1 = roundToTwo(self.custom_value1());
var customValue2 = roundToTwo(self.custom_value2()); var customValue2 = roundToTwo(self.custom_value2());
var customTaxes1 = self.custom_taxes1() == 1; var customTaxes1 = self.custom_taxes1() == 1;
@ -1326,6 +1325,65 @@
} }
}); });
self.totals.itemTaxes = ko.computed(function() {
var taxes = {};
var total = self.totals.rawSubtotal();
for(var i=0; i<self.invoice_items().length; i++) {
var item = self.invoice_items()[i];
var lineTotal = item.totals.rawTotal();
if (self.discount()) {
if (parseInt(self.is_amount_discount())) {
lineTotal -= roundToTwo((lineTotal/total) * self.discount());
} else {
lineTotal -= roundToTwo(lineTotal * (self.discount()/100));
}
}
var taxAmount = roundToTwo(lineTotal * item.tax_rate() / 100);
if (taxAmount) {
var key = item.tax_name() + item.tax_rate();
if (taxes.hasOwnProperty(key)) {
taxes[key].amount += taxAmount;
} else {
taxes[key] = {name:item.tax_name(), rate:item.tax_rate(), amount:taxAmount};
}
}
}
return taxes;
});
self.totals.hasItemTaxes = ko.computed(function() {
var count = 0;
var taxes = self.totals.itemTaxes();
for (var key in taxes) {
if (taxes.hasOwnProperty(key)) {
count++;
}
}
return count > 0;
});
self.totals.itemTaxRates = ko.computed(function() {
var taxes = self.totals.itemTaxes();
var parts = [];
for (var key in taxes) {
if (taxes.hasOwnProperty(key)) {
parts.push(taxes[key].name + ' ' + (taxes[key].rate*1) + '%');
}
}
return parts.join('<br/>');
});
self.totals.itemTaxAmounts = ko.computed(function() {
var taxes = self.totals.itemTaxes();
var parts = [];
for (var key in taxes) {
if (taxes.hasOwnProperty(key)) {
parts.push(formatMoney(taxes[key].amount, self.client().currency_id()));
}
}
return parts.join('<br/>');
});
self.totals.rawPaidToDate = ko.computed(function() { self.totals.rawPaidToDate = ko.computed(function() {
return accounting.toFixed(self.amount(),2) - accounting.toFixed(self.balance(),2); return accounting.toFixed(self.amount(),2) - accounting.toFixed(self.balance(),2);
}); });
@ -1352,10 +1410,17 @@
total = NINJA.parseFloat(total) + customValue2; total = NINJA.parseFloat(total) + customValue2;
} }
var taxRate = parseFloat(self.tax_rate()); var taxRate = parseFloat(self.tax_rate());
if (taxRate > 0) { if (taxRate > 0) {
total = NINJA.parseFloat(total) + roundToTwo((total * (taxRate/100))); total = NINJA.parseFloat(total) + roundToTwo((total * (taxRate/100)));
} }
var taxes = self.totals.itemTaxes();
for (var key in taxes) {
if (taxes.hasOwnProperty(key)) {
total += taxes[key].amount;
}
}
if (customValue1 && !customTaxes1) { if (customValue1 && !customTaxes1) {
total = NINJA.parseFloat(total) + customValue1; total = NINJA.parseFloat(total) + customValue1;
@ -1530,8 +1595,8 @@
self.displayName = ko.computed({ self.displayName = ko.computed({
read: function () { read: function () {
var name = self.name() ? self.name() : ''; var name = self.name() ? self.name() : '';
var rate = self.rate() ? parseFloat(self.rate()) + '% ' : ''; var rate = self.rate() ? parseFloat(self.rate()) + '%' : '';
return rate + name; return name + ' ' + rate;
}, },
write: function (value) { write: function (value) {
// do nothing // do nothing
@ -1605,7 +1670,6 @@
if (data) { if (data) {
ko.mapping.fromJS(data, self.mapping, this); ko.mapping.fromJS(data, self.mapping, this);
//if (this.cost()) this.cost(formatMoney(this.cost(), model ? model.invoice().currency_id() : 1, true));
} }
self.wrapped_notes = ko.computed({ self.wrapped_notes = ko.computed({
@ -1625,11 +1689,7 @@
this.totals.rawTotal = ko.computed(function() { this.totals.rawTotal = ko.computed(function() {
var cost = roundToTwo(NINJA.parseFloat(self.cost())); var cost = roundToTwo(NINJA.parseFloat(self.cost()));
var qty = roundToTwo(NINJA.parseFloat(self.qty())); var qty = roundToTwo(NINJA.parseFloat(self.qty()));
var taxRate = NINJA.parseFloat(self.tax_rate()); var value = cost * qty;
var value = cost * qty;
if (taxRate > 0) {
value += value * (taxRate/100);
}
return value ? roundToTwo(value) : 0; return value ? roundToTwo(value) : 0;
}); });

View File

@ -5,12 +5,8 @@
<script src="{{ asset('js/pdf_viewer.js') }}" type="text/javascript"></script> <script src="{{ asset('js/pdf_viewer.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/compatibility.js') }}" type="text/javascript"></script> <script src="{{ asset('js/compatibility.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/pdfmake.min.js') }}" type="text/javascript"></script>
@if (Auth::user()->account->utf8_invoices) <script src="{{ asset('js/vfs_fonts.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/pdfmake.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/vfs_fonts.js') }}" type="text/javascript"></script>
@endif
<script> <script>

View File

@ -7,11 +7,8 @@
<script src="{{ asset('js/pdf_viewer.js') }}" type="text/javascript"></script> <script src="{{ asset('js/pdf_viewer.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/compatibility.js') }}" type="text/javascript"></script> <script src="{{ asset('js/compatibility.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/pdfmake.min.js') }}" type="text/javascript"></script>
@if ($invoice->client->account->utf8_invoices) <script src="{{ asset('js/vfs_fonts.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/pdfmake.min.js') }}" type="text/javascript"></script>
<script src="{{ asset('js/vfs_fonts.js') }}" type="text/javascript"></script>
@endif
<style type="text/css"> <style type="text/css">
body { body {

View File

@ -136,6 +136,7 @@ table.table thead .sorting_desc_disabled:after { content: '' !important }
{!! Form::open(array('url' => 'get_started', 'id' => 'startForm')) !!} {!! Form::open(array('url' => 'get_started', 'id' => 'startForm')) !!}
{!! Form::hidden('guest_key') !!} {!! Form::hidden('guest_key') !!}
{!! Form::hidden('sign_up', Input::get('sign_up')) !!} {!! Form::hidden('sign_up', Input::get('sign_up')) !!}
{!! Form::hidden('redirect_to', Input::get('redirect_to')) !!}
{!! Form::close() !!} {!! Form::close() !!}
<script> <script>

View File

@ -270,15 +270,11 @@
} }
function ViewModel(data) { function ViewModel(data) {
console.log('== ViewModel ==');
console.log(data);
var self = this; var self = this;
self.time_log = ko.observableArray(); self.time_log = ko.observableArray();
if (data) { if (data) {
data = JSON.parse(data.time_log); data = JSON.parse(data.time_log);
console.log(data);
for (var i=0; i<data.length; i++) { for (var i=0; i<data.length; i++) {
self.time_log.push(new TimeModel(data[i])); self.time_log.push(new TimeModel(data[i]));
} }