From db53a789be480aace3ea05850ba60cbb7d3a3983 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Fri, 31 Jul 2015 16:53:13 +0530 Subject: [PATCH 1/3] [fix] Tax calculation while discount applied on net total --- erpnext/controllers/taxes_and_totals.py | 6 +++--- erpnext/public/js/controllers/taxes_and_totals.js | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index 6b59cea00d..d526f66baf 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -219,7 +219,7 @@ class calculate_taxes_and_totals(object): # adjust Discount Amount loss in last tax iteration if i == (len(self.doc.get("taxes")) - 1) and self.discount_amount_applied \ - and self.doc.discount_amount: + and self.doc.discount_amount and self.doc.apply_discount_on == "Grand Total": self.adjust_discount_amount_loss(tax) @@ -303,9 +303,9 @@ class calculate_taxes_and_totals(object): for tax in self.doc.get("taxes"): if tax.category in ["Valuation and Total", "Total"]: if tax.add_deduct_tax == "Add": - self.doc.taxes_and_charges_added += flt(tax.tax_amount) + self.doc.taxes_and_charges_added += flt(tax.tax_amount_after_discount_amount) else: - self.doc.taxes_and_charges_deducted += flt(tax.tax_amount) + self.doc.taxes_and_charges_deducted += flt(tax.tax_amount_after_discount_amount) self.doc.round_floats_in(self.doc, ["taxes_and_charges_added", "taxes_and_charges_deducted"]) diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 1e238d6934..0b3ca7f2a8 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -256,7 +256,8 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ me.round_off_totals(tax); // adjust Discount Amount loss in last tax iteration - if ((i == me.frm.doc["taxes"].length - 1) && me.discount_amount_applied && me.frm.doc.apply_discount_on == "Grand Total") + if ((i == me.frm.doc["taxes"].length - 1) && me.discount_amount_applied + && me.frm.doc.apply_discount_on == "Grand Total" && me.frm.doc.discount_amount) me.adjust_discount_amount_loss(tax); } }); @@ -365,9 +366,9 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({ $.each(this.frm.doc["taxes"] || [], function(i, tax) { if (in_list(["Valuation and Total", "Total"], tax.category)) { if(tax.add_deduct_tax == "Add") { - me.frm.doc.taxes_and_charges_added += flt(tax.tax_amount); + me.frm.doc.taxes_and_charges_added += flt(tax.tax_amount_after_discount_amount); } else { - me.frm.doc.taxes_and_charges_deducted += flt(tax.tax_amount); + me.frm.doc.taxes_and_charges_deducted += flt(tax.tax_amount_after_discount_amount); } } }) From 1db0b6de0c98f91396026da479f49de06d093555 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 3 Aug 2015 15:37:41 +0530 Subject: [PATCH 2/3] Patch to notify system managers if there are any wrong entries due to bug related to discount amount on net total --- erpnext/patches.txt | 3 +- ...anagers_regarding_wrong_tax_calculation.py | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 78e1609990..de26ff3f71 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -184,4 +184,5 @@ execute:frappe.delete_doc("Module Def", "Contacts") erpnext.patches.v5_4.fix_reserved_qty_and_sle_for_packed_items # 30-07-2015 execute:frappe.reload_doctype("Leave Type") execute:frappe.db.sql("update `tabLeave Type` set include_holiday=0") -erpnext.patches.v5_4.set_root_and_report_type \ No newline at end of file +erpnext.patches.v5_4.set_root_and_report_type +erpnext.patches.v5_4.notify_system_managers_regarding_wrong_tax_calculation diff --git a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py new file mode 100644 index 0000000000..377eb31b7b --- /dev/null +++ b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py @@ -0,0 +1,39 @@ +# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe +from frappe.email import sendmail_to_system_managers +from frappe.utils import get_url_to_form + +def execute(): + wrong_records = [] + for dt in ("Quotation", "Sales Order", "Delivery Note", "Sales Invoice", + "Purchase Order", "Purchase Receipt", "Purchase Invoice"): + records = frappe.db.sql_list("""select name from `tab{0}` + where apply_discount_on = 'Net Total' and ifnull(discount_amount, 0) != 0 + and modified > '2015-02-17' and docstatus=1""".format(dt)) + + if records: + records = [get_url_to_form(dt, d) for d in records] + wrong_records.append([dt, records]) + + if wrong_records: + content = """Dear System Manager, + +Due to an error related to Discount Amount on Net Total, tax calculation might be wrong in the following records. We did not fix the tax amount automatically because it can corrupt the entries, so we request you to check these records and amend if you found the calculation wrong. + +Please check following Entries: + +%s + + +Regards, + +Administrator""" % "\n".join([(d[0] + ": " + ", ".join(d[1])) for d in wrong_records]) + + sendmail_to_system_managers("[Important] [ERPNext] Tax calculation might be wrong, please check.", content) + + print "="*50 + print content + print "="*50 \ No newline at end of file From 03bccb81d8aedf734ef49b1245a6b04f209ec6a6 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 3 Aug 2015 15:38:10 +0530 Subject: [PATCH 3/3] [test case] Test case for discount amount on net total --- .../sales_invoice/test_sales_invoice.py | 52 +++++++++++++++++++ ...anagers_regarding_wrong_tax_calculation.py | 2 +- 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 2e64f99dff..6c6737913e 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -790,6 +790,58 @@ class TestSalesInvoice(unittest.TestCase): set_perpetual_inventory(0) + def test_discount_on_net_total(self): + si = frappe.copy_doc(test_records[2]) + si.apply_discount_on = "Net Total" + si.discount_amount = 625 + si.insert() + + expected_values = { + "keys": ["price_list_rate", "discount_percentage", "rate", "amount", + "base_price_list_rate", "base_rate", "base_amount", + "net_rate", "base_net_rate", "net_amount", "base_net_amount"], + "_Test Item Home Desktop 100": [50, 0, 50, 500, 50, 50, 500, 25, 25, 250, 250], + "_Test Item Home Desktop 200": [150, 0, 150, 750, 150, 150, 750, 75, 75, 375, 375], + } + + # check if children are saved + self.assertEquals(len(si.get("items")), + len(expected_values)-1) + + # check if item values are calculated + for d in si.get("items"): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.get(k), expected_values[d.item_code][i]) + + # check net total + self.assertEquals(si.base_total, 1250) + self.assertEquals(si.total, 1250) + self.assertEquals(si.base_net_total, 625) + self.assertEquals(si.net_total, 625) + + # check tax calculation + expected_values = { + "keys": ["tax_amount", "tax_amount_after_discount_amount", + "base_tax_amount_after_discount_amount"], + "_Test Account Shipping Charges - _TC": [100, 100, 100], + "_Test Account Customs Duty - _TC": [62.5, 62.5, 62.5], + "_Test Account Excise Duty - _TC": [70, 70, 70], + "_Test Account Education Cess - _TC": [1.4, 1.4, 1.4], + "_Test Account S&H Education Cess - _TC": [.7, 0.7, 0.7], + "_Test Account CST - _TC": [17.2, 17.2, 17.2], + "_Test Account VAT - _TC": [78.13, 78.13, 78.13], + "_Test Account Discount - _TC": [-95.49, -95.49, -95.49] + } + + for d in si.get("taxes"): + for i, k in enumerate(expected_values["keys"]): + self.assertEquals(d.get(k), expected_values[d.account_head][i]) + + + self.assertEquals(si.total_taxes_and_charges, 234.44) + self.assertEquals(si.base_grand_total, 859.44) + self.assertEquals(si.grand_total, 859.44) + def create_sales_invoice(**args): si = frappe.new_doc("Sales Invoice") diff --git a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py index 377eb31b7b..8096a37a00 100644 --- a/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py +++ b/erpnext/patches/v5_4/notify_system_managers_regarding_wrong_tax_calculation.py @@ -12,7 +12,7 @@ def execute(): "Purchase Order", "Purchase Receipt", "Purchase Invoice"): records = frappe.db.sql_list("""select name from `tab{0}` where apply_discount_on = 'Net Total' and ifnull(discount_amount, 0) != 0 - and modified > '2015-02-17' and docstatus=1""".format(dt)) + and modified >= '2015-02-17' and docstatus=1""".format(dt)) if records: records = [get_url_to_form(dt, d) for d in records]