From d09de53d1d2d48e77dbc635137259d46af67e4b5 Mon Sep 17 00:00:00 2001 From: diptanilsaha Date: Wed, 14 Jan 2026 01:34:20 +0530 Subject: [PATCH 1/6] fix(transaction.js): use flt instead of cint for plc_conversion_rate (cherry picked from commit 8b445e04e57ecfb25a22e767c455c3cabe173cb6) # Conflicts: # erpnext/public/js/controllers/transaction.js --- erpnext/public/js/controllers/transaction.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 9aaa5728ad7..b5f6b7e9f64 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1089,9 +1089,18 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe plc_conversion_rate() { if(this.frm.doc.price_list_currency === this.get_company_currency()) { this.frm.set_value("plc_conversion_rate", 1.0); +<<<<<<< HEAD } else if(this.frm.doc.price_list_currency === this.frm.doc.currency && this.frm.doc.plc_conversion_rate && cint(this.frm.doc.plc_conversion_rate) != 1 && cint(this.frm.doc.plc_conversion_rate) != cint(this.frm.doc.conversion_rate)) { +======= + } else if ( + this.frm.doc.price_list_currency === this.frm.doc.currency && + this.frm.doc.plc_conversion_rate && + flt(this.frm.doc.plc_conversion_rate) != 1 && + flt(this.frm.doc.plc_conversion_rate) != flt(this.frm.doc.conversion_rate) + ) { +>>>>>>> 8b445e04e5 (fix(transaction.js): use flt instead of cint for plc_conversion_rate) this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate); } From 39e1bddce6701562bb5dc23da9fb592fd8448086 Mon Sep 17 00:00:00 2001 From: Diptanil Saha Date: Wed, 14 Jan 2026 15:53:18 +0530 Subject: [PATCH 2/6] chore: resolve conflict --- erpnext/public/js/controllers/transaction.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index b5f6b7e9f64..ee7a9b05f10 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1089,18 +1089,12 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe plc_conversion_rate() { if(this.frm.doc.price_list_currency === this.get_company_currency()) { this.frm.set_value("plc_conversion_rate", 1.0); -<<<<<<< HEAD - } else if(this.frm.doc.price_list_currency === this.frm.doc.currency - && this.frm.doc.plc_conversion_rate && cint(this.frm.doc.plc_conversion_rate) != 1 && - cint(this.frm.doc.plc_conversion_rate) != cint(this.frm.doc.conversion_rate)) { -======= } else if ( this.frm.doc.price_list_currency === this.frm.doc.currency && this.frm.doc.plc_conversion_rate && flt(this.frm.doc.plc_conversion_rate) != 1 && flt(this.frm.doc.plc_conversion_rate) != flt(this.frm.doc.conversion_rate) ) { ->>>>>>> 8b445e04e5 (fix(transaction.js): use flt instead of cint for plc_conversion_rate) this.frm.set_value("conversion_rate", this.frm.doc.plc_conversion_rate); } From 6e03d4503474c85d46e231bc99117014092b688e Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Thu, 15 Jan 2026 17:04:49 +0530 Subject: [PATCH 3/6] fix: Show non-SLE vouchers with GL entries in Stock vs Account Value Comparison report (cherry picked from commit 1db9ce205f8337c7008d1708bbda8afae641c820) # Conflicts: # erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py --- .../stock_and_account_value_comparison.py | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py index 67e340d0f70..641275a57c5 100644 --- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py @@ -41,9 +41,37 @@ def get_data(report_filters): gl_data = voucher_wise_gl_data.get(key) or {} d.account_value = gl_data.get("account_value", 0) d.difference_value = d.stock_value - d.account_value + d.ledger_type = "Stock Ledger Entry" if abs(d.difference_value) > 0.1: data.append(d) + if key in voucher_wise_gl_data: + del voucher_wise_gl_data[key] + + if voucher_wise_gl_data: + data += get_gl_ledgers_with_no_stock_ledger_entries(voucher_wise_gl_data) + + return data + + +def get_gl_ledgers_with_no_stock_ledger_entries(voucher_wise_gl_data): + data = [] + + for key in voucher_wise_gl_data: + gl_data = voucher_wise_gl_data.get(key) or {} + data.append( + { + "name": gl_data.get("name"), + "ledger_type": "GL Entry", + "voucher_type": gl_data.get("voucher_type"), + "voucher_no": gl_data.get("voucher_no"), + "posting_date": gl_data.get("posting_date"), + "stock_value": 0, + "account_value": gl_data.get("account_value", 0), + "difference_value": gl_data.get("account_value", 0) * -1, + } + ) + return data @@ -87,7 +115,15 @@ def get_gl_data(report_filters, filters): "name", "voucher_type", "voucher_no", +<<<<<<< HEAD "sum(debit_in_account_currency) - sum(credit_in_account_currency) as account_value", +======= + "posting_date", + { + "SUB": [{"SUM": "debit_in_account_currency"}, {"SUM": "credit_in_account_currency"}], + "as": "account_value", + }, +>>>>>>> 1db9ce205f (fix: Show non-SLE vouchers with GL entries in Stock vs Account Value Comparison report) ], group_by="voucher_type, voucher_no", ) @@ -105,10 +141,15 @@ def get_columns(filters): { "label": _("Stock Ledger ID"), "fieldname": "name", - "fieldtype": "Link", - "options": "Stock Ledger Entry", + "fieldtype": "Dynamic Link", + "options": "ledger_type", "width": "80", }, + { + "label": _("Ledger Type"), + "fieldname": "ledger_type", + "fieldtype": "Data", + }, {"label": _("Posting Date"), "fieldname": "posting_date", "fieldtype": "Date"}, {"label": _("Posting Time"), "fieldname": "posting_time", "fieldtype": "Time"}, {"label": _("Voucher Type"), "fieldname": "voucher_type", "width": "110"}, From ad5181c52ffd754033fdeb8b8d9f1ad11fe54ded Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Thu, 15 Jan 2026 19:28:44 +0530 Subject: [PATCH 4/6] chore: fix conflicts --- .../stock_and_account_value_comparison.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py index 641275a57c5..6f94f40aefd 100644 --- a/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py +++ b/erpnext/stock/report/stock_and_account_value_comparison/stock_and_account_value_comparison.py @@ -115,15 +115,8 @@ def get_gl_data(report_filters, filters): "name", "voucher_type", "voucher_no", -<<<<<<< HEAD "sum(debit_in_account_currency) - sum(credit_in_account_currency) as account_value", -======= "posting_date", - { - "SUB": [{"SUM": "debit_in_account_currency"}, {"SUM": "credit_in_account_currency"}], - "as": "account_value", - }, ->>>>>>> 1db9ce205f (fix: Show non-SLE vouchers with GL entries in Stock vs Account Value Comparison report) ], group_by="voucher_type, voucher_no", ) From cf49c32b942734c43539fbbf0b6508d6805d5258 Mon Sep 17 00:00:00 2001 From: Lakshit Jain Date: Mon, 19 Jan 2026 12:30:29 +0530 Subject: [PATCH 5/6] Merge pull request #51787 from ljain112/fix-taxes-disc fix: recalculate taxes when item tax template changes after discount (cherry picked from commit f00aeec9b47878761ccc225c504a0412f6488a0b) # Conflicts: # erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py # erpnext/controllers/taxes_and_totals.py --- .../sales_invoice/test_sales_invoice.py | 58 +++++++++++++++++++ erpnext/controllers/taxes_and_totals.py | 18 ++++++ 2 files changed, 76 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index dd8acec196e..7e5917ad742 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2828,7 +2828,65 @@ class TestSalesInvoice(FrappeTestCase): self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC") self.assertEqual(sales_invoice.items[0].item_tax_rate, item_tax_map) +<<<<<<< HEAD @change_settings("Selling Settings", {"enable_discount_accounting": 1}) +======= + def test_item_tax_template_change_with_grand_total_discount(self): + """ + Test that when item tax template changes due to discount on Grand Total, + the tax calculations are consistent. + """ + item = create_item("Test Item With Multiple Tax Templates") + + item.set("taxes", []) + item.append( + "taxes", + { + "item_tax_template": "_Test Account Excise Duty @ 10 - _TC", + "minimum_net_rate": 0, + "maximum_net_rate": 500, + }, + ) + + item.append( + "taxes", + { + "item_tax_template": "_Test Account Excise Duty @ 12 - _TC", + "minimum_net_rate": 501, + "maximum_net_rate": 1000, + }, + ) + + item.save() + + si = create_sales_invoice(item=item.name, rate=700, do_not_save=True) + si.append( + "taxes", + { + "charge_type": "On Net Total", + "account_head": "_Test Account Excise Duty - _TC", + "cost_center": "_Test Cost Center - _TC", + "description": "Excise Duty", + "rate": 0, + }, + ) + si.insert() + + self.assertEqual(si.items[0].item_tax_template, "_Test Account Excise Duty @ 12 - _TC") + + si.apply_discount_on = "Grand Total" + si.discount_amount = 300 + si.save() + + # Verify template changed to 10% + self.assertEqual(si.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC") + self.assertEqual(si.taxes[0].tax_amount, 70) # 10% of 700 + self.assertEqual(si.grand_total, 470) # 700 + 70 - 300 + + si.submit() + + @IntegrationTestCase.change_settings("Selling Settings", {"enable_discount_accounting": 1}) +>>>>>>> f00aeec9b4 (Merge pull request #51787 from ljain112/fix-taxes-disc) def test_sales_invoice_with_discount_accounting_enabled(self): discount_account = create_account( account_name="Discount Account", diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index ced62b71cf9..f871e7d1b3b 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -42,17 +42,28 @@ class calculate_taxes_and_totals: items = list(filter(lambda item: not item.get("is_alternative"), self.doc.get("items"))) return items +<<<<<<< HEAD def calculate(self): if not len(self._items): +======= + def calculate(self, ignore_tax_template_validation=False): + if not len(self.doc.items): +>>>>>>> f00aeec9b4 (Merge pull request #51787 from ljain112/fix-taxes-disc) return self.discount_amount_applied = False + self.need_recomputation = False + self.ignore_tax_template_validation = ignore_tax_template_validation + self._calculate() if self.doc.meta.get_field("discount_amount"): self.set_discount_amount() self.apply_discount_amount() + if not ignore_tax_template_validation and self.need_recomputation: + return self.calculate(ignore_tax_template_validation=True) + # Update grand total as per cash and non trade discount if self.doc.apply_discount_on == "Grand Total" and self.doc.get("is_cash_or_non_trade_discount"): self.doc.grand_total -= self.doc.discount_amount @@ -96,6 +107,9 @@ class calculate_taxes_and_totals: self.doc.base_tax_withholding_net_total = sum_base_net_amount def validate_item_tax_template(self): + if self.ignore_tax_template_validation: + return + if self.doc.get("is_return") and self.doc.get("return_against"): return @@ -136,6 +150,10 @@ class calculate_taxes_and_totals: ) ) + # For correct tax_amount calculation re-computation is required + if self.discount_amount_applied and self.doc.apply_discount_on == "Grand Total": + self.need_recomputation = True + def update_item_tax_map(self): for item in self.doc.items: item.item_tax_rate = get_item_tax_map( From b4dc1be5ed18dd0d07c748b30ee5a96a0ab7302d Mon Sep 17 00:00:00 2001 From: ljain112 Date: Mon, 19 Jan 2026 13:45:11 +0530 Subject: [PATCH 6/6] chore: resolve conflicts --- .../accounts/doctype/sales_invoice/test_sales_invoice.py | 6 +----- erpnext/controllers/taxes_and_totals.py | 7 +------ 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py index 7e5917ad742..535046aad1b 100644 --- a/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/test_sales_invoice.py @@ -2828,9 +2828,6 @@ class TestSalesInvoice(FrappeTestCase): self.assertEqual(sales_invoice.items[0].item_tax_template, "_Test Account Excise Duty @ 10 - _TC") self.assertEqual(sales_invoice.items[0].item_tax_rate, item_tax_map) -<<<<<<< HEAD - @change_settings("Selling Settings", {"enable_discount_accounting": 1}) -======= def test_item_tax_template_change_with_grand_total_discount(self): """ Test that when item tax template changes due to discount on Grand Total, @@ -2885,8 +2882,7 @@ class TestSalesInvoice(FrappeTestCase): si.submit() - @IntegrationTestCase.change_settings("Selling Settings", {"enable_discount_accounting": 1}) ->>>>>>> f00aeec9b4 (Merge pull request #51787 from ljain112/fix-taxes-disc) + @change_settings("Selling Settings", {"enable_discount_accounting": 1}) def test_sales_invoice_with_discount_accounting_enabled(self): discount_account = create_account( account_name="Discount Account", diff --git a/erpnext/controllers/taxes_and_totals.py b/erpnext/controllers/taxes_and_totals.py index f871e7d1b3b..102622adf7a 100644 --- a/erpnext/controllers/taxes_and_totals.py +++ b/erpnext/controllers/taxes_and_totals.py @@ -42,13 +42,8 @@ class calculate_taxes_and_totals: items = list(filter(lambda item: not item.get("is_alternative"), self.doc.get("items"))) return items -<<<<<<< HEAD - def calculate(self): - if not len(self._items): -======= def calculate(self, ignore_tax_template_validation=False): - if not len(self.doc.items): ->>>>>>> f00aeec9b4 (Merge pull request #51787 from ljain112/fix-taxes-disc) + if not len(self._items): return self.discount_amount_applied = False