fix(pos): incorrect grand_total in case of inclusive taxes on item
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
index 0720d9b..f372dd6 100644
--- a/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/pos_invoice_merge_log.py
@@ -84,12 +84,21 @@
sales_invoice.set_posting_time = 1
sales_invoice.posting_date = getdate(self.posting_date)
sales_invoice.save()
+ self.write_off_fractional_amount(sales_invoice, data)
sales_invoice.submit()
self.consolidated_invoice = sales_invoice.name
return sales_invoice.name
+ def write_off_fractional_amount(self, invoice, data):
+ pos_invoice_grand_total = sum(d.grand_total for d in data)
+
+ if abs(pos_invoice_grand_total - invoice.grand_total) < 1:
+
+ invoice.write_off_amount += -1 * (pos_invoice_grand_total - invoice.grand_total)
+ invoice.save()
+
def process_merging_into_credit_note(self, data):
credit_note = self.get_new_sales_invoice()
credit_note.is_return = 1
@@ -102,6 +111,7 @@
# TODO: return could be against multiple sales invoice which could also have been consolidated?
# credit_note.return_against = self.consolidated_invoice
credit_note.save()
+ self.write_off_fractional_amount(credit_note, data)
credit_note.submit()
self.consolidated_credit_note = credit_note.name
@@ -135,9 +145,15 @@
i.uom == item.uom and i.net_rate == item.net_rate and i.warehouse == item.warehouse):
found = True
i.qty = i.qty + item.qty
+ i.amount = i.amount + item.net_amount
+ i.net_amount = i.amount
+ i.base_amount = i.base_amount + item.base_net_amount
+ i.base_net_amount = i.base_amount
if not found:
item.rate = item.net_rate
+ item.amount = item.net_amount
+ item.base_amount = item.base_net_amount
item.price_list_rate = 0
si_item = map_child_doc(item, invoice, {"doctype": "Sales Invoice Item"})
items.append(si_item)
@@ -169,10 +185,12 @@
found = True
if not found:
payments.append(payment)
- rounding_adjustment += doc.rounding_adjustment
- rounded_total += doc.rounded_total
- base_rounding_adjustment += doc.base_rounding_adjustment
- base_rounded_total += doc.base_rounded_total
+
+ if doc.rounding_adjustment or doc.base_rounding_adjustment:
+ rounding_adjustment += doc.rounding_adjustment
+ rounded_total += doc.rounded_total
+ base_rounding_adjustment += doc.base_rounding_adjustment
+ base_rounded_total += doc.base_rounded_total
if loyalty_points_sum:
diff --git a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py
index 3555da8..928d266 100644
--- a/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py
+++ b/erpnext/accounts/doctype/pos_invoice_merge_log/test_pos_invoice_merge_log.py
@@ -150,3 +150,118 @@
frappe.set_user("Administrator")
frappe.db.sql("delete from `tabPOS Profile`")
frappe.db.sql("delete from `tabPOS Invoice`")
+
+
+ def test_consolidation_round_off_error_1(self):
+ '''
+ Test case for bug:
+ Round off error in consolidated invoice creation if POS Invoice has inclusive tax
+ '''
+ frappe.db.sql("delete from `tabPOS Invoice`")
+
+ try:
+ init_user_and_profile()
+
+ inv = create_pos_invoice(qty=3, rate=10000, do_not_save=True)
+ inv.append("taxes", {
+ "account_head": "_Test Account VAT - _TC",
+ "charge_type": "On Net Total",
+ "cost_center": "_Test Cost Center - _TC",
+ "description": "VAT",
+ "doctype": "Sales Taxes and Charges",
+ "rate": 7.5,
+ "included_in_print_rate": 1
+ })
+ inv.append('payments', {
+ 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 30000
+ })
+ inv.insert()
+ inv.submit()
+
+ inv2 = create_pos_invoice(qty=3, rate=10000, do_not_save=True)
+ inv2.append("taxes", {
+ "account_head": "_Test Account VAT - _TC",
+ "charge_type": "On Net Total",
+ "cost_center": "_Test Cost Center - _TC",
+ "description": "VAT",
+ "doctype": "Sales Taxes and Charges",
+ "rate": 7.5,
+ "included_in_print_rate": 1
+ })
+ inv2.append('payments', {
+ 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 30000
+ })
+ inv2.insert()
+ inv2.submit()
+
+ consolidate_pos_invoices()
+
+ inv.load_from_db()
+ consolidated_invoice = frappe.get_doc('Sales Invoice', inv.consolidated_invoice)
+ self.assertEqual(consolidated_invoice.outstanding_amount, 0)
+ self.assertEqual(consolidated_invoice.status, 'Paid')
+
+ finally:
+ frappe.set_user("Administrator")
+ frappe.db.sql("delete from `tabPOS Profile`")
+ frappe.db.sql("delete from `tabPOS Invoice`")
+
+ def test_consolidation_round_off_error_2(self):
+ '''
+ Test the same case as above but with an Unpaid POS Invoice
+ '''
+ frappe.db.sql("delete from `tabPOS Invoice`")
+
+ try:
+ init_user_and_profile()
+
+ inv = create_pos_invoice(qty=6, rate=10000, do_not_save=True)
+ inv.append("taxes", {
+ "account_head": "_Test Account VAT - _TC",
+ "charge_type": "On Net Total",
+ "cost_center": "_Test Cost Center - _TC",
+ "description": "VAT",
+ "doctype": "Sales Taxes and Charges",
+ "rate": 7.5,
+ "included_in_print_rate": 1
+ })
+ inv.append('payments', {
+ 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 60000
+ })
+ inv.insert()
+ inv.submit()
+
+ inv2 = create_pos_invoice(qty=6, rate=10000, do_not_save=True)
+ inv2.append("taxes", {
+ "account_head": "_Test Account VAT - _TC",
+ "charge_type": "On Net Total",
+ "cost_center": "_Test Cost Center - _TC",
+ "description": "VAT",
+ "doctype": "Sales Taxes and Charges",
+ "rate": 7.5,
+ "included_in_print_rate": 1
+ })
+ inv2.append('payments', {
+ 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 60000
+ })
+ inv2.insert()
+ inv2.submit()
+
+ inv3 = create_pos_invoice(qty=3, rate=600, do_not_save=True)
+ inv3.append('payments', {
+ 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 1000
+ })
+ inv3.insert()
+ inv3.submit()
+
+ consolidate_pos_invoices()
+
+ inv.load_from_db()
+ consolidated_invoice = frappe.get_doc('Sales Invoice', inv.consolidated_invoice)
+ self.assertEqual(consolidated_invoice.outstanding_amount, 800)
+ self.assertEqual(consolidated_invoice.status, 'Unpaid')
+
+ finally:
+ frappe.set_user("Administrator")
+ frappe.db.sql("delete from `tabPOS Profile`")
+ frappe.db.sql("delete from `tabPOS Invoice`")
diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py
index 075e3e3..5d1856c 100644
--- a/erpnext/controllers/taxes_and_totals.py
+++ b/erpnext/controllers/taxes_and_totals.py
@@ -106,6 +106,9 @@
self.doc.conversion_rate = flt(self.doc.conversion_rate)
def calculate_item_values(self):
+ if self.doc.get('is_consolidated'):
+ return
+
if not self.discount_amount_applied:
for item in self.doc.get("items"):
self.doc.round_floats_in(item)