Skip to content

Commit

Permalink
fix(Quotation): calculate row values for alternative items (backport f…
Browse files Browse the repository at this point in the history
…rappe#43054) (frappe#43495)

Co-authored-by: Raffael Meyer <14891507+barredterra@users.noreply.github.com>
fix(Quotation): calculate row values for alternative items (frappe#43054)
  • Loading branch information
2 people authored and khalandarsihan committed Oct 6, 2024
1 parent 1a29ac6 commit 4503e20
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 9 deletions.
8 changes: 4 additions & 4 deletions erpnext/controllers/taxes_and_totals.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def filter_rows(self):
return items

def calculate(self):
if not len(self._items):
if not len(self.doc.items):
return

self.discount_amount_applied = False
Expand Down Expand Up @@ -95,7 +95,7 @@ def validate_item_tax_template(self):
if self.doc.get("is_return") and self.doc.get("return_against"):
return

for item in self._items:
for item in self.doc.items:
if item.item_code and item.get("item_tax_template"):
item_doc = frappe.get_cached_doc("Item", item.item_code)
args = {
Expand Down Expand Up @@ -154,7 +154,7 @@ def calculate_item_values(self):
return

if not self.discount_amount_applied:
for item in self._items:
for item in self.doc.items:
self.doc.round_floats_in(item)

if item.discount_percentage == 100:
Expand Down Expand Up @@ -258,7 +258,7 @@ def determine_exclusive_rate(self):
if not any(cint(tax.included_in_print_rate) for tax in self.doc.get("taxes")):
return

for item in self._items:
for item in self.doc.items:
item_tax_map = self._load_item_tax_rate(item.item_tax_rate)
cumulated_tax_fraction = 0
total_inclusive_tax_amount_per_qty = 0
Expand Down
6 changes: 3 additions & 3 deletions erpnext/public/js/controllers/taxes_and_totals.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
calculate_item_values() {
var me = this;
if (!this.discount_amount_applied) {
for (const item of this.frm._items || []) {
for (const item of this.frm.doc.items || []) {
frappe.model.round_floats_in(item);
item.net_rate = item.rate;
item.qty = item.qty === undefined ? (me.frm.doc.is_return ? -1 : 1) : item.qty;
Expand Down Expand Up @@ -227,7 +227,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
});
if(has_inclusive_tax==false) return;

$.each(me.frm._items || [], function(n, item) {
$.each(this.frm.doc.items || [], function(n, item) {
var item_tax_map = me._load_item_tax_rate(item.item_tax_rate);
var cumulated_tax_fraction = 0.0;
var total_inclusive_tax_amount_per_qty = 0;
Expand Down Expand Up @@ -630,7 +630,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {

_cleanup() {
this.frm.doc.base_in_words = this.frm.doc.in_words = "";
let items = this.frm._items;
let items = this.frm.doc.items;

if(items && items.length) {
if(!frappe.meta.get_docfield(items[0].doctype, "item_tax_amount", this.frm.doctype)) {
Expand Down
42 changes: 40 additions & 2 deletions erpnext/selling/doctype/quotation/test_quotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,12 +561,50 @@ def test_alternative_items_with_service_items(self):
"description": "VAT",
"doctype": "Sales Taxes and Charges",
"rate": 10,
"included_in_print_rate": 1,
},
)
quotation.submit()

self.assertEqual(quotation.net_total, 290)
self.assertEqual(quotation.grand_total, 319)
self.assertEqual(round(quotation.items[1].net_rate, 2), 136.36)
self.assertEqual(round(quotation.items[1].amount, 2), 150)

self.assertEqual(round(quotation.items[2].net_rate, 2), 163.64)
self.assertEqual(round(quotation.items[2].amount, 2), 180)

self.assertEqual(round(quotation.net_total, 2), 263.64)
self.assertEqual(round(quotation.total_taxes_and_charges, 2), 26.36)
self.assertEqual(quotation.grand_total, 290)

def test_amount_calculation_for_alternative_items(self):
"""Make sure that the amount is calculated correctly for alternative items when the qty is changed."""
from erpnext.stock.doctype.item.test_item import make_item

item_list = []
stock_items = {
"_Test Simple Item 1": 100,
"_Test Alt 1": 120,
}

for item, rate in stock_items.items():
make_item(item, {"is_stock_item": 0})
item_list.append(
{
"item_code": item,
"qty": 1,
"rate": rate,
"is_alternative": "Alt" in item,
}
)

quotation = make_quotation(item_list=item_list, do_not_submit=1)

self.assertEqual(quotation.items[1].amount, 120)

quotation.items[1].qty = 2
quotation.save()

self.assertEqual(quotation.items[1].amount, 240)

def test_alternative_items_sales_order_mapping_with_stock_items(self):
from erpnext.selling.doctype.quotation.quotation import make_sales_order
Expand Down

0 comments on commit 4503e20

Please sign in to comment.