Working on product fields

This commit is contained in:
Hillel Coren 2017-10-29 12:39:15 +02:00
parent 817d7b83ad
commit 450e4ae66a
11 changed files with 40 additions and 57 deletions

View File

@ -376,4 +376,10 @@ trait PresentsInvoice
return null;
}
public function hideQuantity() {
$fields = $this->getInvoiceFields();
return ! isset($fields['product_fields']['product.quantity']);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -225,8 +225,6 @@ NINJA.decodeJavascript = function(invoice, javascript)
'taskLineItems': NINJA.invoiceLines(invoice, true),
'taskLineItemColumns': NINJA.invoiceColumns(invoice, true),
'invoiceDocuments' : NINJA.invoiceDocuments(invoice),
'quantityWidth': NINJA.quantityWidth(invoice),
'taxWidth': NINJA.taxWidth(invoice),
'clientDetails': NINJA.clientDetails(invoice),
'notesAndTerms': NINJA.notesAndTerms(invoice),
'subtotals': invoice.is_statement ? NINJA.statementSubtotals(invoice) : NINJA.subtotals(invoice),
@ -248,15 +246,9 @@ NINJA.decodeJavascript = function(invoice, javascript)
}
for (var key in json) {
// remove trailing commas for these fields
if (['quantityWidth', 'taxWidth'].indexOf(key) >= 0) {
var regExp = new RegExp('"\\$'+key+'",', 'g');
val = json[key];
} else {
var regExp = new RegExp('"\\$'+key+'"', 'g');
var val = JSON.stringify(json[key]);
val = doubleDollarSign(val);
}
var regExp = new RegExp('"\\$'+key+'"', 'g');
var val = JSON.stringify(json[key]);
val = doubleDollarSign(val);
javascript = javascript.replace(regExp, val);
}
@ -417,7 +409,7 @@ NINJA.invoiceColumns = function(invoice, isTasks)
columns.push(hasDescription ? '10%' : '*');
}
} else if (field == 'product.tax') {
if (invoice.has_taxes) {
if (invoice.has_item_taxes) {
columns.push(hasDescription ? '15%' : '*');
}
} else if (field == 'product.description') {
@ -445,16 +437,6 @@ NINJA.invoiceFooter = function(invoice)
}
}
NINJA.quantityWidth = function(invoice)
{
return invoice.account.hide_quantity == '1' ? '' : '"14%", ';
}
NINJA.taxWidth = function(invoice)
{
return invoice.account.show_item_taxes == '1' ? '"14%", ' : '';
}
NINJA.productFields = function(invoice, isTasks) {
var account = invoice.account;
var fields = JSON.parse(account.invoice_fields);
@ -500,6 +482,7 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
for (var i=0; i<fields.length; i++) {
var field = fields[i].split('.')[1]; // split to remove 'product.'
var headerStyles = styles.concat([snakeToCamel(field), snakeToCamel(field) + 'TableHeader']);
if (field == 'custom_value1' && ! invoice.has_custom_item_value1) {
continue;
@ -509,9 +492,11 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
continue;
} else if (field == 'product_key' && ! invoice.has_product_key) {
continue;
} else if (field == 'unit_cost' || field == 'rate' || field == 'hours') {
headerStyles.push('cost');
}
grid[0].push({text: invoiceLabels[field], style: styles.concat(snakeToCamel(field) + 'TableHeader')});
grid[0].push({text: invoiceLabels[field], style: headerStyles});
}
for (var i=0; i<invoice.invoice_items.length; i++) {
@ -596,11 +581,14 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
styles.push('productKey');
} else if (field == 'description') {
value = item.notes;
} else if (field == 'unit_cost') {
} else if (field == 'unit_cost' || field == 'rate') {
value = item.cost;
styles.push('cost');
} else if (field == 'quantity') {
} else if (field == 'quantity' || field == 'hours') {
value = formatAmount(item.qty, invoice.client.currency_id, getPrecision(item.qty));
if (field == 'hours') {
styles.push('cost');
}
} else if (field == 'tax') {
value = ' ';
if (item.tax_name1) {

View File

@ -692,7 +692,7 @@ function calculateAmounts(invoice) {
if (lineTotal) {
total += lineTotal;
}
if (!item.notes && !item.product_key && !item.cost && !item.qty) {
if (!item.notes && !item.product_key && !item.cost) {
continue;
}
if (item.invoice_item_type_id == 2) {

View File

@ -51,7 +51,6 @@
remove_created_by:{{ Auth::user()->hasFeature(FEATURE_REMOVE_CREATED_BY) ? 'true' : 'false' }},
invoice_settings:{{ Auth::user()->hasFeature(FEATURE_INVOICE_SETTINGS) ? 'true' : 'false' }}
};
invoice.account.hide_quantity = {!! Auth::user()->account->hide_quantity ? 'true' : 'false' !!};
invoice.account.hide_paid_to_date = {!! Auth::user()->account->hide_paid_to_date ? 'true' : 'false' !!};
NINJA.primaryColor = '{!! Auth::user()->account->primary_color !!}';
NINJA.secondaryColor = '{!! Auth::user()->account->secondary_color !!}';

View File

@ -282,10 +282,7 @@
<div role="tabpanel" class="tab-pane" id="invoice_options">
<div class="panel-body">
<!--
{!! Former::checkbox('hide_quantity')->text(trans('texts.hide_quantity_help'))->value(1) !!}
-->
{!! Former::checkbox('hide_paid_to_date')->text(trans('texts.hide_paid_to_date_help'))->value(1) !!}
{!! Former::checkbox('invoice_embed_documents')->text(trans('texts.invoice_embed_documents_help'))->value(1) !!}

View File

@ -8,10 +8,10 @@
<div class="table-responsive">
<table class="field-list">
<tbody data-bind="sortable: { data: {{ $section }}, as: 'field', afterMove: onDragged }">
<tbody data-bind="sortable: { data: {{ $section }}, as: 'field', afterMove: onDragged, allowDrop: {{ in_array($section, ['product_fields', 'task_fields']) ? 'false' : 'true' }} }">
<tr style="cursor:move;background-color:#fff;margin:1px">
<td>
<i class="fa fa-close" style="cursor:pointer" title="{{ trans('texts.remove') }}"
<i class="fa fa-close" style="cursor:default" title="{{ trans('texts.remove') }}"
data-bind="click: $root.{{ Utils::toCamelCase('remove' . ucwords($section)) }}"></i>
<span data-bind="text: window.field_map[field]"></span>
</td>

View File

@ -390,14 +390,14 @@
</td>
<td class="hide-border" style="display:none" data-bind="visible: $root.invoice_item_taxes.show"/>
<td colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ trans('texts.subtotal') }}</td>
<td colspan="2">{{ trans('texts.subtotal') }}</td>
<td style="text-align: right"><span data-bind="text: totals.subtotal"/></td>
</tr>
<tr style="display:none" data-bind="visible: discount() != 0">
<td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
<td colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ trans('texts.discount') }}</td>
<td colspan="2">{{ trans('texts.discount') }}</td>
<td style="text-align: right"><span data-bind="text: totals.discounted"/></td>
</tr>
@ -405,7 +405,7 @@
<tr>
<td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
<td colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ $account->custom_invoice_label1 ?: trans('texts.surcharge') }}</td>
<td colspan="2">{{ $account->custom_invoice_label1 ?: trans('texts.surcharge') }}</td>
<td style="text-align: right;padding-right: 28px" colspan="2"><input name="custom_value1" class="form-control" data-bind="value: custom_value1, valueUpdate: 'afterkeydown'"/></td>
</tr>
@endif
@ -413,7 +413,7 @@
<tr>
<td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
<td colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ $account->custom_invoice_label2 ?: trans('texts.surcharge') }}</td>
<td colspan="2">{{ $account->custom_invoice_label2 ?: trans('texts.surcharge') }}</td>
<td style="text-align: right;padding-right: 28px" colspan="2"><input name="custom_value2" class="form-control" data-bind="value: custom_value2, valueUpdate: 'afterkeydown'"/></td>
</tr>
@endif
@ -421,9 +421,7 @@
<tr style="display:none" data-bind="visible: $root.invoice_item_taxes.show &amp;&amp; totals.hasItemTaxes">
<td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
@if (!$account->hide_quantity)
<td>{{ trans('texts.tax') }}</td>
@endif
<td>{{ trans('texts.tax') }}</td>
<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>
@ -431,9 +429,7 @@
<tr style="display:none" data-bind="visible: $root.invoice_taxes.show">
<td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
@if (!$account->hide_quantity)
<td>{{ trans('texts.tax') }}</td>
@endif
<td>{{ trans('texts.tax') }}</td>
<td style="min-width:120px">
{!! Former::select('')
->id('taxRateSelect1')
@ -462,7 +458,7 @@
<tr>
<td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
<td colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ $account->custom_invoice_label1 ?: trans('texts.surcharge') }}</td>
<td colspan="2">{{ $account->custom_invoice_label1 ?: trans('texts.surcharge') }}</td>
<td style="text-align: right;padding-right: 28px" colspan="2"><input name="custom_value1" class="form-control" data-bind="value: custom_value1, valueUpdate: 'afterkeydown'"/></td>
</tr>
@endif
@ -471,7 +467,7 @@
<tr>
<td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
<td colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ $account->custom_invoice_label2 ?: trans('texts.surcharge') }}</td>
<td colspan="2">{{ $account->custom_invoice_label2 ?: trans('texts.surcharge') }}</td>
<td style="text-align: right;padding-right: 28px" colspan="2"><input name="custom_value2" class="form-control" data-bind="value: custom_value2, valueUpdate: 'afterkeydown'"/></td>
</tr>
@endif
@ -480,7 +476,7 @@
<tr>
<td class="hide-border" colspan="3"/>
<td style="display:none" class="hide-border" data-bind="visible: $root.invoice_item_taxes.show"/>
<td colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ trans('texts.paid_to_date') }}</td>
<td colspan="2">{{ trans('texts.paid_to_date') }}</td>
<td style="text-align: right" data-bind="text: totals.paidToDate"></td>
</tr>
@endif
@ -488,14 +484,14 @@
<tr data-bind="style: { 'font-weight': partial() ? 'normal' : 'bold', 'font-size': partial() ? '1em' : '1.05em' }">
<td class="hide-border" colspan="3"/>
<td class="hide-border" style="display:none" data-bind="visible: $root.invoice_item_taxes.show"/>
<td class="hide-border" data-bind="css: {'hide-border': !partial()}" colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ $entityType == ENTITY_INVOICE ? $invoiceLabels['balance_due'] : trans('texts.total') }}</td>
<td class="hide-border" data-bind="css: {'hide-border': !partial()}" colspan="2">{{ $entityType == ENTITY_INVOICE ? $invoiceLabels['balance_due'] : trans('texts.total') }}</td>
<td class="hide-border" data-bind="css: {'hide-border': !partial()}" style="text-align: right"><span data-bind="text: totals.total"></span></td>
</tr>
<tr style="font-size:1.05em; display:none; font-weight:bold" data-bind="visible: partial">
<td class="hide-border" colspan="3"/>
<td class="hide-border" style="display:none" data-bind="visible: $root.invoice_item_taxes.show"/>
<td class="hide-border" colspan="{{ $account->hide_quantity ? 1 : 2 }}">{{ $invoiceLabels['partial_due'] }}</td>
<td class="hide-border" colspan="2">{{ $invoiceLabels['partial_due'] }}</td>
<td class="hide-border" style="text-align: right"><span data-bind="text: totals.partial"></span></td>
</tr>

View File

@ -15,7 +15,7 @@
<th style="min-width:120px">{{ $account->custom_invoice_item_label2 }}</th>
@endif
<th style="min-width:120px">{{ $invoiceLabels[$isTasks ? 'rate' : 'unit_cost'] }}</th>
<th style="{{ $account->hide_quantity ? 'display:none' : 'min-width:120px' }}">{{ $invoiceLabels[$isTasks ? 'hours' : 'quantity'] }}</th>
<th style="min-width:120px">{{ $invoiceLabels[$isTasks ? 'hours' : 'quantity'] }}</th>
<th style="min-width:{{ $account->enable_second_tax_rate ? 180 : 120 }}px;display:none;" data-bind="visible: $root.invoice_item_taxes.show">{{ trans('texts.tax') }}</th>
<th style="min-width:120px;">{{ trans('texts.line_total') }}</th>
<th style="min-width:32px;" class="hide-border"></th>
@ -54,7 +54,7 @@
<input data-bind="value: prettyCost, valueUpdate: 'afterkeydown', attr: {name: 'invoice_items[{{ $isTasks ? 'T' : '' }}' + $index() + '][cost]'}"
style="text-align: right" class="form-control invoice-item"/>
</td>
<td style="{{ $account->hide_quantity ? 'display:none' : '' }}">
<td>
<input data-bind="value: prettyQty, valueUpdate: 'afterkeydown', attr: {name: 'invoice_items[{{ $isTasks ? 'T' : '' }}' + $index() + '][qty]'}"
style="text-align: right" class="form-control invoice-item" name="quantity"/>
</td>

View File

@ -309,9 +309,6 @@ function InvoiceModel(data) {
return false;
}
var itemModel = new ItemModel();
@if ($account->hide_quantity)
itemModel.qty(1);
@endif
if (isTask) {
itemModel.invoice_item_type_id({{ INVOICE_ITEM_TYPE_TASK }});
self.invoice_items_with_tasks.push(itemModel);
@ -903,7 +900,7 @@ function ItemModel(data) {
}
this.isEmpty = function() {
return !self.product_key() && !self.notes() && !self.cost() && (!self.qty() || {{ $account->hide_quantity ? 'true' : 'false' }});
return !self.product_key() && !self.notes() && !self.cost() && !self.qty();
}
this.onSelect = function() {}