Per product Tax rate in invoice doesn't update product. #1108

This commit is contained in:
Hillel Coren 2017-05-17 12:18:48 +03:00
parent 22a1be4d9c
commit 0ed4250766
20 changed files with 179 additions and 122 deletions

View File

@ -82,7 +82,7 @@ class AccountApiController extends BaseAPIController
$updatedAt = $request->updated_at ? date('Y-m-d H:i:s', $request->updated_at) : false;
$transformer = new AccountTransformer(null, $request->serializer);
$account->load(array_merge($transformer->getDefaultIncludes(), ['projects.client', 'products.default_tax_rate']));
$account->load(array_merge($transformer->getDefaultIncludes(), ['projects.client']));
$account = $this->createItem($account, $transformer, 'account');
return $this->response($account);

View File

@ -487,7 +487,7 @@ class AccountController extends BaseController
$data = [
'account' => Auth::user()->account,
'title' => trans('texts.tax_rates'),
'taxRates' => TaxRate::scope()->whereIsInclusive(false)->get(['id', 'name', 'rate']),
'taxRates' => TaxRate::scope()->whereIsInclusive(false)->get(),
];
return View::make('accounts.tax_rates', $data);

View File

@ -302,9 +302,8 @@ class InvoiceController extends BaseController
return [
'data' => Input::old('data'),
'account' => Auth::user()->account->load('country'),
'products' => Product::scope()->with('default_tax_rate')->orderBy('product_key')->get(),
'products' => Product::scope()->orderBy('product_key')->get(),
'taxRateOptions' => $taxRateOptions,
'defaultTax' => $account->default_tax_rate,
'currencies' => Cache::get('currencies'),
'sizes' => Cache::get('sizes'),
'invoiceDesigns' => InvoiceDesign::getDesigns(),

View File

@ -346,8 +346,10 @@ class OnlinePaymentController extends BaseController
'frequency_id' => Input::get('frequency_id'),
'auto_bill_id' => Input::get('auto_bill_id'),
'start_date' => Input::get('start_date', date('Y-m-d')),
'tax_rate1' => $account->default_tax_rate ? $account->default_tax_rate->rate : 0,
'tax_name1' => $account->default_tax_rate ? $account->default_tax_rate->name : '',
'tax_rate1' => $account->tax_rate1,
'tax_name1' => $account->tax_name1,
'tax_rate2' => $account->tax_rate2,
'tax_name2' => $account->tax_name2,
'custom_text_value1' => Input::get('custom_invoice1'),
'custom_text_value2' => Input::get('custom_invoice2'),
'invoice_items' => [[
@ -355,8 +357,10 @@ class OnlinePaymentController extends BaseController
'notes' => $product->notes,
'cost' => $product->cost,
'qty' => 1,
'tax_rate1' => $product->default_tax_rate ? $product->default_tax_rate->rate : 0,
'tax_name1' => $product->default_tax_rate ? $product->default_tax_rate->name : '',
'tax_rate1' => $account->tax_rate1,
'tax_name1' => $account->tax_name1,
'tax_rate2' => $account->tax_rate2,
'tax_name2' => $account->tax_name2,
'custom_value1' => Input::get('custom_product1') ?: $product->custom_value1,
'custom_value2' => Input::get('custom_product2') ?: $product->custom_value2,
]],

View File

@ -83,7 +83,7 @@ class ProductController extends BaseController
$data = [
'account' => $account,
'taxRates' => $account->invoice_item_taxes ? TaxRate::scope()->whereIsInclusive(false)->get(['id', 'name', 'rate']) : null,
'taxRates' => $account->invoice_item_taxes ? TaxRate::scope()->whereIsInclusive(false)->get() : null,
'product' => $product,
'entity' => $product,
'method' => 'PUT',

View File

@ -98,9 +98,8 @@ class QuoteController extends BaseController
return [
'entityType' => ENTITY_QUOTE,
'account' => $account,
'products' => Product::scope()->with('default_tax_rate')->orderBy('product_key')->get(),
'products' => Product::scope()->orderBy('product_key')->get(),
'taxRateOptions' => $account->present()->taxRateOptions,
'defaultTax' => $account->default_tax_rate,
'countries' => Cache::get('countries'),
'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(),
'taxRates' => TaxRate::scope()->orderBy('name')->get(),

View File

@ -110,7 +110,10 @@ class Account extends Eloquent
'num_days_reminder3',
'custom_invoice_text_label1',
'custom_invoice_text_label2',
'default_tax_rate_id',
'tax_name1',
'tax_rate1',
'tax_name2',
'tax_rate2',
'recurring_hour',
'invoice_number_pattern',
'quote_number_pattern',
@ -366,14 +369,6 @@ class Account extends Eloquent
return $this->belongsTo('App\Models\Industry');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function default_tax_rate()
{
return $this->belongsTo('App\Models\TaxRate');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View File

@ -30,7 +30,10 @@ class Product extends EntityModel
'notes',
'cost',
'qty',
'default_tax_rate_id',
'tax_name1',
'tax_rate1',
'tax_name2',
'tax_rate2',
'custom_value1',
'custom_value2',
];
@ -84,12 +87,4 @@ class Product extends EntityModel
{
return $this->belongsTo('App\Models\User')->withTrashed();
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function default_tax_rate()
{
return $this->belongsTo('App\Models\TaxRate');
}
}

View File

@ -83,10 +83,12 @@ class InvoiceIntent extends BaseIntent
$item['cost'] = $product->cost;
$item['notes'] = $product->notes;
/*
if ($taxRate = $product->default_tax_rate) {
$item['tax_name1'] = $taxRate->name;
$item['tax_rate1'] = $taxRate->rate;
}
*/
$invoiceItems[] = $item;
}

View File

@ -655,6 +655,10 @@ class InvoiceRepository extends BaseRepository
if ($product && (Auth::user()->can('edit', $product))) {
$product->notes = ($task || $expense) ? '' : $item['notes'];
$product->cost = $expense ? 0 : $item['cost'];
$product->tax_name1 = $item['tax_name1'];
$product->tax_rate1 = $item['tax_rate1'];
$product->tax_name2 = $item['tax_name2'];
$product->tax_rate2 = $item['tax_rate2'];
$product->custom_value1 = isset($item['custom_value1']) ? $item['custom_value1'] : null;
$product->custom_value2 = isset($item['custom_value2']) ? $item['custom_value2'] : null;
$product->save();

View File

@ -23,18 +23,14 @@ class ProductRepository extends BaseRepository
public function find($accountId, $filter = null)
{
$query = DB::table('products')
->leftJoin('tax_rates', function ($join) {
$join->on('tax_rates.id', '=', 'products.default_tax_rate_id')
->whereNull('tax_rates.deleted_at');
})
->where('products.account_id', '=', $accountId)
->select(
'products.public_id',
'products.product_key',
'products.notes',
'products.cost',
'tax_rates.name as tax_name',
'tax_rates.rate as tax_rate',
'products.tax_name1 as tax_name',
'products.tax_rate1 as tax_rate',
'products.deleted_at',
'products.is_deleted'
);
@ -82,9 +78,7 @@ class ProductRepository extends BaseRepository
$max = SIMILAR_MIN_THRESHOLD;
$productId = 0;
$products = Product::scope()
->with('default_tax_rate')
->get();
$products = Product::scope()->get();
foreach ($products as $product) {
if (! $product->product_key) {

View File

@ -213,7 +213,10 @@ class AccountTransformer extends EntityTransformer
'num_days_reminder3' => $account->num_days_reminder3,
'custom_invoice_text_label1' => $account->custom_invoice_text_label1,
'custom_invoice_text_label2' => $account->custom_invoice_text_label2,
'default_tax_rate_id' => $account->default_tax_rate_id ? $account->default_tax_rate->public_id : 0,
'tax_name1' => $account->tax_name1 ?: '',
'tax_rate1' => (float) $account->tax_rate1,
'tax_name2' => $account->tax_name2 ?: '',
'tax_rate2' => (float) $account->tax_rate2,
'recurring_hour' => $account->recurring_hour,
'invoice_number_pattern' => $account->invoice_number_pattern,
'quote_number_pattern' => $account->quote_number_pattern,

View File

@ -15,7 +15,6 @@ class ProductTransformer extends EntityTransformer
* @SWG\Property(property="notes", type="string", example="Notes...")
* @SWG\Property(property="cost", type="number", format="float", example=10.00)
* @SWG\Property(property="qty", type="number", format="float", example=1)
* @SWG\Property(property="default_tax_rate_id", type="integer", example=1)
* @SWG\Property(property="updated_at", type="integer", example=1451160233, readOnly=true)
* @SWG\Property(property="archived_at", type="integer", example=1451160233, readOnly=true)
*/
@ -27,7 +26,10 @@ class ProductTransformer extends EntityTransformer
'notes' => $product->notes,
'cost' => $product->cost,
'qty' => $product->qty,
'default_tax_rate_id' => $product->default_tax_rate_id ? $product->default_tax_rate->public_id : 0,
'tax_name1' => $product->tax_name1 ?: '',
'tax_rate1' => (float) $product->tax_rate1,
'tax_name2' => $product->tax_name2 ?: '',
'tax_rate2' => (float) $product->tax_rate2,
'updated_at' => $this->getTimestamp($product->updated_at),
'archived_at' => $this->getTimestamp($product->deleted_at),
]);

View File

@ -23,6 +23,41 @@ class AddDefaultNoteToClient extends Migration
Schema::table('payments', function ($table) {
$table->text('private_notes')->nullable();
});
Schema::table('accounts', function ($table) {
$table->string('tax_name1')->nullable();
$table->decimal('tax_rate1', 13, 3);
$table->string('tax_name2')->nullable();
$table->decimal('tax_rate2', 13, 3);
});
Schema::table('products', function ($table) {
$table->string('tax_name1')->nullable();
$table->decimal('tax_rate1', 13, 3);
$table->string('tax_name2')->nullable();
$table->decimal('tax_rate2', 13, 3);
});
DB::statement('update products
left join tax_rates on tax_rates.id = products.default_tax_rate_id
set products.tax_name1 = tax_rates.name, products.tax_rate1 = tax_rates.rate');
DB::statement('update accounts
left join tax_rates on tax_rates.id = accounts.default_tax_rate_id
set accounts.tax_name1 = tax_rates.name, accounts.tax_rate1 = tax_rates.rate');
if (Schema::hasColumn('accounts', 'default_tax_rate_id')) {
Schema::table('accounts', function ($table) {
$table->dropColumn('default_tax_rate_id');
}
});
if (Schema::hasColumn('products', 'default_tax_rate_id')) {
Schema::table('products', function ($table) {
$table->dropColumn('default_tax_rate_id');
}
});
}
/**
@ -43,5 +78,19 @@ class AddDefaultNoteToClient extends Migration
Schema::table('payments', function ($table) {
$table->dropColumn('private_notes');
});
Schema::table('accounts', function ($table) {
$table->dropColumn('tax_name1');
$table->dropColumn('tax_rate1');
$table->dropColumn('tax_name2');
$table->dropColumn('tax_rate2');
});
Schema::table('products', function ($table) {
$table->dropColumn('tax_name1');
$table->dropColumn('tax_rate1');
$table->dropColumn('tax_name2');
$table->dropColumn('tax_rate2');
});
}
}

View File

@ -33,12 +33,7 @@
{!! Former::text('cost') !!}
@if ($account->invoice_item_taxes)
{!! Former::select('default_tax_rate_id')
->addOption('', '')
->label(trans('texts.tax_rate'))
->fromQuery($taxRates, function($model) { return $model->name . ': ' . $model->rate . '%'; }, 'id') !!}
@endif
@include('partials.tax_rates')
</div>
</div>

View File

@ -47,11 +47,7 @@
&nbsp;
{!! Former::select('default_tax_rate_id')
->style('max-width: 250px')
->addOption('', '')
->fromQuery($taxRates, function($model) { return $model->name . ': ' . $model->rate . '%'; }, 'id') !!}
@include('partials.tax_rates')
&nbsp;
{!! Former::actions( Button::success(trans('texts.save'))->submit()->appendIcon(Icon::create('floppy-disk')) ) !!}

View File

@ -152,35 +152,13 @@
->label(' ')
->value(1) !!}
@endif
@endif
<div style="display:none" data-bind="visible: apply_taxes">
<br/>
{!! Former::select('tax_select1')
->addOption('','')
->label(trans('texts.tax_rate'))
->onchange('taxSelectChange(event)')
->fromQuery($taxRates) !!}
<div style="display:none">
{!! Former::input('tax_rate1') !!}
{!! Former::input('tax_name1') !!}
@include('partials.tax_rates')
</div>
<div style="display:{{ $account->enable_second_tax_rate ? 'block' : 'none' }}">
{!! Former::select('tax_select2')
->addOption('','')
->label(trans('texts.tax_rate'))
->onchange('taxSelectChange(event)')
->fromQuery($taxRates) !!}
<div style="display:none">
{!! Former::input('tax_rate2') !!}
{!! Former::input('tax_name2') !!}
</div>
</div>
</div>
@endif
@if ($account->hasFeature(FEATURE_DOCUMENTS))
{!! Former::checkbox('invoice_documents')
->text(trans('texts.add_documents_to_invoice'))
@ -259,7 +237,6 @@
var vendors = {!! $vendors !!};
var clients = {!! $clients !!};
var categories = {!! $categories !!};
var taxRates = {!! $taxRates !!};
var clientMap = {};
var vendorMap = {};
@ -355,9 +332,6 @@
onClientChange();
});
setTaxSelect(1);
setTaxSelect(2);
@if ($data)
// this means we failed so we'll reload the previous state
window.model = new ViewModel({!! $data !!});
@ -594,38 +568,6 @@
window.countUploadingDocuments--;
}
function taxSelectChange(event) {
var $select = $(event.target);
var tax = $select.find('option:selected').text();
var index = tax.lastIndexOf(': ');
var taxName = tax.substring(0, index);
var taxRate = tax.substring(index + 2, tax.length - 1);
var selectName = $select.attr('name');
var instance = selectName.substring(selectName.length - 1);
$('#tax_name' + instance).val(taxName);
$('#tax_rate' + instance).val(taxRate);
}
function setTaxSelect(instance) {
var $select = $('#tax_select' + instance);
var taxName = $('#tax_name' + instance).val();
var taxRate = $('#tax_rate' + instance).val();
if (!taxRate || !taxName) {
return;
}
var tax = _.findWhere(taxRates, {name:taxName, rate:taxRate});
if (tax) {
$select.val(tax.public_id);
} else {
var option = new Option(taxName + ': ' + taxRate + '%', '');
option.selected = true;
$select.append(option);
}
}
function onInvoiceDocumentsChange()
{
if (isStorageSupported()) {

View File

@ -908,10 +908,15 @@
model.invoice().addItem(); // add blank item
@else
// set the default account tax rate
@if ($account->invoice_taxes && ! empty($defaultTax))
var defaultTax = {!! $defaultTax->toJson() !!};
model.invoice().tax_rate1(defaultTax.rate);
model.invoice().tax_name1(defaultTax.name);
@if ($account->invoice_taxes)
@if (! empty($account->tax_name1))
model.invoice().tax_rate1("{{ $account->tax_rate1 }}");
model.invoice().tax_name1("{{ $account->tax_name1 }}");
@endif
@if (! empty($account->tax_name2))
model.invoice().tax_rate2("{{ $account->tax_rate2 }}");
model.invoice().tax_name2("{{ $account->tax_name2 }}");
@endif
@endif
@endif

View File

@ -944,9 +944,13 @@ ko.bindingHandlers.productTypeahead = {
model.qty(1);
}
@if ($account->invoice_item_taxes)
if (datum.default_tax_rate) {
if (datum.tax_name1) {
var $select = $(this).parentsUntil('tbody').find('select').first();
$select.val('0 ' + datum.default_tax_rate.rate + ' ' + datum.default_tax_rate.name).trigger('change');
$select.val('0 ' + datum.tax_rate1 + ' ' + datum.tax_name1).trigger('change');
}
if (datum.tax_name2) {
var $select = $(this).parentsUntil('tbody').find('select').last();
$select.val('0 ' + datum.tax_rate2 + ' ' + datum.tax_name2).trigger('change');
}
@endif
@if (Auth::user()->isPro() && $account->custom_invoice_item_label1)

View File

@ -0,0 +1,69 @@
@if ($account->invoice_item_taxes)
{!! Former::select('tax_select1')
->addOption('','')
->label(trans('texts.tax_rate'))
->onchange('taxSelectChange(event)')
->fromQuery($taxRates) !!}
<div style="display:none">
{!! Former::input('tax_rate1') !!}
{!! Former::input('tax_name1') !!}
</div>
<div style="display:{{ $account->enable_second_tax_rate ? 'block' : 'none' }}">
{!! Former::select('tax_select2')
->addOption('','')
->label(trans('texts.tax_rate'))
->onchange('taxSelectChange(event)')
->fromQuery($taxRates) !!}
<div style="display:none">
{!! Former::input('tax_rate2') !!}
{!! Former::input('tax_name2') !!}
</div>
</div>
@endif
<script type="text/javascript">
var taxRates = {!! $taxRates !!};
function taxSelectChange(event) {
var $select = $(event.target);
var tax = $select.find('option:selected').text();
var index = tax.lastIndexOf(': ');
var taxName = tax.substring(0, index);
var taxRate = tax.substring(index + 2, tax.length - 1);
var selectName = $select.attr('name');
var instance = selectName.substring(selectName.length - 1);
$('#tax_name' + instance).val(taxName);
$('#tax_rate' + instance).val(taxRate);
}
function setTaxSelect(instance) {
var $select = $('#tax_select' + instance);
var taxName = $('#tax_name' + instance).val();
var taxRate = $('#tax_rate' + instance).val();
if (!taxRate || !taxName) {
return;
}
var tax = _.findWhere(taxRates, {name:taxName, rate:taxRate});
if (tax) {
$select.val(tax.public_id);
} else {
var option = new Option(taxName + ': ' + taxRate + '%', '');
option.selected = true;
$select.append(option);
}
}
$(function() {
setTaxSelect(1);
setTaxSelect(2);
});
</script>