mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-18 04:24:36 -04:00
Line item discounts
This commit is contained in:
parent
15b5860ffe
commit
2f6de520ec
@ -543,6 +543,15 @@ class InvoiceRepository extends BaseRepository
|
|||||||
$invoiceItemQty = Utils::roundSignificant(Utils::parseFloat($item['qty']));
|
$invoiceItemQty = Utils::roundSignificant(Utils::parseFloat($item['qty']));
|
||||||
|
|
||||||
$lineTotal = $invoiceItemCost * $invoiceItemQty;
|
$lineTotal = $invoiceItemCost * $invoiceItemQty;
|
||||||
|
|
||||||
|
if (! empty($item['discount']) && $discount = Utils::parseFloat($item['discount'])) {
|
||||||
|
if ($invoice->is_amount_discount) {
|
||||||
|
$lineTotal -= $discount;
|
||||||
|
} else {
|
||||||
|
$lineTotal -= $lineTotal * $discount / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$total += round($lineTotal, 2);
|
$total += round($lineTotal, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -552,6 +561,14 @@ class InvoiceRepository extends BaseRepository
|
|||||||
$invoiceItemQty = Utils::roundSignificant(Utils::parseFloat($item['qty']));
|
$invoiceItemQty = Utils::roundSignificant(Utils::parseFloat($item['qty']));
|
||||||
$lineTotal = $invoiceItemCost * $invoiceItemQty;
|
$lineTotal = $invoiceItemCost * $invoiceItemQty;
|
||||||
|
|
||||||
|
if (! empty($item['discount']) && $discount = Utils::parseFloat($item['discount'])) {
|
||||||
|
if ($invoice->is_amount_discount) {
|
||||||
|
$lineTotal -= $discount;
|
||||||
|
} else {
|
||||||
|
$lineTotal -= round($lineTotal * $discount / 100, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($invoice->discount > 0) {
|
if ($invoice->discount > 0) {
|
||||||
if ($invoice->is_amount_discount) {
|
if ($invoice->is_amount_discount) {
|
||||||
if ($total != 0) {
|
if ($total != 0) {
|
||||||
|
@ -23,6 +23,7 @@ class InvoiceItemTransformer extends EntityTransformer
|
|||||||
'invoice_item_type_id' => (int) $item->invoice_item_type_id,
|
'invoice_item_type_id' => (int) $item->invoice_item_type_id,
|
||||||
'custom_value1' => $item->custom_value1,
|
'custom_value1' => $item->custom_value1,
|
||||||
'custom_value2' => $item->custom_value2,
|
'custom_value2' => $item->custom_value2,
|
||||||
|
'discount' => (float) $item->discount,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -153,6 +153,7 @@ function GetPdfMake(invoice, javascript, callback) {
|
|||||||
|
|
||||||
// support setting noWrap as a style
|
// support setting noWrap as a style
|
||||||
dd.styles.noWrap = {'noWrap': true};
|
dd.styles.noWrap = {'noWrap': true};
|
||||||
|
dd.styles.discount = {'alignment': 'right'};
|
||||||
|
|
||||||
// set page size
|
// set page size
|
||||||
dd.pageSize = invoice.account.page_size;
|
dd.pageSize = invoice.account.page_size;
|
||||||
@ -560,6 +561,7 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
|
|||||||
'product.rate',
|
'product.rate',
|
||||||
'product.tax',
|
'product.tax',
|
||||||
'product.line_total',
|
'product.line_total',
|
||||||
|
'product.discount',
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isSecondTable) {
|
if (isSecondTable) {
|
||||||
@ -611,6 +613,7 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
|
|||||||
var item = invoice.invoice_items[i];
|
var item = invoice.invoice_items[i];
|
||||||
var cost = NINJA.parseFloat(item.cost) ? formatMoneyInvoice(NINJA.parseFloat(item.cost), invoice, null, getPrecision(NINJA.parseFloat(item.cost))) : ' ';
|
var cost = NINJA.parseFloat(item.cost) ? formatMoneyInvoice(NINJA.parseFloat(item.cost), invoice, null, getPrecision(NINJA.parseFloat(item.cost))) : ' ';
|
||||||
var qty = NINJA.parseFloat(item.qty) ? roundSignificant(NINJA.parseFloat(item.qty)) + '' : ' ';
|
var qty = NINJA.parseFloat(item.qty) ? roundSignificant(NINJA.parseFloat(item.qty)) + '' : ' ';
|
||||||
|
var discount = NINJA.parseFloat(item.discount);
|
||||||
var notes = item.notes;
|
var notes = item.notes;
|
||||||
var productKey = item.product_key;
|
var productKey = item.product_key;
|
||||||
var tax1 = '';
|
var tax1 = '';
|
||||||
@ -651,6 +654,15 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var lineTotal = roundSignificant(NINJA.parseFloat(item.cost) * NINJA.parseFloat(item.qty));
|
var lineTotal = roundSignificant(NINJA.parseFloat(item.cost) * NINJA.parseFloat(item.qty));
|
||||||
|
|
||||||
|
if (discount != 0) {
|
||||||
|
if (parseInt(invoice.is_amount_discount)) {
|
||||||
|
lineTotal -= discount;
|
||||||
|
} else {
|
||||||
|
lineTotal -= (lineTotal * discount / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (account.include_item_taxes_inline == '1') {
|
if (account.include_item_taxes_inline == '1') {
|
||||||
var taxAmount1 = 0;
|
var taxAmount1 = 0;
|
||||||
var taxAmount2 = 0;
|
var taxAmount2 = 0;
|
||||||
@ -699,6 +711,12 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
|
|||||||
if (field == 'hours') {
|
if (field == 'hours') {
|
||||||
styles.push('cost');
|
styles.push('cost');
|
||||||
}
|
}
|
||||||
|
} else if (field == 'discount') {
|
||||||
|
if (parseInt(invoice.is_amount_discount)) {
|
||||||
|
value = roundSignificant(discount, true);
|
||||||
|
} else {
|
||||||
|
value = discount + '%';
|
||||||
|
}
|
||||||
} else if (field == 'tax') {
|
} else if (field == 'tax') {
|
||||||
value = ' ';
|
value = ' ';
|
||||||
if (item.tax_name1) {
|
if (item.tax_name1) {
|
||||||
|
@ -575,7 +575,19 @@ function calculateAmounts(invoice) {
|
|||||||
// sum line item
|
// sum line item
|
||||||
for (var i=0; i<invoice.invoice_items.length; i++) {
|
for (var i=0; i<invoice.invoice_items.length; i++) {
|
||||||
var item = invoice.invoice_items[i];
|
var item = invoice.invoice_items[i];
|
||||||
var lineTotal = invoice.is_statement ? roundToTwo(NINJA.parseFloat(item.balance)) : roundSignificant(NINJA.parseFloat(item.cost) * NINJA.parseFloat(item.qty));
|
if (invoice.is_statement) {
|
||||||
|
var lineTotal = roundToTwo(NINJA.parseFloat(item.balance));
|
||||||
|
} else {
|
||||||
|
var lineTotal = roundSignificant(NINJA.parseFloat(item.cost) * NINJA.parseFloat(item.qty));
|
||||||
|
var discount = NINJA.parseFloat(item.discount);
|
||||||
|
if (discount != 0) {
|
||||||
|
if (parseInt(invoice.is_amount_discount)) {
|
||||||
|
lineTotal -= discount;
|
||||||
|
} else {
|
||||||
|
lineTotal -= (lineTotal * discount / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
lineTotal = roundToTwo(lineTotal);
|
lineTotal = roundToTwo(lineTotal);
|
||||||
if (lineTotal) {
|
if (lineTotal) {
|
||||||
total += lineTotal;
|
total += lineTotal;
|
||||||
@ -623,6 +635,16 @@ function calculateAmounts(invoice) {
|
|||||||
|
|
||||||
// calculate line item tax
|
// calculate line item tax
|
||||||
var lineTotal = roundSignificant(NINJA.parseFloat(item.cost) * NINJA.parseFloat(item.qty));
|
var lineTotal = roundSignificant(NINJA.parseFloat(item.cost) * NINJA.parseFloat(item.qty));
|
||||||
|
var discount = NINJA.parseFloat(item.discount);
|
||||||
|
if (discount != 0) {
|
||||||
|
if (parseInt(invoice.is_amount_discount)) {
|
||||||
|
lineTotal -= discount;
|
||||||
|
} else {
|
||||||
|
lineTotal -= (lineTotal * discount / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineTotal = roundToTwo(lineTotal);
|
||||||
|
|
||||||
if (invoice.discount != 0) {
|
if (invoice.discount != 0) {
|
||||||
if (parseInt(invoice.is_amount_discount)) {
|
if (parseInt(invoice.is_amount_discount)) {
|
||||||
lineTotal -= roundToTwo((lineTotal/total) * invoice.discount);
|
lineTotal -= roundToTwo((lineTotal/total) * invoice.discount);
|
||||||
|
@ -1203,7 +1203,6 @@
|
|||||||
var invoice = createInvoiceModel();
|
var invoice = createInvoiceModel();
|
||||||
var design = getDesignJavascript();
|
var design = getDesignJavascript();
|
||||||
|
|
||||||
/*
|
|
||||||
@if ($invoice->exists)
|
@if ($invoice->exists)
|
||||||
if (! checkedInvoiceBalances) {
|
if (! checkedInvoiceBalances) {
|
||||||
checkedInvoiceBalances = true;
|
checkedInvoiceBalances = true;
|
||||||
@ -1218,7 +1217,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
*/
|
|
||||||
|
|
||||||
@if ( ! $account->live_preview)
|
@if ( ! $account->live_preview)
|
||||||
return;
|
return;
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div id="scrollable-dropdown-menu">
|
<div id="scrollable-dropdown-menu">
|
||||||
<input id="product_key" type="text" data-bind="productTypeahead: product_key, items: $root.products, key: 'product_key', valueUpdate: 'afterkeydown', attr: {name: 'invoice_items[{{ $isTasks ? 'T' : '' }}' + $index() + '][product_key]'}" class="form-control invoice-item handled"/>
|
<input type="text" data-bind="productTypeahead: product_key, items: $root.products, key: 'product_key', valueUpdate: 'afterkeydown', attr: {name: 'invoice_items[{{ $isTasks ? 'T' : '' }}' + $index() + '][product_key]'}" class="form-control invoice-item handled"/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
|
@ -897,6 +897,14 @@ function ItemModel(data) {
|
|||||||
|
|
||||||
this.totals.rawTotal = ko.computed(function() {
|
this.totals.rawTotal = ko.computed(function() {
|
||||||
var value = roundSignificant(NINJA.parseFloat(self.cost()) * NINJA.parseFloat(self.qty()));
|
var value = roundSignificant(NINJA.parseFloat(self.cost()) * NINJA.parseFloat(self.qty()));
|
||||||
|
if (self.discount()) {
|
||||||
|
var discount = NINJA.parseFloat(self.discount());
|
||||||
|
if (parseInt(model.invoice().is_amount_discount())) {
|
||||||
|
value -= discount;
|
||||||
|
} else {
|
||||||
|
value -= (value * discount / 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
return value ? roundToTwo(value) : 0;
|
return value ? roundToTwo(value) : 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
0
tests/acceptance/DiscountCest.php
Normal file
0
tests/acceptance/DiscountCest.php
Normal file
Loading…
x
Reference in New Issue
Block a user