mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
working in taxes
This commit is contained in:
parent
130a176888
commit
f323d0ed95
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,6 +1,6 @@
|
|||||||
/app/config/staging
|
/app/config/staging
|
||||||
/app/config/development
|
/app/config/development
|
||||||
/app/storage/
|
/app/storage
|
||||||
/public/logo
|
/public/logo
|
||||||
/public/build
|
/public/build
|
||||||
/bootstrap/compiled.php
|
/bootstrap/compiled.php
|
||||||
@ -8,4 +8,4 @@
|
|||||||
composer.phar
|
composer.phar
|
||||||
composer.lock
|
composer.lock
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
|
@ -348,6 +348,7 @@ class InvoiceController extends \BaseController {
|
|||||||
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
'products' => Product::scope()->get(array('product_key','notes','cost','qty')),
|
||||||
'countries' => Country::orderBy('name')->get(),
|
'countries' => Country::orderBy('name')->get(),
|
||||||
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
'clients' => Client::scope()->with('contacts')->orderBy('name')->get(),
|
||||||
|
'taxRates' => TaxRate::scope()->orderBy('name')->get(),
|
||||||
'frequencies' => array(
|
'frequencies' => array(
|
||||||
1 => 'Weekly',
|
1 => 'Weekly',
|
||||||
2 => 'Two weeks',
|
2 => 'Two weeks',
|
||||||
|
@ -10,7 +10,6 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
*/
|
*/
|
||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
Schema::dropIfExists('tax_rates');
|
|
||||||
Schema::dropIfExists('themes');
|
Schema::dropIfExists('themes');
|
||||||
Schema::dropIfExists('credits');
|
Schema::dropIfExists('credits');
|
||||||
Schema::dropIfExists('activities');
|
Schema::dropIfExists('activities');
|
||||||
@ -20,6 +19,7 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
Schema::dropIfExists('payments');
|
Schema::dropIfExists('payments');
|
||||||
Schema::dropIfExists('invoice_items');
|
Schema::dropIfExists('invoice_items');
|
||||||
Schema::dropIfExists('products');
|
Schema::dropIfExists('products');
|
||||||
|
Schema::dropIfExists('tax_rates');
|
||||||
Schema::dropIfExists('contacts');
|
Schema::dropIfExists('contacts');
|
||||||
Schema::dropIfExists('invoices');
|
Schema::dropIfExists('invoices');
|
||||||
Schema::dropIfExists('password_reminders');
|
Schema::dropIfExists('password_reminders');
|
||||||
@ -313,6 +313,24 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
$t->unique( array('account_id','public_id') );
|
$t->unique( array('account_id','public_id') );
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Schema::create('tax_rates', function($t)
|
||||||
|
{
|
||||||
|
$t->increments('id');
|
||||||
|
$t->unsignedInteger('account_id')->index();
|
||||||
|
$t->unsignedInteger('user_id');
|
||||||
|
$t->timestamps();
|
||||||
|
$t->softDeletes();
|
||||||
|
|
||||||
|
$t->string('name');
|
||||||
|
$t->decimal('rate', 10, 2);
|
||||||
|
|
||||||
|
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
||||||
|
$t->foreign('user_id')->references('id')->on('users');
|
||||||
|
|
||||||
|
$t->unsignedInteger('public_id');
|
||||||
|
$t->unique( array('account_id','public_id') );
|
||||||
|
});
|
||||||
|
|
||||||
Schema::create('products', function($t)
|
Schema::create('products', function($t)
|
||||||
{
|
{
|
||||||
$t->increments('id');
|
$t->increments('id');
|
||||||
@ -341,6 +359,7 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
$t->unsignedInteger('user_id');
|
$t->unsignedInteger('user_id');
|
||||||
$t->unsignedInteger('invoice_id')->index();
|
$t->unsignedInteger('invoice_id')->index();
|
||||||
$t->unsignedInteger('product_id')->nullable();
|
$t->unsignedInteger('product_id')->nullable();
|
||||||
|
$t->unsignedInteger('tax_rate_id')->nullable();
|
||||||
$t->timestamps();
|
$t->timestamps();
|
||||||
$t->softDeletes();
|
$t->softDeletes();
|
||||||
|
|
||||||
@ -354,6 +373,7 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
|
|
||||||
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
|
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
|
||||||
$t->foreign('product_id')->references('id')->on('products');
|
$t->foreign('product_id')->references('id')->on('products');
|
||||||
|
$t->foreign('tax_rate_id')->references('id')->on('tax_rates');
|
||||||
$t->foreign('user_id')->references('id')->on('users');
|
$t->foreign('user_id')->references('id')->on('users');
|
||||||
|
|
||||||
$t->unsignedInteger('public_id');
|
$t->unsignedInteger('public_id');
|
||||||
@ -412,24 +432,6 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
$t->unique( array('account_id','public_id') );
|
$t->unique( array('account_id','public_id') );
|
||||||
});
|
});
|
||||||
|
|
||||||
Schema::create('tax_rates', function($t)
|
|
||||||
{
|
|
||||||
$t->increments('id');
|
|
||||||
$t->unsignedInteger('account_id')->index();
|
|
||||||
$t->unsignedInteger('user_id');
|
|
||||||
$t->timestamps();
|
|
||||||
$t->softDeletes();
|
|
||||||
|
|
||||||
$t->string('name');
|
|
||||||
$t->decimal('rate', 10, 2);
|
|
||||||
|
|
||||||
$t->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
|
|
||||||
$t->foreign('user_id')->references('id')->on('users');
|
|
||||||
|
|
||||||
$t->unsignedInteger('public_id');
|
|
||||||
$t->unique( array('account_id','public_id') );
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::create('activities', function($t)
|
Schema::create('activities', function($t)
|
||||||
{
|
{
|
||||||
$t->increments('id');
|
$t->increments('id');
|
||||||
@ -461,7 +463,6 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
*/
|
*/
|
||||||
public function down()
|
public function down()
|
||||||
{
|
{
|
||||||
Schema::dropIfExists('tax_rates');
|
|
||||||
Schema::dropIfExists('themes');
|
Schema::dropIfExists('themes');
|
||||||
Schema::dropIfExists('credits');
|
Schema::dropIfExists('credits');
|
||||||
Schema::dropIfExists('activities');
|
Schema::dropIfExists('activities');
|
||||||
@ -471,6 +472,7 @@ class ConfideSetupUsersTable extends Migration {
|
|||||||
Schema::dropIfExists('payments');
|
Schema::dropIfExists('payments');
|
||||||
Schema::dropIfExists('invoice_items');
|
Schema::dropIfExists('invoice_items');
|
||||||
Schema::dropIfExists('products');
|
Schema::dropIfExists('products');
|
||||||
|
Schema::dropIfExists('tax_rates');
|
||||||
Schema::dropIfExists('contacts');
|
Schema::dropIfExists('contacts');
|
||||||
Schema::dropIfExists('invoices');
|
Schema::dropIfExists('invoices');
|
||||||
Schema::dropIfExists('password_reminders');
|
Schema::dropIfExists('password_reminders');
|
||||||
|
@ -47,9 +47,11 @@ class EntityModel extends Eloquent
|
|||||||
|
|
||||||
public function scopeScope($query, $publicId = false, $accountId = false)
|
public function scopeScope($query, $publicId = false, $accountId = false)
|
||||||
{
|
{
|
||||||
if (!$accountId) {
|
if (!$accountId)
|
||||||
|
{
|
||||||
$accountId = Auth::user()->account_id;
|
$accountId = Auth::user()->account_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$query->whereAccountId($accountId);
|
$query->whereAccountId($accountId);
|
||||||
|
|
||||||
if ($publicId)
|
if ($publicId)
|
||||||
|
@ -4,6 +4,7 @@ use Invoice;
|
|||||||
use InvoiceItem;
|
use InvoiceItem;
|
||||||
use Product;
|
use Product;
|
||||||
use Utils;
|
use Utils;
|
||||||
|
use TaxRate;
|
||||||
|
|
||||||
class InvoiceRepository
|
class InvoiceRepository
|
||||||
{
|
{
|
||||||
@ -134,6 +135,24 @@ class InvoiceRepository
|
|||||||
$product->save();
|
$product->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$taxRate = false;
|
||||||
|
if ($item->tax)
|
||||||
|
{
|
||||||
|
if ($item->tax->public_id)
|
||||||
|
{
|
||||||
|
$taxRate = TaxRate::scope($item->tax->public_id)->firstOrFail();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$taxRate = TaxRate::createNew();
|
||||||
|
}
|
||||||
|
|
||||||
|
$taxRate->rate = floatval($item->tax->rate);
|
||||||
|
$taxRate->name = trim($item->tax->name);
|
||||||
|
|
||||||
|
$taxRate->save();
|
||||||
|
}
|
||||||
|
|
||||||
$invoiceItem = InvoiceItem::createNew();
|
$invoiceItem = InvoiceItem::createNew();
|
||||||
$invoiceItem->product_id = isset($product) ? $product->id : null;
|
$invoiceItem->product_id = isset($product) ? $product->id : null;
|
||||||
$invoiceItem->product_key = trim($item->product_key);
|
$invoiceItem->product_key = trim($item->product_key);
|
||||||
@ -141,6 +160,13 @@ class InvoiceRepository
|
|||||||
$invoiceItem->cost = floatval($item->cost);
|
$invoiceItem->cost = floatval($item->cost);
|
||||||
$invoiceItem->qty = floatval($item->qty);
|
$invoiceItem->qty = floatval($item->qty);
|
||||||
|
|
||||||
|
if ($taxRate)
|
||||||
|
{
|
||||||
|
$invoiceItem->tax_rate_id = $taxRate->id;
|
||||||
|
$invoiceItem->tax_rate = $taxRate->rate;
|
||||||
|
$invoiceItem->tax_name = $taxRate->name;
|
||||||
|
}
|
||||||
|
|
||||||
$invoice->invoice_items()->save($invoiceItem);
|
$invoice->invoice_items()->save($invoiceItem);
|
||||||
$total += floatval($item->qty) * floatval($item->cost);
|
$total += floatval($item->qty) * floatval($item->cost);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
@section('head')
|
@section('head')
|
||||||
|
|
||||||
<meta name="csrf-token" content="<?= csrf_token() ?>">
|
<meta name="csrf-token" content="<?= csrf_token() ?>">
|
||||||
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
|
<script src="{{ asset('js/jquery-ui.min.js') }}" type="text/javascript"></script>
|
||||||
@if (Auth::check() && Auth::user()->theme_id)
|
@if (Auth::check() && Auth::user()->theme_id)
|
||||||
<link rel="stylesheet" type="text/css" href="{{ asset('css/themes/'.Auth::user()->theme->name.'.min.css') }}"/>
|
<link rel="stylesheet" type="text/css" href="{{ asset('css/themes/'.Auth::user()->theme->name.'.min.css') }}"/>
|
||||||
@else
|
@else
|
||||||
|
@ -114,7 +114,7 @@
|
|||||||
<input onkeyup="onItemChange()" data-bind="value: qty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
|
<input onkeyup="onItemChange()" data-bind="value: qty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:80px; vertical-align:middle" data-bind="visible: $parent.tax_rates().length > 1">
|
<td style="width:80px; vertical-align:middle" data-bind="visible: $parent.tax_rates().length > 1">
|
||||||
<select style="width:100%" data-bind="options: $parent.tax_rates"></select>
|
<select style="width:100%" data-bind="value: tax, options: $parent.tax_rates, optionsText: 'displayName'"></select>
|
||||||
</td>
|
</td>
|
||||||
<td style="width:100px;text-align: right;padding-top:9px !important">
|
<td style="width:100px;text-align: right;padding-top:9px !important">
|
||||||
<span data-bind="text: total"></span>
|
<span data-bind="text: total"></span>
|
||||||
@ -126,7 +126,8 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="hide-border" data-bind="attr: {colspan: tax_rates().length > 1 ? 4 : 3}"/>
|
<td class="hide-border"/>
|
||||||
|
<td data-bind="attr: {colspan: tax_rates().length > 1 ? 3 : 2}"/>
|
||||||
<td colspan="2">Subtotal</td>
|
<td colspan="2">Subtotal</td>
|
||||||
<td style="text-align: right"><span data-bind="text: subtotal"/></td>
|
<td style="text-align: right"><span data-bind="text: subtotal"/></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -352,23 +353,22 @@
|
|||||||
//$('[name="client_combobox"]').focus();
|
//$('[name="client_combobox"]').focus();
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
$('#clientModal').on('hidden.bs.modal', function () {
|
$('#clientModal').on('shown.bs.modal', function () {
|
||||||
|
$('#name').focus();
|
||||||
|
}).on('hidden.bs.modal', function () {
|
||||||
if (model.clientBackup) {
|
if (model.clientBackup) {
|
||||||
console.log("Loading backup");
|
|
||||||
//console.log(model.clientBackup);
|
|
||||||
model.loadClient(model.clientBackup);
|
model.loadClient(model.clientBackup);
|
||||||
refreshPDF();
|
refreshPDF();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
$('#clientModal').on('shown.bs.modal', function () {
|
|
||||||
$('#name').focus();
|
|
||||||
})
|
|
||||||
|
|
||||||
$('#taxModal').on('shown.bs.modal', function () {
|
$('#taxModal').on('shown.bs.modal', function () {
|
||||||
$('#taxModal input:first').focus();
|
$('#taxModal input:first').focus();
|
||||||
})
|
}).on('hidden.bs.modal', function () {
|
||||||
|
if (model.taxBackup) {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
$('#actionDropDown > button:first').click(function() {
|
$('#actionDropDown > button:first').click(function() {
|
||||||
onSaveClick();
|
onSaveClick();
|
||||||
@ -557,10 +557,13 @@
|
|||||||
|
|
||||||
|
|
||||||
self.showTaxesForm = function() {
|
self.showTaxesForm = function() {
|
||||||
|
self.taxBackup = ko.mapping.toJS(self.tax_rates);
|
||||||
|
|
||||||
$('#taxModal').modal('show');
|
$('#taxModal').modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
self.taxFormComplete = function() {
|
self.taxFormComplete = function() {
|
||||||
|
model.taxBackup = false;
|
||||||
$('#taxModal').modal('hide');
|
$('#taxModal').modal('hide');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -606,8 +609,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.addItem = function() {
|
self.addItem = function() {
|
||||||
self.invoice_items.push(new ItemModel());
|
var itemModel = new ItemModel();
|
||||||
|
self.invoice_items.push(itemModel);
|
||||||
applyComboboxListeners();
|
applyComboboxListeners();
|
||||||
|
|
||||||
|
itemModel.tax.subscribe(function (data) {
|
||||||
|
console.log('Tax change...');
|
||||||
|
console.log(data)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.removeTaxRate = function(taxRate) {
|
self.removeTaxRate = function(taxRate) {
|
||||||
@ -615,8 +624,8 @@
|
|||||||
//refreshPDF();
|
//refreshPDF();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.addTaxRate = function() {
|
self.addTaxRate = function(data) {
|
||||||
self.tax_rates.push(new TaxRateModel());
|
self.tax_rates.push(new TaxRateModel(data));
|
||||||
applyComboboxListeners();
|
applyComboboxListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -725,19 +734,30 @@
|
|||||||
|
|
||||||
function TaxRateModel(data) {
|
function TaxRateModel(data) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.rate = ko.observable();
|
self.public_id = ko.observable('');
|
||||||
this.name = ko.observable('');
|
self.rate = ko.observable();
|
||||||
this.actionsVisible = ko.observable(false);
|
self.name = ko.observable('');
|
||||||
|
self.actionsVisible = ko.observable(false);
|
||||||
|
|
||||||
this.hideActions = function() {
|
if (data) {
|
||||||
this.actionsVisible(false);
|
ko.mapping.fromJS(data, {}, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.displayName = ko.computed(function() {
|
||||||
|
var name = self.name() ? self.name() : false;
|
||||||
|
var rate = self.rate() ? self.rate() : false;
|
||||||
|
return (name && rate) ? (rate + '%' + ' - ' + name) : '';
|
||||||
|
});
|
||||||
|
|
||||||
|
self.hideActions = function() {
|
||||||
|
self.actionsVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showActions = function() {
|
self.showActions = function() {
|
||||||
this.actionsVisible(true);
|
self.actionsVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isEmpty = function() {
|
self.isEmpty = function() {
|
||||||
return !self.rate() && !self.name();
|
return !self.rate() && !self.name();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -748,13 +768,22 @@
|
|||||||
this.notes = ko.observable('');
|
this.notes = ko.observable('');
|
||||||
this.cost = ko.observable();
|
this.cost = ko.observable();
|
||||||
this.qty = ko.observable();
|
this.qty = ko.observable();
|
||||||
this.tax_rate = ko.observable();
|
this.tax = ko.observable();
|
||||||
this.tax_name = ko.observable('');
|
|
||||||
this.actionsVisible = ko.observable(false);
|
this.actionsVisible = ko.observable(false);
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
ko.mapping.fromJS(data, {}, this);
|
ko.mapping.fromJS(data, {}, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('data: ' + data);
|
||||||
|
for (var i=0; i<model.tax_rates().length; i++) {
|
||||||
|
var taxRate = model.tax_rates()[i];
|
||||||
|
if (data && (data.tax_name == taxRate.name())) {
|
||||||
|
self.tax(taxRate);
|
||||||
|
} else if (!data && !taxRate.tax_name) {
|
||||||
|
self.tax(taxRate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.wrapped_notes = ko.computed({
|
self.wrapped_notes = ko.computed({
|
||||||
read: function() {
|
read: function() {
|
||||||
@ -771,13 +800,13 @@
|
|||||||
this.rawTotal = ko.computed(function() {
|
this.rawTotal = ko.computed(function() {
|
||||||
var cost = parseFloat(self.cost());
|
var cost = parseFloat(self.cost());
|
||||||
var qty = parseFloat(self.qty());
|
var qty = parseFloat(self.qty());
|
||||||
var tax = parseFloat(self.tax_rate());
|
var taxRate = self.tax() ? parseFloat(self.tax().rate()) : 0;
|
||||||
var value = cost * qty;
|
var value = cost * qty;
|
||||||
if (tax > 0) {
|
if (taxRate > 0) {
|
||||||
//value = value * ((100 - this.tax())/100);
|
value += value * (taxRate/100);
|
||||||
}
|
}
|
||||||
return value ? value : '';
|
return value ? value : '';
|
||||||
});
|
});
|
||||||
|
|
||||||
this.total = ko.computed(function() {
|
this.total = ko.computed(function() {
|
||||||
var total = self.rawTotal();
|
var total = self.rawTotal();
|
||||||
@ -793,8 +822,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.isEmpty = function() {
|
this.isEmpty = function() {
|
||||||
return !self.product_key() && !self.notes() && !self.cost() && !self.qty() && !self.tax();
|
return !self.product_key() && !self.notes() && !self.cost() && !self.qty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.onSelect = function(){
|
||||||
|
console.log("select");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onItemChange()
|
function onItemChange()
|
||||||
@ -845,10 +878,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
window.model = new InvoiceModel();
|
window.model = new InvoiceModel();
|
||||||
|
@foreach ($taxRates as $taxRate)
|
||||||
|
model.addTaxRate({{ $taxRate }});
|
||||||
|
@endforeach
|
||||||
@if ($invoice)
|
@if ($invoice)
|
||||||
var invoice = {{ $invoice }};
|
var invoice = {{ $invoice }};
|
||||||
ko.mapping.fromJS(invoice, model.mapping, model);
|
ko.mapping.fromJS(invoice, model.mapping, model);
|
||||||
if (!model.discount()) model.discount('');
|
if (!model.discount()) model.discount('');
|
||||||
var invitationContactIds = {{ json_encode($invitationContactIds) }};
|
var invitationContactIds = {{ json_encode($invitationContactIds) }};
|
||||||
var client = clientMap[invoice.client.public_id];
|
var client = clientMap[invoice.client.public_id];
|
||||||
@ -859,12 +895,11 @@
|
|||||||
@else
|
@else
|
||||||
model.invoice_number('{{ $invoiceNumber }}');
|
model.invoice_number('{{ $invoiceNumber }}');
|
||||||
model.terms(wordWrapText('{{ $account->invoice_terms }}', 250));
|
model.terms(wordWrapText('{{ $account->invoice_terms }}', 250));
|
||||||
@endif
|
@endif
|
||||||
model.addItem();
|
|
||||||
model.addTaxRate();
|
model.addTaxRate();
|
||||||
|
model.addItem();
|
||||||
ko.applyBindings(model);
|
ko.applyBindings(model);
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@stop
|
@stop
|
12
public/js/jquery-ui.min.js
vendored
Executable file
12
public/js/jquery-ui.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
@ -132,6 +132,7 @@ function generatePDF(invoice) {
|
|||||||
var qty = item.qty ? parseFloat(item.qty) + '' : '';
|
var qty = item.qty ? parseFloat(item.qty) + '' : '';
|
||||||
var notes = item.notes;
|
var notes = item.notes;
|
||||||
var productKey = item.product_key;
|
var productKey = item.product_key;
|
||||||
|
var tax = item.tax && parseFloat(item.tax.rate) ? parseFloat(item.tax.rate) + '%' : false;
|
||||||
|
|
||||||
// show at most one blank line
|
// show at most one blank line
|
||||||
if (shownItem && (!cost || cost == '0.00') && !qty && !notes && !productKey) {
|
if (shownItem && (!cost || cost == '0.00') && !qty && !notes && !productKey) {
|
||||||
@ -144,11 +145,17 @@ function generatePDF(invoice) {
|
|||||||
productKey = processVariables(productKey);
|
productKey = processVariables(productKey);
|
||||||
|
|
||||||
var lineTotal = item.cost * item.qty;
|
var lineTotal = item.cost * item.qty;
|
||||||
if (lineTotal) total += lineTotal;
|
if (tax) {
|
||||||
|
lineTotal += lineTotal * parseFloat(item.tax.rate) / 100;
|
||||||
|
}
|
||||||
|
if (lineTotal) {
|
||||||
|
total += lineTotal;
|
||||||
|
}
|
||||||
lineTotal = formatNumber(lineTotal);
|
lineTotal = formatNumber(lineTotal);
|
||||||
|
|
||||||
var costX = unitCostRight - (doc.getStringUnitWidth(cost) * doc.internal.getFontSize());
|
var costX = unitCostRight - (doc.getStringUnitWidth(cost) * doc.internal.getFontSize());
|
||||||
var qtyX = qtyRight - (doc.getStringUnitWidth(qty) * doc.internal.getFontSize());
|
var qtyX = qtyRight - (doc.getStringUnitWidth(qty) * doc.internal.getFontSize());
|
||||||
|
var taxX = taxRight - (doc.getStringUnitWidth(tax) * doc.internal.getFontSize());
|
||||||
var totalX = lineTotalRight - (doc.getStringUnitWidth(lineTotal) * doc.internal.getFontSize());
|
var totalX = lineTotalRight - (doc.getStringUnitWidth(lineTotal) * doc.internal.getFontSize());
|
||||||
var x = tableTop + (line * rowHeight) + 6;
|
var x = tableTop + (line * rowHeight) + 6;
|
||||||
|
|
||||||
@ -158,6 +165,10 @@ function generatePDF(invoice) {
|
|||||||
doc.text(qtyX, x, qty);
|
doc.text(qtyX, x, qty);
|
||||||
doc.text(totalX, x, lineTotal);
|
doc.text(totalX, x, lineTotal);
|
||||||
|
|
||||||
|
if (tax) {
|
||||||
|
doc.text(taxX, x, tax);
|
||||||
|
}
|
||||||
|
|
||||||
line += doc.splitTextToSize(item.notes, 200).length;
|
line += doc.splitTextToSize(item.notes, 200).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user