From cf34219c71a0e7b6c2921fecc5d62b9d76ea8807 Mon Sep 17 00:00:00 2001 From: Dany Robert Date: Mon, 29 Jan 2024 09:32:44 +0530 Subject: [PATCH 1/4] fix: specify precision for net_amount (#39481) * fix: specify precision for net_amount * fix: correct existing test to account for precision * fix: rounding issue in test cases * fix: optional grand total manipulation * fix: use `grand_total_diff` for manipulation * fix: patch to set default for grand total manipulation * fix: wrong rounding assertion for USD * fix: undefined this.frm error * chore: linters * fix: `net_amount` percision and method rename * fix: missing frm reference * chore: minor cleanups and depr message * refactor: remove optional adjusting of grand total (cherry picked from commit 50d56db0c2ffcbb5ac466e0b8f1b7330dc78c9b3) # Conflicts: # erpnext/public/js/controllers/accounts.js # erpnext/public/js/controllers/taxes_and_totals.js --- .../accounts_settings/accounts_settings.json | 2 +- .../doctype/pos_invoice/test_pos_invoice.py | 2 +- .../test_pos_invoice_merge_log.py | 2 +- .../sales_invoice/test_sales_invoice.py | 65 +++++++++++-------- erpnext/controllers/taxes_and_totals.py | 24 +++++-- erpnext/public/js/controllers/accounts.js | 40 ++++++++++++ .../public/js/controllers/taxes_and_totals.js | 32 +++++++-- 7 files changed, 122 insertions(+), 45 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 0370fa2ce87..5581ab038c5 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -469,7 +469,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-11-20 09:37:47.650347", + "modified": "2024-01-22 12:10:10.151819", "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", diff --git a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py index 186c0ea7fd4..b44262cc280 100644 --- a/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py +++ b/erpnext/accounts/doctype/pos_invoice/test_pos_invoice.py @@ -87,7 +87,7 @@ class TestPOSInvoice(unittest.TestCase): inv.save() - self.assertEqual(inv.net_total, 4298.25) + self.assertEqual(inv.net_total, 4298.24) self.assertEqual(inv.grand_total, 4900.00) def test_tax_calculation_with_multiple_items(self): 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 144523624e8..5f5427c0764 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 @@ -340,7 +340,7 @@ class TestPOSInvoiceMergeLog(unittest.TestCase): inv.load_from_db() consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice) self.assertEqual(consolidated_invoice.status, "Return") - self.assertEqual(consolidated_invoice.rounding_adjustment, -0.001) + self.assertEqual(consolidated_invoice.rounding_adjustment, -0.002) finally: frappe.set_user("Administrator") diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index bb51223db16..0ff26ba4d74 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -307,7 +307,8 @@ class TestSalesInvoice(FrappeTestCase): si.insert() # with inclusive tax - self.assertEqual(si.items[0].net_amount, 3947.368421052631) + self.assertEqual(si.items[0].net_amount, 3947.37) + self.assertEqual(si.net_total, si.base_net_total) self.assertEqual(si.net_total, 3947.37) self.assertEqual(si.grand_total, 5000) @@ -651,7 +652,7 @@ class TestSalesInvoice(FrappeTestCase): 62.5, 625.0, 50, - 499.97600115194473, + 499.98, ], "_Test Item Home Desktop 200": [ 190.66, @@ -662,7 +663,7 @@ class TestSalesInvoice(FrappeTestCase): 190.66, 953.3, 150, - 749.9968530500239, + 750, ], } @@ -675,20 +676,21 @@ class TestSalesInvoice(FrappeTestCase): self.assertEqual(d.get(k), expected_values[d.item_code][i]) # check net total - self.assertEqual(si.net_total, 1249.97) + self.assertEqual(si.base_net_total, si.net_total) + self.assertEqual(si.net_total, 1249.98) self.assertEqual(si.total, 1578.3) # check tax calculation expected_values = { "keys": ["tax_amount", "total"], - "_Test Account Excise Duty - _TC": [140, 1389.97], - "_Test Account Education Cess - _TC": [2.8, 1392.77], - "_Test Account S&H Education Cess - _TC": [1.4, 1394.17], - "_Test Account CST - _TC": [27.88, 1422.05], - "_Test Account VAT - _TC": [156.25, 1578.30], - "_Test Account Customs Duty - _TC": [125, 1703.30], - "_Test Account Shipping Charges - _TC": [100, 1803.30], - "_Test Account Discount - _TC": [-180.33, 1622.97], + "_Test Account Excise Duty - _TC": [140, 1389.98], + "_Test Account Education Cess - _TC": [2.8, 1392.78], + "_Test Account S&H Education Cess - _TC": [1.4, 1394.18], + "_Test Account CST - _TC": [27.88, 1422.06], + "_Test Account VAT - _TC": [156.25, 1578.31], + "_Test Account Customs Duty - _TC": [125, 1703.31], + "_Test Account Shipping Charges - _TC": [100, 1803.31], + "_Test Account Discount - _TC": [-180.33, 1622.98], } for d in si.get("taxes"): @@ -724,7 +726,7 @@ class TestSalesInvoice(FrappeTestCase): "base_rate": 2500, "base_amount": 25000, "net_rate": 40, - "net_amount": 399.9808009215558, + "net_amount": 399.98, "base_net_rate": 2000, "base_net_amount": 19999, }, @@ -738,7 +740,7 @@ class TestSalesInvoice(FrappeTestCase): "base_rate": 7500, "base_amount": 37500, "net_rate": 118.01, - "net_amount": 590.0531205155963, + "net_amount": 590.05, "base_net_rate": 5900.5, "base_net_amount": 29502.5, }, @@ -776,8 +778,13 @@ class TestSalesInvoice(FrappeTestCase): self.assertEqual(si.base_grand_total, 60795) self.assertEqual(si.grand_total, 1215.90) - self.assertEqual(si.rounding_adjustment, 0.01) - self.assertEqual(si.base_rounding_adjustment, 0.50) + # no rounding adjustment as the Smallest Currency Fraction Value of USD is 0.01 + if frappe.db.get_value("Currency", "USD", "smallest_currency_fraction_value") < 0.01: + self.assertEqual(si.rounding_adjustment, 0.10) + self.assertEqual(si.base_rounding_adjustment, 5.0) + else: + self.assertEqual(si.rounding_adjustment, 0.0) + self.assertEqual(si.base_rounding_adjustment, 0.0) def test_outstanding(self): w = self.make() @@ -2126,7 +2133,7 @@ class TestSalesInvoice(FrappeTestCase): def test_rounding_adjustment_2(self): si = create_sales_invoice(rate=400, do_not_save=True) - for rate in [400, 600, 100]: + for rate in [400.25, 600.30, 100.65]: si.append( "items", { @@ -2152,17 +2159,18 @@ class TestSalesInvoice(FrappeTestCase): ) si.save() si.submit() - self.assertEqual(si.net_total, 1271.19) - self.assertEqual(si.grand_total, 1500) - self.assertEqual(si.total_taxes_and_charges, 228.82) - self.assertEqual(si.rounding_adjustment, -0.01) + self.assertEqual(si.net_total, si.base_net_total) + self.assertEqual(si.net_total, 1272.20) + self.assertEqual(si.grand_total, 1501.20) + self.assertEqual(si.total_taxes_and_charges, 229) + self.assertEqual(si.rounding_adjustment, -0.20) expected_values = [ - ["_Test Account Service Tax - _TC", 0.0, 114.41], - ["_Test Account VAT - _TC", 0.0, 114.41], - [si.debit_to, 1500, 0.0], - ["Round Off - _TC", 0.01, 0.01], - ["Sales - _TC", 0.0, 1271.18], + ["_Test Account Service Tax - _TC", 0.0, 114.50], + ["_Test Account VAT - _TC", 0.0, 114.50], + [si.debit_to, 1501, 0.0], + ["Round Off - _TC", 0.20, 0.0], + ["Sales - _TC", 0.0, 1272.20], ] gl_entries = frappe.db.sql( @@ -2220,7 +2228,8 @@ class TestSalesInvoice(FrappeTestCase): si.save() si.submit() - self.assertEqual(si.net_total, 4007.16) + self.assertEqual(si.net_total, si.base_net_total) + self.assertEqual(si.net_total, 4007.15) self.assertEqual(si.grand_total, 4488.02) self.assertEqual(si.total_taxes_and_charges, 480.86) self.assertEqual(si.rounding_adjustment, -0.02) @@ -2232,7 +2241,7 @@ class TestSalesInvoice(FrappeTestCase): ["_Test Account Service Tax - _TC", 0.0, 240.43], ["_Test Account VAT - _TC", 0.0, 240.43], ["Sales - _TC", 0.0, 4007.15], - ["Round Off - _TC", 0.02, 0.01], + ["Round Off - _TC", 0.01, 0.0], ] ) diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index e92356e30a8..7d371bdf9a6 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -8,6 +8,7 @@ import frappe from frappe import _, scrub from frappe.model.document import Document from frappe.utils import cint, flt, round_based_on_smallest_currency_fraction +from frappe.utils.deprecations import deprecated import erpnext from erpnext.accounts.doctype.journal_entry.journal_entry import get_exchange_rate @@ -71,7 +72,7 @@ class calculate_taxes_and_totals: self.calculate_net_total() self.calculate_tax_withholding_net_total() self.calculate_taxes() - self.manipulate_grand_total_for_inclusive_tax() + self.adjust_grand_total_for_inclusive_tax() self.calculate_totals() self._cleanup() self.calculate_total_net_weight() @@ -280,7 +281,7 @@ class calculate_taxes_and_totals: ): amount = flt(item.amount) - total_inclusive_tax_amount_per_qty - item.net_amount = flt(amount / (1 + cumulated_tax_fraction)) + item.net_amount = flt(amount / (1 + cumulated_tax_fraction), item.precision("net_amount")) item.net_rate = flt(item.net_amount / item.qty, item.precision("net_rate")) item.discount_percentage = flt( item.discount_percentage, item.precision("discount_percentage") @@ -505,7 +506,12 @@ class calculate_taxes_and_totals: tax.base_tax_amount = round(tax.base_tax_amount, 0) tax.base_tax_amount_after_discount_amount = round(tax.base_tax_amount_after_discount_amount, 0) + @deprecated def manipulate_grand_total_for_inclusive_tax(self): + # for backward compatablility - if in case used by an external application + return self.adjust_grand_total_for_inclusive_tax() + + def adjust_grand_total_for_inclusive_tax(self): # if fully inclusive taxes and diff if self.doc.get("taxes") and any(cint(t.included_in_print_rate) for t in self.doc.get("taxes")): last_tax = self.doc.get("taxes")[-1] @@ -527,17 +533,21 @@ class calculate_taxes_and_totals: diff = flt(diff, self.doc.precision("rounding_adjustment")) if diff and abs(diff) <= (5.0 / 10 ** last_tax.precision("tax_amount")): - self.doc.rounding_adjustment = diff + self.doc.grand_total_diff = diff + else: + self.doc.grand_total_diff = 0 def calculate_totals(self): if self.doc.get("taxes"): - self.doc.grand_total = flt(self.doc.get("taxes")[-1].total) + flt(self.doc.rounding_adjustment) + self.doc.grand_total = flt(self.doc.get("taxes")[-1].total) + flt( + self.doc.get("grand_total_diff") + ) else: self.doc.grand_total = flt(self.doc.net_total) if self.doc.get("taxes"): self.doc.total_taxes_and_charges = flt( - self.doc.grand_total - self.doc.net_total - flt(self.doc.rounding_adjustment), + self.doc.grand_total - self.doc.net_total - flt(self.doc.get("grand_total_diff")), self.doc.precision("total_taxes_and_charges"), ) else: @@ -600,8 +610,8 @@ class calculate_taxes_and_totals: self.doc.grand_total, self.doc.currency, self.doc.precision("rounded_total") ) - # if print_in_rate is set, we would have already calculated rounding adjustment - self.doc.rounding_adjustment += flt( + # rounding adjustment should always be the difference vetween grand and rounded total + self.doc.rounding_adjustment = flt( self.doc.rounded_total - self.doc.grand_total, self.doc.precision("rounding_adjustment") ) diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js index 1ba941ab6f7..79770b83202 100644 --- a/erpnext/public/js/controllers/accounts.js +++ b/erpnext/public/js/controllers/accounts.js @@ -22,6 +22,7 @@ frappe.ui.form.on(cur_frm.doctype, { } else { var account_type = ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation"]; } +<<<<<<< HEAD return { query: "erpnext.controllers.queries.tax_account_query", @@ -29,6 +30,18 @@ frappe.ui.form.on(cur_frm.doctype, { "account_type": account_type, "company": doc.company, } +======= + }, + included_in_print_rate: function(frm, cdt, cdn) { + let tax = frappe.get_doc(cdt, cdn); + try { + me.validate_taxes_and_charges(cdt, cdn); + me.validate_inclusive_tax(tax, frm); + } catch(e) { + tax.included_in_print_rate = 0; + refresh_field("included_in_print_rate", tax.name, tax.parentfield); + throw e; +>>>>>>> 50d56db0c2 (fix: specify precision for net_amount (#39481)) } }); frm.set_query("cost_center", "taxes", function(doc) { @@ -53,14 +66,24 @@ frappe.ui.form.on(cur_frm.doctype, { erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.open_grid_row()); }, +<<<<<<< HEAD allocate_advances_automatically: function(frm) { frm.trigger('fetch_advances'); }, +======= + validate_inclusive_tax: function(tax, frm) { + this.frm = this.frm || frm; + let actual_type_error = function() { + var msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx]) + frappe.throw(msg); + }; +>>>>>>> 50d56db0c2 (fix: specify precision for net_amount (#39481)) only_include_allocated_payments: function(frm) { frm.trigger('fetch_advances'); }, +<<<<<<< HEAD fetch_advances: function(frm) { if(frm.doc.allocate_advances_automatically) { frappe.call({ @@ -68,6 +91,23 @@ frappe.ui.form.on(cur_frm.doctype, { method: "set_advances", callback: function(r, rt) { refresh_field("advances"); +======= + if(cint(tax.included_in_print_rate)) { + if(tax.charge_type == "Actual") { + // inclusive tax cannot be of type Actual + actual_type_error(); + } else if (tax.charge_type == "On Previous Row Amount" && this.frm && + !cint(this.frm.doc["taxes"][tax.row_id - 1].included_in_print_rate) + ) { + // referred row should also be an inclusive tax + on_previous_row_error(tax.row_id); + } else if (tax.charge_type == "On Previous Row Total" && this.frm) { + var taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id), + function(t) { return cint(t.included_in_print_rate) ? null : t; }); + if(taxes_not_included.length > 0) { + // all rows above this tax should be inclusive + on_previous_row_error(tax.row_id == 1 ? "1" : "1 - " + tax.row_id); +>>>>>>> 50d56db0c2 (fix: specify precision for net_amount (#39481)) } }) } diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index 670cf35bb11..b164453e68c 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -103,7 +103,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { this.determine_exclusive_rate(); this.calculate_net_total(); this.calculate_taxes(); - this.manipulate_grand_total_for_inclusive_tax(); + this.adjust_grand_total_for_inclusive_tax(); this.calculate_totals(); this._cleanup(); } @@ -183,9 +183,15 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0; }); +<<<<<<< HEAD if (!this.discount_amount_applied && cur_frm) { cur_frm.cscript.validate_taxes_and_charges(tax.doctype, tax.name); me.validate_inclusive_tax(tax); +======= + if (!this.discount_amount_applied) { + erpnext.accounts.taxes.validate_taxes_and_charges(tax.doctype, tax.name); + erpnext.accounts.taxes.validate_inclusive_tax(tax, this.frm); +>>>>>>> 50d56db0c2 (fix: specify precision for net_amount (#39481)) } frappe.model.round_floats_in(tax); }); @@ -243,7 +249,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { if(!me.discount_amount_applied && item.qty && (total_inclusive_tax_amount_per_qty || cumulated_tax_fraction)) { var amount = flt(item.amount) - total_inclusive_tax_amount_per_qty; - item.net_amount = flt(amount / (1 + cumulated_tax_fraction)); + item.net_amount = flt(amount / (1 + cumulated_tax_fraction), precision("net_amount", item)); item.net_rate = item.qty ? flt(item.net_amount / item.qty, precision("net_rate", item)) : 0; me.set_in_company_currency(item, ["net_rate", "net_amount"]); @@ -298,6 +304,8 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { me.frm.doc.net_total += item.net_amount; me.frm.doc.base_net_total += item.base_net_amount; }); + + frappe.model.round_floats_in(this.frm.doc, ["total", "base_total", "net_total", "base_net_total"]); } calculate_shipping_charges() { @@ -506,8 +514,17 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { } } + /** + * @deprecated Use adjust_grand_total_for_inclusive_tax instead. + */ manipulate_grand_total_for_inclusive_tax() { + // for backward compatablility - if in case used by an external application + this.adjust_grand_total_for_inclusive_tax() + } + + adjust_grand_total_for_inclusive_tax() { var me = this; + // if fully inclusive taxes and diff if (this.frm.doc["taxes"] && this.frm.doc["taxes"].length) { var any_inclusive_tax = false; @@ -533,7 +550,9 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { diff = flt(diff, precision("rounding_adjustment")); if ( diff && Math.abs(diff) <= (5.0 / Math.pow(10, precision("tax_amount", last_tax))) ) { - me.frm.doc.rounding_adjustment = diff; + me.frm.doc.grand_total_diff = diff; + } else { + me.frm.doc.grand_total_diff = 0; } } } @@ -544,7 +563,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { var me = this; var tax_count = this.frm.doc["taxes"] ? this.frm.doc["taxes"].length : 0; this.frm.doc.grand_total = flt(tax_count - ? this.frm.doc["taxes"][tax_count - 1].total + flt(this.frm.doc.rounding_adjustment) + ? this.frm.doc["taxes"][tax_count - 1].total + flt(this.frm.doc.grand_total_diff) : this.frm.doc.net_total); if(["Quotation", "Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"].includes(this.frm.doc.doctype)) { @@ -604,7 +623,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { if(frappe.meta.get_docfield(this.frm.doc.doctype, "rounded_total", this.frm.doc.name)) { this.frm.doc.rounded_total = round_based_on_smallest_currency_fraction(this.frm.doc.grand_total, this.frm.doc.currency, precision("rounded_total")); - this.frm.doc.rounding_adjustment += flt(this.frm.doc.rounded_total - this.frm.doc.grand_total, + this.frm.doc.rounding_adjustment = flt(this.frm.doc.rounded_total - this.frm.doc.grand_total, precision("rounding_adjustment")); this.set_in_company_currency(this.frm.doc, ["rounding_adjustment", "rounded_total"]); @@ -672,8 +691,7 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { if (total_for_discount_amount) { $.each(this.frm._items || [], function(i, item) { distributed_amount = flt(me.frm.doc.discount_amount) * item.net_amount / total_for_discount_amount; - item.net_amount = flt(item.net_amount - distributed_amount, - precision("base_amount", item)); + item.net_amount = flt(item.net_amount - distributed_amount, precision("net_amount", item)); net_total += item.net_amount; // discount amount rounding loss adjustment if no taxes From c5dedab30478bef17bbc0b166795dab95f3578b7 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 19 Aug 2024 10:25:27 +0530 Subject: [PATCH 2/4] chore: resolve conflicts --- erpnext/public/js/controllers/accounts.js | 49 ++----------------- .../public/js/controllers/taxes_and_totals.js | 6 --- 2 files changed, 5 insertions(+), 50 deletions(-) diff --git a/erpnext/public/js/controllers/accounts.js b/erpnext/public/js/controllers/accounts.js index 79770b83202..304b71e33d4 100644 --- a/erpnext/public/js/controllers/accounts.js +++ b/erpnext/public/js/controllers/accounts.js @@ -22,7 +22,6 @@ frappe.ui.form.on(cur_frm.doctype, { } else { var account_type = ["Tax", "Chargeable", "Income Account", "Expenses Included In Valuation"]; } -<<<<<<< HEAD return { query: "erpnext.controllers.queries.tax_account_query", @@ -30,18 +29,6 @@ frappe.ui.form.on(cur_frm.doctype, { "account_type": account_type, "company": doc.company, } -======= - }, - included_in_print_rate: function(frm, cdt, cdn) { - let tax = frappe.get_doc(cdt, cdn); - try { - me.validate_taxes_and_charges(cdt, cdn); - me.validate_inclusive_tax(tax, frm); - } catch(e) { - tax.included_in_print_rate = 0; - refresh_field("included_in_print_rate", tax.name, tax.parentfield); - throw e; ->>>>>>> 50d56db0c2 (fix: specify precision for net_amount (#39481)) } }); frm.set_query("cost_center", "taxes", function(doc) { @@ -66,24 +53,14 @@ frappe.ui.form.on(cur_frm.doctype, { erpnext.taxes.set_conditional_mandatory_rate_or_amount(frm.open_grid_row()); }, -<<<<<<< HEAD allocate_advances_automatically: function(frm) { frm.trigger('fetch_advances'); }, -======= - validate_inclusive_tax: function(tax, frm) { - this.frm = this.frm || frm; - let actual_type_error = function() { - var msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx]) - frappe.throw(msg); - }; ->>>>>>> 50d56db0c2 (fix: specify precision for net_amount (#39481)) only_include_allocated_payments: function(frm) { frm.trigger('fetch_advances'); }, -<<<<<<< HEAD fetch_advances: function(frm) { if(frm.doc.allocate_advances_automatically) { frappe.call({ @@ -91,23 +68,6 @@ frappe.ui.form.on(cur_frm.doctype, { method: "set_advances", callback: function(r, rt) { refresh_field("advances"); -======= - if(cint(tax.included_in_print_rate)) { - if(tax.charge_type == "Actual") { - // inclusive tax cannot be of type Actual - actual_type_error(); - } else if (tax.charge_type == "On Previous Row Amount" && this.frm && - !cint(this.frm.doc["taxes"][tax.row_id - 1].included_in_print_rate) - ) { - // referred row should also be an inclusive tax - on_previous_row_error(tax.row_id); - } else if (tax.charge_type == "On Previous Row Total" && this.frm) { - var taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id), - function(t) { return cint(t.included_in_print_rate) ? null : t; }); - if(taxes_not_included.length > 0) { - // all rows above this tax should be inclusive - on_previous_row_error(tax.row_id == 1 ? "1" : "1 - " + tax.row_id); ->>>>>>> 50d56db0c2 (fix: specify precision for net_amount (#39481)) } }) } @@ -270,7 +230,8 @@ cur_frm.cscript.validate_taxes_and_charges = function(cdt, cdn) { } -cur_frm.cscript.validate_inclusive_tax = function(tax) { +cur_frm.cscript.validate_inclusive_tax = function(tax, frm) { + this.frm = this.frm || frm; var actual_type_error = function() { var msg = __("Actual type tax cannot be included in Item rate in row {0}", [tax.idx]) frappe.throw(msg); @@ -286,12 +247,12 @@ cur_frm.cscript.validate_inclusive_tax = function(tax) { if(tax.charge_type == "Actual") { // inclusive tax cannot be of type Actual actual_type_error(); - } else if(tax.charge_type == "On Previous Row Amount" && + } else if(tax.charge_type == "On Previous Row Amount" && this.frm && !cint(this.frm.doc["taxes"][tax.row_id - 1].included_in_print_rate) ) { // referred row should also be an inclusive tax on_previous_row_error(tax.row_id); - } else if(tax.charge_type == "On Previous Row Total") { + } else if(tax.charge_type == "On Previous Row Total" && this.frm) { var taxes_not_included = $.map(this.frm.doc["taxes"].slice(0, tax.row_id), function(t) { return cint(t.included_in_print_rate) ? null : t; }); if(taxes_not_included.length > 0) { @@ -334,7 +295,7 @@ if(!erpnext.taxes.flags[cur_frm.cscript.tax_table]) { var tax = frappe.get_doc(cdt, cdn); try { cur_frm.cscript.validate_taxes_and_charges(cdt, cdn); - cur_frm.cscript.validate_inclusive_tax(tax); + cur_frm.cscript.validate_inclusive_tax(tax, frm); } catch(e) { tax.included_in_print_rate = 0; refresh_field("included_in_print_rate", tax.name, tax.parentfield); diff --git a/erpnext/public/js/controllers/taxes_and_totals.js b/erpnext/public/js/controllers/taxes_and_totals.js index b164453e68c..82e1d518362 100644 --- a/erpnext/public/js/controllers/taxes_and_totals.js +++ b/erpnext/public/js/controllers/taxes_and_totals.js @@ -183,15 +183,9 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments { $.each(tax_fields, function(i, fieldname) { tax[fieldname] = 0.0; }); -<<<<<<< HEAD if (!this.discount_amount_applied && cur_frm) { cur_frm.cscript.validate_taxes_and_charges(tax.doctype, tax.name); me.validate_inclusive_tax(tax); -======= - if (!this.discount_amount_applied) { - erpnext.accounts.taxes.validate_taxes_and_charges(tax.doctype, tax.name); - erpnext.accounts.taxes.validate_inclusive_tax(tax, this.frm); ->>>>>>> 50d56db0c2 (fix: specify precision for net_amount (#39481)) } frappe.model.round_floats_in(tax); }); From 678f08898a5bbbe1ceafb82e5df61e7c80953823 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 21 Aug 2024 15:23:57 +0530 Subject: [PATCH 3/4] refactor(test): update tast case of rounding value --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 0ff26ba4d74..8c246702874 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -415,7 +415,7 @@ class TestSalesInvoice(FrappeTestCase): for i, k in enumerate(expected_values["keys"]): self.assertEqual(d.get(k), expected_values[d.account_head][i]) - self.assertEqual(si.base_grand_total, 1500) + self.assertEqual(si.base_grand_total, 1500.01) self.assertEqual(si.grand_total, 1500) self.assertEqual(si.rounding_adjustment, -0.01) @@ -2106,7 +2106,7 @@ class TestSalesInvoice(FrappeTestCase): self.assertEqual(si.net_total, 19453.13) self.assertEqual(si.grand_total, 24900) self.assertEqual(si.total_taxes_and_charges, 5446.88) - self.assertEqual(si.rounding_adjustment, -0.01) + self.assertEqual(si.rounding_adjustment, 0.00) expected_values = dict( (d[0], d) From c2fdef4d5b5809fc054f670b13ee26a8705feaf5 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 21 Aug 2024 17:36:11 +0530 Subject: [PATCH 4/4] refactor(test): update grand total --- erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py | 2 +- 1 file changed, 1 insertion(+), 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 8c246702874..7b471ed418e 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -416,7 +416,7 @@ class TestSalesInvoice(FrappeTestCase): self.assertEqual(d.get(k), expected_values[d.account_head][i]) self.assertEqual(si.base_grand_total, 1500.01) - self.assertEqual(si.grand_total, 1500) + self.assertEqual(si.grand_total, 1500.01) self.assertEqual(si.rounding_adjustment, -0.01) def test_discount_amount_gl_entry(self):