mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-04 02:44:35 -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']));
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
@ -552,6 +561,14 @@ class InvoiceRepository extends BaseRepository
|
||||
$invoiceItemQty = Utils::roundSignificant(Utils::parseFloat($item['qty']));
|
||||
$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->is_amount_discount) {
|
||||
if ($total != 0) {
|
||||
|
@ -23,6 +23,7 @@ class InvoiceItemTransformer extends EntityTransformer
|
||||
'invoice_item_type_id' => (int) $item->invoice_item_type_id,
|
||||
'custom_value1' => $item->custom_value1,
|
||||
'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
|
||||
dd.styles.noWrap = {'noWrap': true};
|
||||
dd.styles.discount = {'alignment': 'right'};
|
||||
|
||||
// set page size
|
||||
dd.pageSize = invoice.account.page_size;
|
||||
@ -560,6 +561,7 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
|
||||
'product.rate',
|
||||
'product.tax',
|
||||
'product.line_total',
|
||||
'product.discount',
|
||||
];
|
||||
|
||||
if (isSecondTable) {
|
||||
@ -611,6 +613,7 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
|
||||
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 qty = NINJA.parseFloat(item.qty) ? roundSignificant(NINJA.parseFloat(item.qty)) + '' : ' ';
|
||||
var discount = NINJA.parseFloat(item.discount);
|
||||
var notes = item.notes;
|
||||
var productKey = item.product_key;
|
||||
var tax1 = '';
|
||||
@ -651,6 +654,15 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
|
||||
}
|
||||
|
||||
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') {
|
||||
var taxAmount1 = 0;
|
||||
var taxAmount2 = 0;
|
||||
@ -699,6 +711,12 @@ NINJA.invoiceLines = function(invoice, isSecondTable) {
|
||||
if (field == 'hours') {
|
||||
styles.push('cost');
|
||||
}
|
||||
} else if (field == 'discount') {
|
||||
if (parseInt(invoice.is_amount_discount)) {
|
||||
value = roundSignificant(discount, true);
|
||||
} else {
|
||||
value = discount + '%';
|
||||
}
|
||||
} else if (field == 'tax') {
|
||||
value = ' ';
|
||||
if (item.tax_name1) {
|
||||
|
@ -575,7 +575,19 @@ function calculateAmounts(invoice) {
|
||||
// sum line item
|
||||
for (var i=0; i<invoice.invoice_items.length; 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);
|
||||
if (lineTotal) {
|
||||
total += lineTotal;
|
||||
@ -623,6 +635,16 @@ function calculateAmounts(invoice) {
|
||||
|
||||
// calculate line item tax
|
||||
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 (parseInt(invoice.is_amount_discount)) {
|
||||
lineTotal -= roundToTwo((lineTotal/total) * invoice.discount);
|
||||
|
@ -1203,7 +1203,6 @@
|
||||
var invoice = createInvoiceModel();
|
||||
var design = getDesignJavascript();
|
||||
|
||||
/*
|
||||
@if ($invoice->exists)
|
||||
if (! checkedInvoiceBalances) {
|
||||
checkedInvoiceBalances = true;
|
||||
@ -1218,7 +1217,6 @@
|
||||
}
|
||||
}
|
||||
@endif
|
||||
*/
|
||||
|
||||
@if ( ! $account->live_preview)
|
||||
return;
|
||||
|
@ -32,7 +32,7 @@
|
||||
</td>
|
||||
<td>
|
||||
<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>
|
||||
</td>
|
||||
<td>
|
||||
|
@ -897,6 +897,14 @@ function ItemModel(data) {
|
||||
|
||||
this.totals.rawTotal = ko.computed(function() {
|
||||
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;
|
||||
});
|
||||
|
||||
|
0
tests/acceptance/DiscountCest.php
Normal file
0
tests/acceptance/DiscountCest.php
Normal file
Loading…
x
Reference in New Issue
Block a user