mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-09-20 00:11:35 +02:00
Working on taxes
This commit is contained in:
parent
7a90856025
commit
309442cab3
@ -134,7 +134,7 @@ class InvoiceController extends \BaseController {
|
||||
return View::make('invoices.deleted');
|
||||
}
|
||||
|
||||
if ($invoice->invoice_status_id < INVOICE_STATUS_VIEWED)
|
||||
if (!$invoice->isViewed())
|
||||
{
|
||||
$invoice->invoice_status_id = INVOICE_STATUS_VIEWED;
|
||||
$invoice->save();
|
||||
@ -241,15 +241,13 @@ class InvoiceController extends \BaseController {
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>');
|
||||
}
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
exit('Sorry, there was an error processing your payment. Please try again later.<p>'.$e);
|
||||
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>'.$e);
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
public function do_payment()
|
||||
@ -274,9 +272,12 @@ class InvoiceController extends \BaseController {
|
||||
$payment->transaction_reference = $ref;
|
||||
$payment->save();
|
||||
|
||||
if ($payment->amount >= $invoice->amount) {
|
||||
if ($payment->amount >= $invoice->amount)
|
||||
{
|
||||
$invoice->invoice_status_id = INVOICE_STATUS_PAID;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
$invoice->invoice_status_id = INVOICE_STATUS_PARTIAL;
|
||||
}
|
||||
$invoice->save();
|
||||
@ -286,12 +287,12 @@ class InvoiceController extends \BaseController {
|
||||
}
|
||||
else
|
||||
{
|
||||
exit($response->getMessage());
|
||||
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>'.$response->getMessage());
|
||||
}
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
exit('Sorry, there was an error processing your payment. Please try again later.' . $e);
|
||||
return Utils::fatalError('Sorry, there was an error processing your payment. Please try again later.<p>'.$e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -404,11 +405,16 @@ class InvoiceController extends \BaseController {
|
||||
$invoiceData['client_id'] = $client->id;
|
||||
$invoice = $this->invoiceRepo->save($publicId, $invoiceData);
|
||||
|
||||
$account = Auth::user()->account;
|
||||
if ($account->invoice_taxes != $input->invoice_taxes || $account->invoice_item_taxes != $input->invoice_item_taxes)
|
||||
{
|
||||
$account->invoice_taxes = $input->invoice_taxes;
|
||||
$account->invoice_item_taxes = $input->invoice_item_taxes;
|
||||
$account->save();
|
||||
}
|
||||
|
||||
if ($action == 'email' && $invoice->invoice_status_id == INVOICE_STATUS_DRAFT)
|
||||
{
|
||||
$invoice->invoice_status_id = INVOICE_STATUS_SENT;
|
||||
$invoice->save();
|
||||
|
||||
$client->balance = $client->balance + $invoice->amount;
|
||||
$client->save();
|
||||
}
|
||||
|
@ -125,6 +125,9 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->unsignedInteger('country_id')->nullable();
|
||||
$t->text('invoice_terms');
|
||||
|
||||
$t->boolean('invoice_taxes')->default(true);
|
||||
$t->boolean('invoice_item_taxes')->default(false);
|
||||
|
||||
$t->foreign('timezone_id')->references('id')->on('timezones');
|
||||
$t->foreign('date_format_id')->references('id')->on('date_formats');
|
||||
$t->foreign('datetime_format_id')->references('id')->on('datetime_formats');
|
||||
@ -303,6 +306,9 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->timestamp('last_sent_date')->nullable();
|
||||
$t->unsignedInteger('recurring_invoice_id')->index()->nullable();
|
||||
|
||||
$t->string('tax_name');
|
||||
$t->decimal('tax_rate', 13, 4);
|
||||
|
||||
$t->decimal('amount', 13, 4);
|
||||
$t->decimal('balance', 13, 4);
|
||||
|
||||
|
@ -2,6 +2,12 @@
|
||||
|
||||
class Utils
|
||||
{
|
||||
public static function fatalError($error)
|
||||
{
|
||||
Log::error($error);
|
||||
return View::make('error')->with('error', $error);
|
||||
}
|
||||
|
||||
public static function formatPhoneNumber($phoneNumber)
|
||||
{
|
||||
$phoneNumber = preg_replace('/[^0-9]/','',$phoneNumber);
|
||||
|
@ -42,9 +42,15 @@ class Invoice extends EntityModel
|
||||
return $this->invoice_status_id >= INVOICE_STATUS_SENT;
|
||||
}
|
||||
|
||||
public function isViewed()
|
||||
{
|
||||
return $this->invoice_status_id >= INVOICE_STATUS_VIEWED;
|
||||
}
|
||||
|
||||
public function hidePrivateFields()
|
||||
{
|
||||
$this->setVisible(['invoice_number', 'discount', 'po_number', 'invoice_date', 'due_date', 'terms', 'currency_id', 'public_notes', 'amount', 'balance', 'invoice_items', 'client']);
|
||||
$this->setVisible(['invoice_number', 'discount', 'po_number', 'invoice_date', 'due_date', 'terms', 'currency_id', 'public_notes', 'amount', 'balance', 'invoice_items', 'client', 'tax_name', 'tax_rate']);
|
||||
|
||||
$this->client->setVisible(['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'work_phone', 'payment_terms', 'contacts']);
|
||||
|
||||
foreach ($this->invoice_items as $invoiceItem)
|
||||
|
@ -80,7 +80,7 @@ class InvoiceRepository
|
||||
}
|
||||
|
||||
$invoice->client_id = $data['client_id'];
|
||||
$invoice->discount = $data['discount'];
|
||||
$invoice->discount = floatval($data['discount']);
|
||||
$invoice->invoice_number = trim($data['invoice_number']);
|
||||
$invoice->invoice_date = Utils::toSqlDate($data['invoice_date']);
|
||||
$invoice->due_date = Utils::toSqlDate($data['due_date']);
|
||||
@ -93,30 +93,19 @@ class InvoiceRepository
|
||||
$invoice->public_notes = trim($data['public_notes']);
|
||||
$invoice->po_number = trim($data['po_number']);
|
||||
$invoice->currency_id = $data['currency_id'];
|
||||
$invoice->tax_rate = 0;
|
||||
|
||||
$total = 0;
|
||||
|
||||
foreach ($data['invoice_items'] as $item)
|
||||
if (isset($data['tax']) && isset($data['tax']->rate) && floatval($data['tax']->rate) > 0)
|
||||
{
|
||||
if (!isset($item->cost))
|
||||
{
|
||||
$item->cost = 0;
|
||||
}
|
||||
|
||||
if (!isset($item->qty))
|
||||
{
|
||||
$item->qty = 0;
|
||||
}
|
||||
|
||||
$total += floatval($item->qty) * floatval($item->cost);
|
||||
$invoice->tax_rate = floatval($data['tax']->rate);
|
||||
$invoice->tax_name = trim($data['tax']->name);
|
||||
}
|
||||
|
||||
$invoice->amount = $total;
|
||||
$invoice->balance = $total;
|
||||
$invoice->save();
|
||||
|
||||
$invoice->invoice_items()->forceDelete();
|
||||
|
||||
$total = 0;
|
||||
|
||||
foreach ($data['invoice_items'] as $item)
|
||||
{
|
||||
if (!$item->cost && !$item->qty && !$item->product_key && !$item->notes)
|
||||
@ -149,17 +138,31 @@ class InvoiceRepository
|
||||
$invoiceItem->notes = trim($item->notes);
|
||||
$invoiceItem->cost = floatval($item->cost);
|
||||
$invoiceItem->qty = floatval($item->qty);
|
||||
$invoiceItem->tax_rate = 0;
|
||||
|
||||
if ($item->tax && isset($item->tax->rate) && isset($item->tax->name))
|
||||
if ($item->tax && isset($item->tax->rate) && floatval($item->tax->rate) > 0)
|
||||
{
|
||||
$invoiceItem->tax_rate = floatval($item->tax->rate);
|
||||
$invoiceItem->tax_name = trim($item->tax->name);
|
||||
}
|
||||
|
||||
$invoice->invoice_items()->save($invoiceItem);
|
||||
$total += floatval($item->qty) * floatval($item->cost);
|
||||
|
||||
$lineTotal = $invoiceItem->cost * $invoiceItem->qty;
|
||||
$total += $lineTotal + ($lineTotal * $invoiceItem->tax_rate / 100);
|
||||
}
|
||||
|
||||
if ($invoice->discount > 0)
|
||||
{
|
||||
$total *= (100 - $invoice->discount) / 100;
|
||||
}
|
||||
|
||||
$total += $total * $invoice->tax_rate / 100;
|
||||
|
||||
$invoice->amount = $total;
|
||||
$invoice->balance = $total;
|
||||
$invoice->save();
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
}
|
||||
|
7
app/views/error.blade.php
Executable file
7
app/views/error.blade.php
Executable file
@ -0,0 +1,7 @@
|
||||
@extends('header')
|
||||
|
||||
@section('content')
|
||||
|
||||
{{ $error }}
|
||||
|
||||
@stop
|
@ -16,7 +16,7 @@
|
||||
'email' => 'required',
|
||||
'product_key' => 'max:14',
|
||||
)); }}
|
||||
|
||||
|
||||
<div class="row" style="min-height:195px" onkeypress="formEnterClick(event)">
|
||||
<div class="col-md-5" id="col_1">
|
||||
|
||||
@ -108,59 +108,70 @@
|
||||
<th>Description</th>
|
||||
<th>Unit Cost</th>
|
||||
<th>Quantity</th>
|
||||
<th data-bind="visible: tax_rates().length > 1">Tax</th>
|
||||
<th data-bind="visible: showInvoiceItemTaxes">Tax</th>
|
||||
<th>Line Total</th>
|
||||
<th class="hide-border"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-bind="sortable: { data: invoice_items, afterMove: onDragged }">
|
||||
<tr data-bind="event: { mouseover: showActions, mouseout: hideActions }" class="sortable-row">
|
||||
<td style="width:20px;" class="hide-border td-icon">
|
||||
<td style="min-width:20px;" class="hide-border td-icon">
|
||||
<i data-bind="visible: actionsVisible() && $parent.invoice_items().length > 1" class="fa fa-sort"></i>
|
||||
</td>
|
||||
<td style="width:120px">
|
||||
<td style="min-width:120px">
|
||||
{{ Former::text('product_key')->useDatalist(Product::getProductKeys($products), 'key')->onkeyup('onItemChange()')
|
||||
->raw()->data_bind("value: product_key, valueUpdate: 'afterkeydown'")->addClass('datalist') }}
|
||||
</td>
|
||||
<td style="width:300px">
|
||||
<td style="width:100%">
|
||||
<textarea data-bind="value: wrapped_notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" style="resize: none;" class="form-control word-wrap"></textarea>
|
||||
</td>
|
||||
<td style="width:100px">
|
||||
<td style="min-width:120px">
|
||||
<input onkeyup="onItemChange()" data-bind="value: prettyCost, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control"//>
|
||||
</td>
|
||||
<td style="width:80px">
|
||||
<td style="min-width:120px">
|
||||
<input onkeyup="onItemChange()" data-bind="value: prettyQty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control"//>
|
||||
</td>
|
||||
<td style="width:120px; vertical-align:middle" data-bind="visible: $parent.tax_rates().length > 1">
|
||||
<td style="min-width:120px; vertical-align:middle" data-bind="visible: $parent.showInvoiceItemTaxes">
|
||||
<select class="form-control" style="width:100%" data-bind="value: tax, options: $parent.tax_rates, optionsText: 'displayName'"></select>
|
||||
</td>
|
||||
<td style="width:100px;text-align: right;padding-top:9px !important">
|
||||
<td style="min-width:120px;text-align: right;padding-top:9px !important">
|
||||
<span data-bind="text: total"></span>
|
||||
</td>
|
||||
<td style="width:20px; cursor:pointer" class="hide-border td-icon">
|
||||
<td style="min-width:20px; cursor:pointer" class="hide-border td-icon">
|
||||
<i data-bind="click: $parent.removeItem, visible: actionsVisible() && $parent.invoice_items().length > 1" class="fa fa-minus-circle" title="Remove item"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td class="hide-border"/>
|
||||
<td data-bind="attr: {colspan: tax_rates().length > 1 ? 3 : 2}"/>
|
||||
<td colspan="2"/>
|
||||
<td data-bind="visible: showInvoiceItemTaxes"/>
|
||||
<td colspan="2">Subtotal</td>
|
||||
<td style="text-align: right"><span data-bind="text: subtotal"/></td>
|
||||
</tr>
|
||||
<tr data-bind="visible: discount() > 0">
|
||||
<td class="hide-border" data-bind="attr: {colspan: tax_rates().length > 1 ? 4 : 3}"/>
|
||||
<td class="hide-border" colspan="3"/>
|
||||
<td class="hide-border" data-bind="visible: showInvoiceItemTaxes"/>
|
||||
<td colspan="2">Discount</td>
|
||||
<td style="text-align: right"><span data-bind="text: discounted"/></td>
|
||||
</tr>
|
||||
<tr data-bind="visible: showInvoiceTaxes">
|
||||
<td class="hide-border" colspan="3"/>
|
||||
<td class="hide-border" data-bind="visible: showInvoiceItemTaxes"/>
|
||||
<td style="vertical-align: middle">Tax</td>
|
||||
<td><select class="form-control" style="width:100%" data-bind="value: tax, options: tax_rates, optionsText: 'displayName'"></select></td>
|
||||
<td style="vertical-align: middle; text-align: right"><span data-bind="text: taxAmount"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="hide-border" data-bind="attr: {colspan: tax_rates().length > 1 ? 4 : 3}"/>
|
||||
<td class="hide-border" colspan="3"/>
|
||||
<td class="hide-border" data-bind="visible: showInvoiceItemTaxes"/>
|
||||
<td colspan="2">Paid to Date</td>
|
||||
<td style="text-align: right"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="hide-border" data-bind="attr: {colspan: tax_rates().length > 1 ? 4 : 3}"/>
|
||||
<td class="hide-border" colspan="3"/>
|
||||
<td class="hide-border" data-bind="visible: showInvoiceItemTaxes"/>
|
||||
<td colspan="2"><b>Balance Due</b></td>
|
||||
<td style="text-align: right"><span data-bind="text: total"/></td>
|
||||
</tr>
|
||||
@ -319,6 +330,12 @@
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
{{ Former::checkbox('invoice_taxes')->text('Enable specifying an <b>invoice tax</b>')
|
||||
->label('Settings')->data_bind('checked: invoice_taxes, enable: tax_rates().length > 1') }}
|
||||
{{ Former::checkbox('invoice_item_taxes')->text('Enable specifying <b>line item taxes</b>')
|
||||
->label(' ')->data_bind('checked: invoice_item_taxes, enable: tax_rates().length > 1') }}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer" style="margin-top: 0px">
|
||||
@ -394,9 +411,24 @@
|
||||
$('#taxModal').on('shown.bs.modal', function () {
|
||||
$('#taxModal input:first').focus();
|
||||
}).on('hidden.bs.modal', function () {
|
||||
console.log('TAX HIDDEN: %s %s', model.invoice_taxes(), model.invoice_item_taxes())
|
||||
/*
|
||||
var blank = model.getBlankTaxRate();
|
||||
if (!model.invoice_taxes()) {
|
||||
model.tax(blank);
|
||||
}
|
||||
if (!model.invoice_item_taxes()) {
|
||||
for (var i=0; i<model.invoice_items().length; i++) {
|
||||
var item = model.invoice_items()[i];
|
||||
item.tax(blank);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*
|
||||
if (model.taxBackup) {
|
||||
|
||||
}
|
||||
*/
|
||||
})
|
||||
|
||||
$('#actionDropDown > button:first').click(function() {
|
||||
@ -558,12 +590,16 @@
|
||||
self.due_date = ko.observable('');
|
||||
self.start_date = ko.observable('');
|
||||
self.end_date = ko.observable('');
|
||||
self.tax = ko.observable('');
|
||||
self.is_recurring = ko.observable(false);
|
||||
self.invoice_status_id = ko.observable(0);
|
||||
|
||||
self.invoice_items = ko.observableArray();
|
||||
self.tax_rates = ko.observableArray();
|
||||
|
||||
self.invoice_taxes = ko.observable({{ Auth::user()->account->invoice_taxes ? 'true' : 'false' }});
|
||||
self.invoice_item_taxes = ko.observable({{ Auth::user()->account->invoice_item_taxes ? 'true' : 'false' }});
|
||||
|
||||
self.mapping = {
|
||||
'invoice_items': {
|
||||
create: function(options) {
|
||||
@ -590,6 +626,30 @@
|
||||
owner: this
|
||||
});
|
||||
|
||||
self.showInvoiceTaxes = ko.computed(function() {
|
||||
if (self.tax_rates().length > 1 && self.invoice_taxes()) {
|
||||
return true;
|
||||
}
|
||||
if (self.tax() && self.tax().rate() > 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
self.showInvoiceItemTaxes = ko.computed(function() {
|
||||
if (self.tax_rates().length > 1 && self.invoice_item_taxes()) {
|
||||
return true;
|
||||
}
|
||||
for (var i=0; i<self.invoice_items().length; i++) {
|
||||
var item = self.invoice_items()[i];
|
||||
if (item.tax() && item.tax().rate() > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
self.wrapped_notes = ko.computed({
|
||||
read: function() {
|
||||
$('#public_notes').height(this.public_notes().split('\n').length * 36);
|
||||
@ -653,7 +713,7 @@
|
||||
|
||||
$('#emailError').css( "display", "none" );
|
||||
//$('.client_select input.form-control').focus();
|
||||
$('#terms').focus();
|
||||
$('#invoice_number').focus();
|
||||
|
||||
refreshPDF();
|
||||
model.clientBackup = false;
|
||||
@ -682,6 +742,15 @@
|
||||
applyComboboxListeners();
|
||||
}
|
||||
|
||||
self.getBlankTaxRate = function() {
|
||||
for (var i=0; i<self.tax_rates().length; i++) {
|
||||
var taxRate = self.tax_rates()[i];
|
||||
if (!taxRate.name()) {
|
||||
return taxRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.rawSubtotal = ko.computed(function() {
|
||||
var total = 0;
|
||||
for(var p = 0; p < self.invoice_items().length; ++p)
|
||||
@ -696,12 +765,32 @@
|
||||
return total > 0 ? formatMoney(total, self.currency_id()) : '';
|
||||
});
|
||||
|
||||
this.rawDiscounted = ko.computed(function() {
|
||||
return self.rawSubtotal() * (self.discount()/100);
|
||||
});
|
||||
|
||||
this.discounted = ko.computed(function() {
|
||||
var total = self.rawSubtotal() * (self.discount()/100);
|
||||
return formatMoney(total, self.currency_id());
|
||||
return formatMoney(self.rawDiscounted(), self.currency_id());
|
||||
});
|
||||
|
||||
self.taxAmount = ko.computed(function() {
|
||||
var total = self.rawSubtotal();
|
||||
|
||||
var discount = parseFloat(self.discount());
|
||||
if (discount > 0) {
|
||||
total = total * ((100 - discount)/100);
|
||||
}
|
||||
|
||||
var taxRate = self.tax() ? parseFloat(self.tax().rate()) : 0;
|
||||
if (taxRate > 0) {
|
||||
var tax = total * (taxRate/100);
|
||||
return formatMoney(tax, self.currency_id());
|
||||
} else {
|
||||
return formatMoney(0);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
this.total = ko.computed(function() {
|
||||
var total = self.rawSubtotal();
|
||||
|
||||
@ -710,6 +799,11 @@
|
||||
total = total * ((100 - discount)/100);
|
||||
}
|
||||
|
||||
var taxRate = self.tax() ? parseFloat(self.tax().rate()) : 0;
|
||||
if (taxRate > 0) {
|
||||
total = parseFloat(total) + (total * (taxRate/100));
|
||||
}
|
||||
|
||||
return total > 0 ? formatMoney(total, self.currency_id()) : '';
|
||||
});
|
||||
|
||||
@ -821,9 +915,9 @@
|
||||
|
||||
|
||||
self.displayName = ko.computed(function() {
|
||||
var name = self.name() ? self.name() : false;
|
||||
var rate = self.rate() ? parseFloat(self.rate()) : false;
|
||||
return (name && rate) ? (rate + '%' + ' - ' + name) : '';
|
||||
var name = self.name() ? self.name() : '';
|
||||
var rate = self.rate() ? parseFloat(self.rate()) + '% -' : '';
|
||||
return rate + name;
|
||||
});
|
||||
|
||||
self.hideActions = function() {
|
||||
|
@ -32,7 +32,7 @@ function generatePDF(invoice) {
|
||||
for (var i=0; i<invoice.invoice_items.length; i++)
|
||||
{
|
||||
var item = invoice.invoice_items[i];
|
||||
if (item.tax && item.tax.rate > 0) {
|
||||
if ((item.tax && item.tax.rate > 0) || (item.tax_rate && parseFloat(item.tax_rate) > 0)) {
|
||||
hasTaxes = true;
|
||||
break;
|
||||
}
|
||||
@ -141,7 +141,12 @@ function generatePDF(invoice) {
|
||||
var qty = item.qty ? parseFloat(item.qty) + '' : '';
|
||||
var notes = item.notes;
|
||||
var productKey = item.product_key;
|
||||
var tax = item.tax && parseFloat(item.tax.rate) ? parseFloat(item.tax.rate) + '%' : false;
|
||||
var tax = 0;
|
||||
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
|
||||
if (shownItem && (!cost || cost == '0.00') && !qty && !notes && !productKey) {
|
||||
@ -155,7 +160,7 @@ function generatePDF(invoice) {
|
||||
|
||||
var lineTotal = item.cost * item.qty;
|
||||
if (tax) {
|
||||
lineTotal += lineTotal * parseFloat(item.tax.rate) / 100;
|
||||
lineTotal += lineTotal * tax / 100;
|
||||
}
|
||||
if (lineTotal) {
|
||||
total += lineTotal;
|
||||
@ -164,7 +169,7 @@ function generatePDF(invoice) {
|
||||
|
||||
var costX = unitCostRight - (doc.getStringUnitWidth(cost) * doc.internal.getFontSize());
|
||||
var qtyX = qtyRight - (doc.getStringUnitWidth(qty) * doc.internal.getFontSize());
|
||||
var taxX = taxRight - (doc.getStringUnitWidth(tax) * doc.internal.getFontSize());
|
||||
var taxX = taxRight - (doc.getStringUnitWidth(tax+'%') * doc.internal.getFontSize());
|
||||
var totalX = lineTotalRight - (doc.getStringUnitWidth(lineTotal) * doc.internal.getFontSize());
|
||||
var x = tableTop + (line * tableRowHeight) + 6;
|
||||
if (i==0) x -= 4;
|
||||
@ -176,7 +181,7 @@ function generatePDF(invoice) {
|
||||
doc.text(totalX, x, lineTotal);
|
||||
|
||||
if (tax) {
|
||||
doc.text(taxX, x, tax);
|
||||
doc.text(taxX, x, tax+'%');
|
||||
}
|
||||
|
||||
line += doc.splitTextToSize(item.notes, 200).length;
|
||||
@ -206,12 +211,30 @@ function generatePDF(invoice) {
|
||||
|
||||
x += 16;
|
||||
doc.text(footerLeft, x, 'Discount');
|
||||
var discount = formatMoney(total * (invoice.discount/100), currencyId, true);
|
||||
var discount = total * (invoice.discount/100);
|
||||
total -= discount;
|
||||
discount = formatMoney(discount, currencyId, true);
|
||||
var discountX = headerRight - (doc.getStringUnitWidth(discount) * doc.internal.getFontSize());
|
||||
doc.text(discountX, x, discount);
|
||||
}
|
||||
|
||||
var tax = 0;
|
||||
if (invoice.tax && parseFloat(invoice.tax.rate)) {
|
||||
tax = parseFloat(invoice.tax.rate);
|
||||
} else if (invoice.tax_rate && parseFloat(invoice.tax_rate)) {
|
||||
tax = parseFloat(invoice.tax_rate);
|
||||
}
|
||||
|
||||
if (tax) {
|
||||
x += 16;
|
||||
doc.text(footerLeft, x, 'Tax ' + tax + '%');
|
||||
var tax = total * (tax/100);
|
||||
total = parseFloat(total) + parseFloat(tax);
|
||||
tax = formatMoney(tax, currencyId, true);
|
||||
var taxX = headerRight - (doc.getStringUnitWidth(tax) * doc.internal.getFontSize());
|
||||
doc.text(taxX, x, tax);
|
||||
}
|
||||
|
||||
x += 16;
|
||||
doc.text(footerLeft, x, 'Paid to Date');
|
||||
var paid = formatMoney(0, currencyId, true);
|
||||
|
Loading…
Reference in New Issue
Block a user