From 1df3b608ecee545b79cebadc9894b016d92f1e62 Mon Sep 17 00:00:00 2001 From: Hossein Yousefian <86075967+ihosseinu@users.noreply.github.com> Date: Sun, 16 Apr 2023 11:03:16 +0330 Subject: [PATCH 01/13] get_incoming_rate_zero_in_rate_fix --- erpnext/stock/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index 0067c321049..bd23351cbd7 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -301,10 +301,10 @@ def get_incoming_rate(args, raise_error_if_no_rate=True): in_rate = ( _get_fifo_lifo_rate(previous_stock_queue, args.get("qty") or 0, valuation_method) if previous_stock_queue - else 0 + else None ) elif valuation_method == "Moving Average": - in_rate = previous_sle.get("valuation_rate") or 0 + in_rate = previous_sle.get("valuation_rate") if in_rate is None: in_rate = get_valuation_rate( From bd9655a7814c9a22dcbe934169bf2774fc691be2 Mon Sep 17 00:00:00 2001 From: Hossein Yousefian <86075967+ihosseinu@users.noreply.github.com> Date: Tue, 18 Apr 2023 14:50:09 +0330 Subject: [PATCH 02/13] get_incoming_rate_voucher_no_fix --- erpnext/stock/utils.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/stock/utils.py b/erpnext/stock/utils.py index bd23351cbd7..65f55b2e8ae 100644 --- a/erpnext/stock/utils.py +++ b/erpnext/stock/utils.py @@ -277,8 +277,6 @@ def get_incoming_rate(args, raise_error_if_no_rate=True): if isinstance(args, str): args = json.loads(args) - voucher_no = args.get("voucher_no") or args.get("name") - in_rate = None if (args.get("serial_no") or "").strip(): in_rate = get_avg_purchase_rate(args.get("serial_no")) @@ -307,6 +305,7 @@ def get_incoming_rate(args, raise_error_if_no_rate=True): in_rate = previous_sle.get("valuation_rate") if in_rate is None: + voucher_no = args.get("voucher_no") or args.get("name") in_rate = get_valuation_rate( args.get("item_code"), args.get("warehouse"), From 2c98081be65b92674c00a7b7585b0d516183658d Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Fri, 1 Aug 2025 16:39:56 +0530 Subject: [PATCH 03/13] fix: add flt to prevent NoneType errors --- erpnext/stock/report/stock_ageing/stock_ageing.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 7d63209f478..5292d257493 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -439,10 +439,10 @@ class FIFOSlots: transfer_qty_to_pop = 0 def __update_balances(self, row: dict, key: tuple | str): - self.item_details[key]["qty_after_transaction"] = row.qty_after_transaction or row.bal_qty + self.item_details[key]["qty_after_transaction"] = row.qty_after_transaction or flt(row.bal_qty) if "total_qty" not in self.item_details[key]: - self.item_details[key]["total_qty"] = row.actual_qty or row.bal_qty + self.item_details[key]["total_qty"] = row.actual_qty or flt(row.bal_qty) else: self.item_details[key]["total_qty"] += row.actual_qty From d38fd0779c09b3d92ac3b4a7090429c2f49e8ce3 Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Sat, 2 Aug 2025 11:38:47 -0400 Subject: [PATCH 04/13] fix: provide missing `company` in report records that require reference to `Company:company:default_currency` --- erpnext/accounts/report/payment_ledger/payment_ledger.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/report/payment_ledger/payment_ledger.py b/erpnext/accounts/report/payment_ledger/payment_ledger.py index d4f0f0a107d..03411cccd78 100644 --- a/erpnext/accounts/report/payment_ledger/payment_ledger.py +++ b/erpnext/accounts/report/payment_ledger/payment_ledger.py @@ -46,6 +46,7 @@ class PaymentLedger: against_voucher_no=ple.against_voucher_no, amount=ple.amount, currency=ple.account_currency, + company=ple.company, ) if self.filters.include_account_currency: From 235f27172915db2ad55b5da1e51887bcf6d5632f Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Sat, 2 Aug 2025 12:23:12 -0400 Subject: [PATCH 05/13] fix: provide company for outstanding record. --- erpnext/accounts/report/payment_ledger/payment_ledger.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/report/payment_ledger/payment_ledger.py b/erpnext/accounts/report/payment_ledger/payment_ledger.py index 03411cccd78..03080aeeed0 100644 --- a/erpnext/accounts/report/payment_ledger/payment_ledger.py +++ b/erpnext/accounts/report/payment_ledger/payment_ledger.py @@ -78,6 +78,7 @@ class PaymentLedger: against_voucher_no="Outstanding:", amount=total, currency=voucher_data[0].currency, + company=voucher_data[0].company, ) if self.filters.include_account_currency: From 0de4477ddf9f8a1e0033af6ed3e3f73e91e5cb18 Mon Sep 17 00:00:00 2001 From: Devin Slauenwhite Date: Sat, 2 Aug 2025 12:29:40 -0400 Subject: [PATCH 06/13] fix: payment ledger voucher seperator row currencies --- erpnext/accounts/report/payment_ledger/payment_ledger.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/payment_ledger/payment_ledger.py b/erpnext/accounts/report/payment_ledger/payment_ledger.py index 03080aeeed0..7a2fdc4c925 100644 --- a/erpnext/accounts/report/payment_ledger/payment_ledger.py +++ b/erpnext/accounts/report/payment_ledger/payment_ledger.py @@ -87,7 +87,12 @@ class PaymentLedger: voucher_data.append(entry) # empty row - voucher_data.append(frappe._dict()) + voucher_data.append( + frappe._dict( + currency=voucher_data[0].currency, + company=voucher_data[0].company, + ) + ) self.data.extend(voucher_data) def build_conditions(self): From c263e6d67e3b31e3bd484d6352359c5bc98b5978 Mon Sep 17 00:00:00 2001 From: l0gesh29 Date: Wed, 30 Jul 2025 16:38:33 +0530 Subject: [PATCH 07/13] fix: add doctype fieldname in condition (cherry picked from commit e2d63e4c32cba418e500a327110258659c8f6388) # Conflicts: # erpnext/accounts/utils.py --- erpnext/accounts/utils.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 8ca34783196..859805f082e 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -2,6 +2,7 @@ # License: GNU General Public License v3. See license.txt +from collections import defaultdict from json import loads from typing import TYPE_CHECKING, Optional @@ -2195,25 +2196,37 @@ def run_ledger_health_checks(): doc.save() +def get_link_fields_grouped_by_option(doctype): + meta = frappe.get_meta(doctype) + link_fields_map = defaultdict(list) + + for df in meta.fields: + if df.fieldtype == "Link" and df.options and not df.ignore_user_permissions: + link_fields_map[df.options].append(df.fieldname) + + return link_fields_map + + def build_qb_match_conditions(doctype, user=None) -> list: match_filters = build_match_conditions(doctype, user, False) + link_fields_map = get_link_fields_grouped_by_option(doctype) criterion = [] apply_strict_user_permissions = frappe.get_system_settings("apply_strict_user_permissions") if match_filters: - from frappe import qb - _dt = qb.DocType(doctype) for filter in match_filters: - for d, names in filter.items(): - fieldname = d.lower().replace(" ", "_") - field = _dt[fieldname] + for link_option, allowed_values in filter.items(): + fieldnames = link_fields_map.get(link_option, []) - cond = field.isin(names) - if not apply_strict_user_permissions: - cond = (Coalesce(field, "") == "") | field.isin(names) + for fieldname in fieldnames: + field = _dt[fieldname] + cond = field.isin(allowed_values) - criterion.append(cond) + if not apply_strict_user_permissions: + cond = (Coalesce(field, "") == "") | cond + + criterion.append(cond) return criterion From f415bc3d14158c1ab72389099d207f9777e2f612 Mon Sep 17 00:00:00 2001 From: Corentin Forler Date: Fri, 18 Jul 2025 16:17:42 +0200 Subject: [PATCH 08/13] fix: Use correct Attachments folder in code list import (cherry picked from commit bc2cb1737aa2b3a26a718e1cdc06f42278d102ae) --- erpnext/edi/doctype/code_list/code_list_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/edi/doctype/code_list/code_list_import.py b/erpnext/edi/doctype/code_list/code_list_import.py index 50df3be471e..ecabb256026 100644 --- a/erpnext/edi/doctype/code_list/code_list_import.py +++ b/erpnext/edi/doctype/code_list/code_list_import.py @@ -60,7 +60,7 @@ def import_genericode(): "doctype": "File", "attached_to_doctype": "Code List", "attached_to_name": code_list.name, - "folder": "Home/Attachments", + "folder": frappe.db.get_value("File", {"is_attachments_folder": 1}), "file_name": frappe.local.uploaded_filename, "file_url": frappe.local.uploaded_file_url, "is_private": 1, From 82e8fb8a5e1bbbe77596a12264f783eb3a9503f5 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Wed, 30 Jul 2025 16:50:49 +0530 Subject: [PATCH 09/13] chore: correct description for `consider_party_ledger_amount` in Tax Withholding Category (cherry picked from commit f619bca2d6c36365291c1dd7366a8646f3480ca3) # Conflicts: # erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json --- .../tax_withholding_category/tax_withholding_category.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json index 153906ffe97..286b915b05e 100644 --- a/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json +++ b/erpnext/accounts/doctype/tax_withholding_category/tax_withholding_category.json @@ -75,7 +75,7 @@ }, { "default": "0", - "description": "Even invoices with apply tax withholding unchecked will be considered for checking cumulative threshold breach", + "description": "Only payment entries with apply tax withholding unchecked will be considered for checking cumulative threshold breach", "fieldname": "consider_party_ledger_amount", "fieldtype": "Check", "label": "Consider Entire Party Ledger Amount", @@ -102,10 +102,11 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2021-07-27 21:47:34.396071", + "modified": "2025-07-30 07:13:51.785735", "modified_by": "Administrator", "module": "Accounts", "name": "Tax Withholding Category", + "naming_rule": "Set by user", "owner": "Administrator", "permissions": [ { @@ -148,4 +149,4 @@ "sort_field": "modified", "sort_order": "DESC", "track_changes": 1 -} \ No newline at end of file +} From 7abc4c40222bafde6f9e00cbc493c00bb9b261fe Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Tue, 5 Aug 2025 15:25:25 +0530 Subject: [PATCH 10/13] fix: closing balance being added twice to fifo queue --- erpnext/stock/report/stock_ageing/stock_ageing.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/erpnext/stock/report/stock_ageing/stock_ageing.py b/erpnext/stock/report/stock_ageing/stock_ageing.py index 5292d257493..aae197fe3a6 100644 --- a/erpnext/stock/report/stock_ageing/stock_ageing.py +++ b/erpnext/stock/report/stock_ageing/stock_ageing.py @@ -274,14 +274,6 @@ class FIFOSlots: d.actual_qty = d.bal_qty key, fifo_queue, transferred_item_key = self.__init_key_stores(d) - serial_nos = d.serial_no if d.serial_no else [] - if fifo_queue and isinstance(fifo_queue[0][0], str): - d.has_serial_no = 1 - - if d.actual_qty > 0: - self.__compute_incoming_stock(d, fifo_queue, transferred_item_key, serial_nos) - else: - self.__compute_outgoing_stock(d, fifo_queue, transferred_item_key, serial_nos) self.__update_balances(d, key) From eb691226d54a86c6ddc20eb7d7179c93e27c4d2b Mon Sep 17 00:00:00 2001 From: l0gesh29 Date: Mon, 28 Jul 2025 13:54:02 +0530 Subject: [PATCH 11/13] feat: add show_amount_in_company_currency in gl report (cherry picked from commit 468e5e9b2e173ac0df49d7febe8fc0d3968217be) # Conflicts: # erpnext/accounts/report/general_ledger/general_ledger.js --- .../report/general_ledger/general_ledger.js | 5 +++++ .../report/general_ledger/general_ledger.py | 13 +++++++++++++ erpnext/accounts/report/utils.py | 2 +- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.js b/erpnext/accounts/report/general_ledger/general_ledger.js index 188199292f2..38f9eba4f90 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.js +++ b/erpnext/accounts/report/general_ledger/general_ledger.js @@ -197,6 +197,11 @@ frappe.query_reports["General Ledger"] = { label: __("Show Net Values in Party Account"), fieldtype: "Check", }, + { + fieldname: "show_amount_in_company_currency", + label: __("Show Credit / Debit in Company Currency"), + fieldtype: "Check", + }, { fieldname: "show_remarks", label: __("Show Remarks"), diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 0ae8a6070a1..275e0b7e41b 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -580,6 +580,19 @@ def get_columns(filters): company = filters.get("company") or get_default_company() filters["presentation_currency"] = currency = get_company_currency(company) + company_currency = get_company_currency(filters.get("company") or get_default_company()) + + if ( + filters.get("show_amount_in_company_currency") + and filters["presentation_currency"] != company_currency + ): + frappe.throw( + _("Presentation Currency cannot be {0} , When {1} is enabled.").format( + frappe.bold(filters["presentation_currency"]), + frappe.bold("Show Credit / Debit in Company Currency"), + ) + ) + columns = [ { "label": _("GL Entry"), diff --git a/erpnext/accounts/report/utils.py b/erpnext/accounts/report/utils.py index 2129f553c8c..92c305e6cd8 100644 --- a/erpnext/accounts/report/utils.py +++ b/erpnext/accounts/report/utils.py @@ -118,7 +118,7 @@ def convert_to_presentation_currency(gl_entries, currency_info, filters=None): len(account_currencies) == 1 and account_currency == presentation_currency and not exchange_gain_or_loss - ): + ) and not filters.get("show_amount_in_company_currency"): entry["debit"] = debit_in_account_currency entry["credit"] = credit_in_account_currency else: From 388b5fb8f6155040f6d7b23fbfca0c1c72c450b9 Mon Sep 17 00:00:00 2001 From: venkat102 Date: Fri, 1 Aug 2025 01:12:39 +0530 Subject: [PATCH 12/13] fix: do not split round off when there is a cost center allocation (cherry picked from commit f0df41d521c161a26257b0ea7321f5bcc67f05c7) --- erpnext/accounts/general_ledger.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index f2bc8b3a2f8..6dc645538f1 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -179,6 +179,15 @@ def process_gl_map(gl_map, merge_entries=True, precision=None): def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None): + round_off_account, default_currency = frappe.get_cached_value( + "Company", gl_map[0].company, ["round_off_account", "default_currency"] + ) + if not precision: + precision = get_field_precision( + frappe.get_meta("GL Entry").get_field("debit"), + currency=default_currency, + ) + new_gl_map = [] for d in gl_map: cost_center = d.get("cost_center") @@ -192,6 +201,11 @@ def distribute_gl_based_on_cost_center_allocation(gl_map, precision=None): new_gl_map.append(d) continue + if d.account == round_off_account: + d.cost_center = cost_center_allocation[0][0] + new_gl_map.append(d) + continue + for sub_cost_center, percentage in cost_center_allocation: gle = copy.deepcopy(d) gle.cost_center = sub_cost_center From 7a9150aac079d7c44045085695715b970ed4b94c Mon Sep 17 00:00:00 2001 From: ravibharathi656 Date: Tue, 5 Aug 2025 17:58:33 +0530 Subject: [PATCH 13/13] test: add test for cost center allocation commercial rounding (cherry picked from commit dd24cce5098be0d3abb15600b5d374559120a9ea) # Conflicts: # erpnext/accounts/doctype/cost_center_allocation/test_cost_center_allocation.py --- .../test_cost_center_allocation.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/erpnext/accounts/doctype/cost_center_allocation/test_cost_center_allocation.py b/erpnext/accounts/doctype/cost_center_allocation/test_cost_center_allocation.py index 4abc82d8bec..dc73242ac06 100644 --- a/erpnext/accounts/doctype/cost_center_allocation/test_cost_center_allocation.py +++ b/erpnext/accounts/doctype/cost_center_allocation/test_cost_center_allocation.py @@ -4,6 +4,8 @@ import unittest import frappe +from frappe.query_builder.functions import Sum +from frappe.tests.utils import change_settings from frappe.utils import add_days, today from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center @@ -190,6 +192,31 @@ class TestCostCenterAllocation(unittest.TestCase): coa2.cancel() jv.cancel() + @change_settings("System Settings", {"rounding_method": "Commercial Rounding"}) + def test_debit_credit_on_cost_center_allocation_for_commercial_rounding(self): + from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice + + cca = create_cost_center_allocation( + "_Test Company", + "Main Cost Center 1 - _TC", + {"Sub Cost Center 2 - _TC": 50, "Sub Cost Center 3 - _TC": 50}, + ) + + si = create_sales_invoice(rate=145.65, cost_center="Main Cost Center 1 - _TC") + + gl_entry = frappe.qb.DocType("GL Entry") + gl_entries = ( + frappe.qb.from_(gl_entry) + .select(Sum(gl_entry.credit).as_("cr"), Sum(gl_entry.debit).as_("dr")) + .where(gl_entry.voucher_type == "Sales Invoice") + .where(gl_entry.voucher_no == si.name) + ).run(as_dict=1) + + self.assertEqual(gl_entries[0].cr, gl_entries[0].dr) + + si.cancel() + cca.cancel() + def create_cost_center_allocation( company,