mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-07 16:14:28 -04:00
bug fixes
This commit is contained in:
parent
f323d0ed95
commit
4ff55936d7
@ -3,20 +3,23 @@
|
||||
use ninja\mailers\ContactMailer as Mailer;
|
||||
use ninja\repositories\InvoiceRepository;
|
||||
use ninja\repositories\ClientRepository;
|
||||
use ninja\repositories\TaxRateRepository;
|
||||
|
||||
class InvoiceController extends \BaseController {
|
||||
|
||||
protected $mailer;
|
||||
protected $invoiceRepo;
|
||||
protected $clientRepo;
|
||||
protected $taxRateRepo;
|
||||
|
||||
public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo, ClientRepository $clientRepo)
|
||||
public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo, ClientRepository $clientRepo, TaxRateRepository $taxRateRepo)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->mailer = $mailer;
|
||||
$this->invoiceRepo = $invoiceRepo;
|
||||
$this->clientRepo = $clientRepo;
|
||||
$this->taxRateRepo = $taxRateRepo;
|
||||
}
|
||||
|
||||
public function index()
|
||||
@ -391,6 +394,8 @@ class InvoiceController extends \BaseController {
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->taxRateRepo->save($input->tax_rates);
|
||||
|
||||
$clientData = (array) $input->client;
|
||||
$client = $this->clientRepo->save($input->client->public_id, $clientData);
|
||||
|
||||
|
@ -359,7 +359,6 @@ class ConfideSetupUsersTable extends Migration {
|
||||
$t->unsignedInteger('user_id');
|
||||
$t->unsignedInteger('invoice_id')->index();
|
||||
$t->unsignedInteger('product_id')->nullable();
|
||||
$t->unsignedInteger('tax_rate_id')->nullable();
|
||||
$t->timestamps();
|
||||
$t->softDeletes();
|
||||
|
||||
@ -373,7 +372,6 @@ class ConfideSetupUsersTable extends Migration {
|
||||
|
||||
$t->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade');
|
||||
$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->unsignedInteger('public_id');
|
||||
|
@ -25,6 +25,11 @@ class Account extends Eloquent
|
||||
return $this->hasMany('AccountGateway');
|
||||
}
|
||||
|
||||
public function tax_rates()
|
||||
{
|
||||
return $this->hasMany('TaxRate');
|
||||
}
|
||||
|
||||
public function country()
|
||||
{
|
||||
return $this->belongsTo('Country');
|
||||
|
@ -3,4 +3,5 @@
|
||||
class TaxRate extends EntityModel
|
||||
{
|
||||
|
||||
|
||||
}
|
@ -135,24 +135,6 @@ class InvoiceRepository
|
||||
$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->product_id = isset($product) ? $product->id : null;
|
||||
$invoiceItem->product_key = trim($item->product_key);
|
||||
@ -160,11 +142,10 @@ class InvoiceRepository
|
||||
$invoiceItem->cost = floatval($item->cost);
|
||||
$invoiceItem->qty = floatval($item->qty);
|
||||
|
||||
if ($taxRate)
|
||||
if ($item->tax && isset($item->tax->rate) && isset($item->tax->name))
|
||||
{
|
||||
$invoiceItem->tax_rate_id = $taxRate->id;
|
||||
$invoiceItem->tax_rate = $taxRate->rate;
|
||||
$invoiceItem->tax_name = $taxRate->name;
|
||||
$invoiceItem->tax_rate = floatval($item->tax->rate);
|
||||
$invoiceItem->tax_name = trim($item->tax->name);
|
||||
}
|
||||
|
||||
$invoice->invoice_items()->save($invoiceItem);
|
||||
|
49
app/ninja/repositories/TaxRateRepository.php
Executable file
49
app/ninja/repositories/TaxRateRepository.php
Executable file
@ -0,0 +1,49 @@
|
||||
<?php namespace ninja\repositories;
|
||||
|
||||
use TaxRate;
|
||||
|
||||
class TaxRateRepository
|
||||
{
|
||||
public function save($taxRates)
|
||||
{
|
||||
$taxRateIds = [];
|
||||
|
||||
foreach ($taxRates as $record)
|
||||
{
|
||||
if (!isset($record->rate) || $record->is_deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!floatval($record->rate) || !trim($record->name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($record->public_id)
|
||||
{
|
||||
$taxRate = TaxRate::scope($record->public_id)->firstOrFail();
|
||||
}
|
||||
else
|
||||
{
|
||||
$taxRate = TaxRate::createNew();
|
||||
}
|
||||
|
||||
$taxRate->rate = floatval($record->rate);
|
||||
$taxRate->name = trim($record->name);
|
||||
$taxRate->save();
|
||||
|
||||
$taxRateIds[] = $taxRate->public_id;
|
||||
}
|
||||
|
||||
$taxRates = TaxRate::scope()->get();
|
||||
|
||||
foreach($taxRates as $taxRate)
|
||||
{
|
||||
if (!in_array($taxRate->public_id, $taxRateIds))
|
||||
{
|
||||
$taxRate->delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -111,10 +111,10 @@
|
||||
<input onkeyup="onItemChange()" data-bind="value: cost, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
|
||||
</td>
|
||||
<td style="width:80px">
|
||||
<input onkeyup="onItemChange()" data-bind="value: qty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
|
||||
<input onkeyup="onItemChange()" data-bind="value: prettyQty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
|
||||
</td>
|
||||
<td style="width:80px; vertical-align:middle" data-bind="visible: $parent.tax_rates().length > 1">
|
||||
<select style="width:100%" data-bind="value: tax, options: $parent.tax_rates, optionsText: 'displayName'"></select>
|
||||
<td style="width:120px; vertical-align:middle" data-bind="visible: $parent.tax_rates().length > 1">
|
||||
<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">
|
||||
<span data-bind="text: total"></span>
|
||||
@ -286,7 +286,7 @@
|
||||
<input onkeyup="onTaxRateChange()" data-bind="value: name, valueUpdate: 'afterkeydown'" class="form-control" onchange="refreshPDF()"//>
|
||||
</td>
|
||||
<td style="width:60px">
|
||||
<input onkeyup="onTaxRateChange()" data-bind="value: rate, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
|
||||
<input onkeyup="onTaxRateChange()" data-bind="value: prettyRate, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" onchange="refreshPDF()"//>
|
||||
</td>
|
||||
<td style="width:10px; cursor:pointer" class="hide-border td-icon">
|
||||
<i data-bind="click: $parent.removeTaxRate, visible: actionsVisible() && $parent.tax_rates().length > 1" class="fa fa-minus-circle" title="Remove item"/>
|
||||
@ -298,7 +298,7 @@
|
||||
</div>
|
||||
|
||||
<div class="modal-footer" style="margin-top: 0px">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<!-- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> -->
|
||||
<button type="button" class="btn btn-primary" data-bind="click: taxFormComplete">Done</button>
|
||||
</div>
|
||||
|
||||
@ -392,9 +392,9 @@
|
||||
var product = products[i];
|
||||
if (product.product_key == key) {
|
||||
var model = ko.dataFor(this);
|
||||
model.notes(product.notes);
|
||||
model.cost(product.cost);
|
||||
model.qty(product.qty);
|
||||
//model.notes(product.notes);
|
||||
//model.cost(product.cost);
|
||||
//model.qty(product.qty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -612,11 +612,6 @@
|
||||
var itemModel = new ItemModel();
|
||||
self.invoice_items.push(itemModel);
|
||||
applyComboboxListeners();
|
||||
|
||||
itemModel.tax.subscribe(function (data) {
|
||||
console.log('Tax change...');
|
||||
console.log(data)
|
||||
});
|
||||
}
|
||||
|
||||
self.removeTaxRate = function(taxRate) {
|
||||
@ -625,7 +620,8 @@
|
||||
}
|
||||
|
||||
self.addTaxRate = function(data) {
|
||||
self.tax_rates.push(new TaxRateModel(data));
|
||||
var itemModel = new TaxRateModel(data);
|
||||
self.tax_rates.push(itemModel);
|
||||
applyComboboxListeners();
|
||||
}
|
||||
|
||||
@ -737,15 +733,27 @@
|
||||
self.public_id = ko.observable('');
|
||||
self.rate = ko.observable();
|
||||
self.name = ko.observable('');
|
||||
self.is_deleted = ko.observable(false);
|
||||
self.actionsVisible = ko.observable(false);
|
||||
|
||||
if (data) {
|
||||
ko.mapping.fromJS(data, {}, this);
|
||||
}
|
||||
|
||||
this.prettyRate = ko.computed({
|
||||
read: function () {
|
||||
return this.rate() ? parseFloat(this.rate()) : '';
|
||||
},
|
||||
write: function (value) {
|
||||
this.rate(value);
|
||||
},
|
||||
owner: this
|
||||
});
|
||||
|
||||
|
||||
self.displayName = ko.computed(function() {
|
||||
var name = self.name() ? self.name() : false;
|
||||
var rate = self.rate() ? self.rate() : false;
|
||||
var rate = self.rate() ? parseFloat(self.rate()) : false;
|
||||
return (name && rate) ? (rate + '%' + ' - ' + name) : '';
|
||||
});
|
||||
|
||||
@ -771,20 +779,41 @@
|
||||
this.tax = ko.observable();
|
||||
this.actionsVisible = ko.observable(false);
|
||||
|
||||
this.prettyQty = ko.computed({
|
||||
read: function () {
|
||||
return this.qty() ? parseFloat(this.qty()) : '';
|
||||
},
|
||||
write: function (value) {
|
||||
this.qty(value);
|
||||
},
|
||||
owner: this
|
||||
});
|
||||
|
||||
if (data) {
|
||||
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())) {
|
||||
if (data && (data.tax_name == taxRate.name() && data.tax_rate == taxRate.rate())) {
|
||||
self.tax(taxRate);
|
||||
} else if (!data && !taxRate.tax_name) {
|
||||
break;
|
||||
} else if ((!data || !data.tax_name) && !taxRate.name()) {
|
||||
self.tax(taxRate);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if the tax was deleted but exists for the line item
|
||||
if (data && data.tax_name && (parseFloat(data.tax_rate)) && !self.tax()) {
|
||||
var taxRate = new TaxRateModel();
|
||||
taxRate.rate(parseFloat(data.tax_rate));
|
||||
taxRate.name(data.tax_name);
|
||||
taxRate.is_deleted(true);
|
||||
model.tax_rates.push(taxRate);
|
||||
self.tax(taxRate);
|
||||
}
|
||||
|
||||
self.wrapped_notes = ko.computed({
|
||||
read: function() {
|
||||
return this.notes();
|
||||
@ -882,6 +911,7 @@
|
||||
@foreach ($taxRates as $taxRate)
|
||||
model.addTaxRate({{ $taxRate }});
|
||||
@endforeach
|
||||
model.addTaxRate();
|
||||
@if ($invoice)
|
||||
var invoice = {{ $invoice }};
|
||||
ko.mapping.fromJS(invoice, model.mapping, model);
|
||||
@ -896,7 +926,6 @@
|
||||
model.invoice_number('{{ $invoiceNumber }}');
|
||||
model.terms(wordWrapText('{{ $account->invoice_terms }}', 250));
|
||||
@endif
|
||||
model.addTaxRate();
|
||||
model.addItem();
|
||||
ko.applyBindings(model);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user