diff --git a/app/Constants.php b/app/Constants.php
index 81c6785b12c6..bd48656cd5fe 100644
--- a/app/Constants.php
+++ b/app/Constants.php
@@ -556,6 +556,8 @@ if (! defined('APP_NAME')) {
define('INVOICE_FIELDS_CLIENT', 'client_fields');
define('INVOICE_FIELDS_INVOICE', 'invoice_fields');
define('INVOICE_FIELDS_ACCOUNT', 'account_fields');
+ define('INVOICE_FIELDS_PRODUCT', 'product_fields');
+ define('INVOICE_FIELDS_TASK', 'task_fields');
$creditCards = [
1 => ['card' => 'images/credit_cards/Test-Visa-Icon.png', 'text' => 'Visa'],
diff --git a/app/Models/Traits/PresentsInvoice.php b/app/Models/Traits/PresentsInvoice.php
index 53647cf9675a..1eb4e3d785b5 100644
--- a/app/Models/Traits/PresentsInvoice.php
+++ b/app/Models/Traits/PresentsInvoice.php
@@ -12,6 +12,29 @@ trait PresentsInvoice
if ($this->invoice_fields) {
$fields = json_decode($this->invoice_fields, true);
+ if (! isset($fields['product_fields'])) {
+ $fields['product_fields'] = [
+ 'product.item',
+ 'product.description',
+ 'product.custom_value1',
+ 'product.custom_value2',
+ 'product.unit_cost',
+ 'product.quantity',
+ 'product.tax',
+ 'product.line_total',
+ ];
+ $fields['task_fields'] = [
+ 'product.service',
+ 'product.description',
+ 'product.custom_value1',
+ 'product.custom_value2',
+ 'product.rate',
+ 'product.hours',
+ 'product.tax',
+ 'product.line_total',
+ ];
+ }
+
return $this->applyLabels($fields);
} else {
return $this->getDefaultInvoiceFields();
@@ -54,6 +77,26 @@ trait PresentsInvoice
'account.city_state_postal',
'account.country',
],
+ 'product_fields' => [
+ 'product.item',
+ 'product.description',
+ 'product.custom_value1',
+ 'product.custom_value2',
+ 'product.unit_cost',
+ 'product.quantity',
+ 'product.tax',
+ 'product.line_total',
+ ],
+ 'task_fields' => [
+ 'product.service',
+ 'product.description',
+ 'product.custom_value1',
+ 'product.custom_value2',
+ 'product.rate',
+ 'product.hours',
+ 'product.tax',
+ 'product.line_total',
+ ]
];
if ($this->custom_invoice_text_label1) {
@@ -136,6 +179,26 @@ trait PresentsInvoice
'account.custom_value2',
'.blank',
],
+ INVOICE_FIELDS_PRODUCT => [
+ 'product.item',
+ 'product.description',
+ 'product.custom_value1',
+ 'product.custom_value2',
+ 'product.unit_cost',
+ 'product.quantity',
+ 'product.tax',
+ 'product.line_total',
+ ],
+ INVOICE_FIELDS_TASK => [
+ 'product.service',
+ 'product.description',
+ 'product.custom_value1',
+ 'product.custom_value2',
+ 'product.rate',
+ 'product.hours',
+ 'product.tax',
+ 'product.line_total',
+ ],
];
return $this->applyLabels($fields);
@@ -264,6 +327,10 @@ trait PresentsInvoice
'invoice_due_date',
'quote_due_date',
'service',
+ 'product_key',
+ 'unit_cost',
+ 'tax1',
+ 'tax2',
];
foreach ($fields as $field) {
@@ -289,6 +356,8 @@ trait PresentsInvoice
'client.custom_value2' => 'custom_client_label2',
'contact.custom_value1' => 'custom_contact_label1',
'contact.custom_value2' => 'custom_contact_label2',
+ 'product.custom_value1' => 'custom_invoice_item_label1',
+ 'product.custom_value2' => 'custom_invoice_item_label2',
] as $field => $property) {
$data[$field] = e($this->$property) ?: trans('texts.custom_field');
}
diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php
index 61ea182ec90b..3340c8b0ad3f 100644
--- a/resources/lang/en/texts.php
+++ b/resources/lang/en/texts.php
@@ -2508,6 +2508,8 @@ $LANG = array(
'return_to_invoice' => 'Return to Invoice',
'gateway_help_13' => 'To use ITN leave the PDT Key field blank.',
'partial_due_date' => 'Partial Due Date',
+ 'task_fields' => 'Task Fields',
+ 'product_fields_help' => 'Drag and drop fields to change their order',
);
diff --git a/resources/views/accounts/invoice_design.blade.php b/resources/views/accounts/invoice_design.blade.php
index 4536b52af9f5..cffac1f44e76 100644
--- a/resources/views/accounts/invoice_design.blade.php
+++ b/resources/views/accounts/invoice_design.blade.php
@@ -102,7 +102,6 @@
var id = $select.val();
$select.val(null).blur();
$('.' + id + '-label-group').fadeIn();
- console.log(id);
}
$(function() {
@@ -166,8 +165,8 @@
{{ trans('texts.general_settings') }}
{{ trans('texts.invoice_labels') }}
{{ trans('texts.invoice_fields') }}
+ {{ trans('texts.product_fields') }}
{{ trans('texts.invoice_options') }}
- {{ trans('texts.header_footer') }}
@@ -242,7 +241,7 @@
-
+
@include('accounts.partials.invoice_fields_selector', ['section' => 'invoice_fields', 'fields' => INVOICE_FIELDS_INVOICE])
@include('accounts.partials.invoice_fields_selector', ['section' => 'client_fields', 'fields' => INVOICE_FIELDS_CLIENT])
@include('accounts.partials.invoice_fields_selector', ['section' => 'account_fields1', 'fields' => INVOICE_FIELDS_ACCOUNT])
@@ -250,43 +249,61 @@
- {{ trans('texts.invoice_fields_help') }}
+ {{ trans('texts.invoice_fields_help') }}
-
- {!! Button::normal(trans('texts.reset'))
+
+ {!! Button::normal(trans('texts.reset'))->small()
->withAttributes(['onclick' => 'sweetConfirm(function() {
resetFields();
- })'])
- ->small() !!}
+ })']) !!}
+
+
+
+ @include('accounts.partials.invoice_fields_selector', ['section' => 'product_fields', 'fields' => INVOICE_FIELDS_PRODUCT, 'colWidth' => 6])
+ @include('accounts.partials.invoice_fields_selector', ['section' => 'task_fields', 'fields' => INVOICE_FIELDS_TASK, 'colWidth' => 6])
+
+
+
+ {{ trans('texts.product_fields_help') }}
+
+
+ {!! Button::normal(trans('texts.reset'))->small()
+ ->withAttributes(['onclick' => 'sweetConfirm(function() {
+ resetFields();
+ })']) !!}
+
+
+
+
+
+
{!! 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) !!}
-
-
-
diff --git a/resources/views/accounts/partials/invoice_fields.blade.php b/resources/views/accounts/partials/invoice_fields.blade.php
index afc33185561f..9db90dacd11d 100644
--- a/resources/views/accounts/partials/invoice_fields.blade.php
+++ b/resources/views/accounts/partials/invoice_fields.blade.php
@@ -7,6 +7,8 @@ function ViewModel(data) {
self.client_fields = ko.observableArray();
self.account_fields1 = ko.observableArray();
self.account_fields2 = ko.observableArray();
+ self.product_fields = ko.observableArray();
+ self.task_fields = ko.observableArray();
window.field_map = [];
self.addField = function(section, field, label) {
@@ -20,6 +22,8 @@ function ViewModel(data) {
self.client_fields.removeAll();
self.account_fields1.removeAll();
self.account_fields2.removeAll();
+ self.product_fields.removeAll();
+ self.task_fields.removeAll();
}
self.onChange = function() {
@@ -29,17 +33,28 @@ function ViewModel(data) {
}
self.updateSelects = function() {
- var usedFields = [].concat(self.invoice_fields(), self.client_fields(), self.account_fields1(), self.account_fields2());
+ var usedFields = [].concat(
+ self.invoice_fields(),
+ self.client_fields(),
+ self.account_fields1(),
+ self.account_fields2());
var selects = [
'invoice_fields',
'client_fields',
'account_fields1',
'account_fields2',
+ 'product_fields',
+ 'task_fields',
];
for (var i=0; i
option').each(function() {
+ if (select == 'product_fields') {
+ usedFields = self.product_fields();
+ } else if (select == 'task_fields') {
+ usedFields = self.task_fields();
+ }
var isUsed = usedFields.indexOf(this.value) >= 0;
$(this).css('color', isUsed ? '#888' : 'black');
});
@@ -66,6 +81,14 @@ function ViewModel(data) {
self.account_fields2.remove(item);
self.onChange();
}
+ self.removeProductFields = function(item) {
+ self.product_fields.remove(item);
+ self.onChange();
+ }
+ self.removeTaskFields = function(item) {
+ self.task_fields.remove(item);
+ self.onChange();
+ }
}
function addField(section) {
diff --git a/resources/views/accounts/partials/invoice_fields_selector.blade.php b/resources/views/accounts/partials/invoice_fields_selector.blade.php
index ac9dcb6b39e8..297fcba44613 100644
--- a/resources/views/accounts/partials/invoice_fields_selector.blade.php
+++ b/resources/views/accounts/partials/invoice_fields_selector.blade.php
@@ -1,4 +1,4 @@
-
+
{!! Former::select("{$section}_select")
->placeholder(trans("texts.{$fields}"))