From 2af2002431e2ebf330273823c47e1b154e28ad89 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Wed, 6 Aug 2025 09:56:39 +0530 Subject: [PATCH 1/6] chore: resolve linting issue --- .../v15_0/repost_gl_entries_with_no_account_subcontracting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v15_0/repost_gl_entries_with_no_account_subcontracting.py b/erpnext/patches/v15_0/repost_gl_entries_with_no_account_subcontracting.py index 1c7d1cc471a..0bb47973194 100644 --- a/erpnext/patches/v15_0/repost_gl_entries_with_no_account_subcontracting.py +++ b/erpnext/patches/v15_0/repost_gl_entries_with_no_account_subcontracting.py @@ -29,4 +29,4 @@ def execute(): if docs: cancel_incorrect_gl_entries([d.name for d in docs]) - recreate_gl_entries([d.voucher_no for d in docs]) \ No newline at end of file + recreate_gl_entries([d.voucher_no for d in docs]) From 5266690cd8f99f198d4d918d635cc67707fc5630 Mon Sep 17 00:00:00 2001 From: Asmita Hase Date: Wed, 6 Aug 2025 10:34:48 +0530 Subject: [PATCH 2/6] refactor: get advance payment doctypes from hooks (cherry picked from commit 2cb2e05b19f140fef59331e9a3c95b7a0175feb6) --- .../advance_payment_ledger_entry.py | 4 ++-- erpnext/accounts/utils.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.py b/erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.py index a9392fc9367..fa863741d51 100644 --- a/erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.py +++ b/erpnext/accounts/doctype/advance_payment_ledger_entry/advance_payment_ledger_entry.py @@ -4,7 +4,7 @@ import frappe from frappe.model.document import Document -from erpnext.accounts.utils import update_voucher_outstanding +from erpnext.accounts.utils import get_advance_payment_doctypes, update_voucher_outstanding class AdvancePaymentLedgerEntry(Document): @@ -29,7 +29,7 @@ class AdvancePaymentLedgerEntry(Document): def on_update(self): if ( - self.against_voucher_type in ["Purchase Order", "Sales Order"] + self.against_voucher_type in get_advance_payment_doctypes() and self.flags.update_outstanding == "Yes" and not frappe.flags.is_reverse_depr_entry ): diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index 36fe32b0381..befe7568c1a 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -470,7 +470,6 @@ def reconcile_against_document( reconciled_entries[(row.voucher_type, row.voucher_no)] = [] reconciled_entries[(row.voucher_type, row.voucher_no)].append(row) - for key, entries in reconciled_entries.items(): voucher_type, voucher_no = key @@ -1805,6 +1804,7 @@ def get_payment_ledger_entries(gl_entries, cancel=0): dr_or_cr = 0 account_type = None + for gle in gl_entries: if gle.account in receivable_or_payable_accounts: account_type = get_account_type(gle.account) @@ -1909,7 +1909,8 @@ def update_voucher_outstanding(voucher_type, voucher_no, account, party_type, pa if not voucher_type or not voucher_no: return - if voucher_type in ["Purchase Order", "Sales Order"]: + # todo use get advanced dotypes hooks + if voucher_type in get_advance_payment_doctypes(): ref_doc = frappe.get_lazy_doc(voucher_type, voucher_no) ref_doc.set_total_advance_paid() return From 4cc9061990f50c9f4b9497933d5a30a6abb2e77a Mon Sep 17 00:00:00 2001 From: Asmita Hase Date: Wed, 6 Aug 2025 10:36:18 +0530 Subject: [PATCH 3/6] chore: add account type to employee advance account in standard chart of accounts (cherry picked from commit a273147b6ea4e71c78e507f1c563abf1e120651a) --- .../chart_of_accounts/verified/standard_chart_of_accounts.py | 2 +- .../verified/standard_chart_of_accounts_with_account_number.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py index 5a5e232db8d..9434b2115c3 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts.py @@ -13,7 +13,7 @@ def get(): _("Bank Accounts"): {"account_type": "Bank", "is_group": 1}, _("Cash In Hand"): {_("Cash"): {"account_type": "Cash"}, "account_type": "Cash"}, _("Loans and Advances (Assets)"): { - _("Employee Advances"): {}, + _("Employee Advances"): {"account_type": "Payable"}, }, _("Securities and Deposits"): {_("Earnest Money"): {}}, _("Stock Assets"): { diff --git a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py index 0e46f1e08a5..09e5141c904 100644 --- a/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py +++ b/erpnext/accounts/doctype/account/chart_of_accounts/verified/standard_chart_of_accounts_with_account_number.py @@ -20,7 +20,7 @@ def get(): "account_number": "1100", }, _("Loans and Advances (Assets)"): { - _("Employee Advances"): {"account_number": "1610"}, + _("Employee Advances"): {"account_number": "1610", "account_type": "Payable"}, "account_number": "1600", }, _("Securities and Deposits"): { From 2d420ed6617ed452f0925ec90f33480e40e05d98 Mon Sep 17 00:00:00 2001 From: Asmita Hase Date: Wed, 6 Aug 2025 10:42:47 +0530 Subject: [PATCH 4/6] chore: removed uncessary comment (cherry picked from commit b4f831a93137ad9fdc1cb83f777d006730a408aa) --- erpnext/accounts/utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/erpnext/accounts/utils.py b/erpnext/accounts/utils.py index befe7568c1a..25c31b9deaa 100644 --- a/erpnext/accounts/utils.py +++ b/erpnext/accounts/utils.py @@ -1909,7 +1909,6 @@ def update_voucher_outstanding(voucher_type, voucher_no, account, party_type, pa if not voucher_type or not voucher_no: return - # todo use get advanced dotypes hooks if voucher_type in get_advance_payment_doctypes(): ref_doc = frappe.get_lazy_doc(voucher_type, voucher_no) ref_doc.set_total_advance_paid() From 5224b6677ddedc7d29a815130a258b9c39d4540f Mon Sep 17 00:00:00 2001 From: khushi8112 Date: Wed, 6 Aug 2025 16:47:01 +0530 Subject: [PATCH 5/6] fix: fetch revaluated asset value for all the assets (cherry picked from commit 67ec4fa47740baa57e094982af9213accc407fd7) --- .../fixed_asset_register.py | 72 +++++++++++++++++-- 1 file changed, 68 insertions(+), 4 deletions(-) diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py index 2b4c55d6ec8..224cdff3f44 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -96,10 +96,14 @@ def get_data(filters): depreciation_amount_map = get_asset_depreciation_amount_map(filters, finance_book) + revaluation_amount_map = get_asset_value_adjustment_map(filters, finance_book) + group_by = frappe.scrub(filters.get("group_by")) if group_by in ("asset_category", "location"): - data = get_group_by_data(group_by, conditions, assets_linked_to_fb, depreciation_amount_map) + data = get_group_by_data( + group_by, conditions, assets_linked_to_fb, depreciation_amount_map, revaluation_amount_map + ) return data fields = [ @@ -126,8 +130,12 @@ def get_data(filters): continue depreciation_amount = depreciation_amount_map.get(asset.asset_id) or 0.0 + revaluation_amount = revaluation_amount_map.get(asset.asset_id, 0.0) asset_value = ( - asset.gross_purchase_amount - asset.opening_accumulated_depreciation - depreciation_amount + asset.gross_purchase_amount + - asset.opening_accumulated_depreciation + - depreciation_amount + + revaluation_amount ) row = { @@ -290,7 +298,59 @@ def get_asset_depreciation_amount_map(filters, finance_book): return dict(asset_depr_amount_map) -def get_group_by_data(group_by, conditions, assets_linked_to_fb, depreciation_amount_map): +def get_asset_value_adjustment_map(filters, finance_book): + start_date = filters.from_date if filters.filter_based_on == "Date Range" else filters.year_start_date + end_date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date + + asset = frappe.qb.DocType("Asset") + gle = frappe.qb.DocType("GL Entry") + aca = frappe.qb.DocType("Asset Category Account") + company = frappe.qb.DocType("Company") + + query = ( + frappe.qb.from_(gle) + .join(asset) + .on(gle.against_voucher == asset.name) + .join(aca) + .on((aca.parent == asset.asset_category) & (aca.company_name == asset.company)) + .join(company) + .on(company.name == asset.company) + .select(asset.name.as_("asset"), Sum(gle.debit - gle.credit).as_("adjustment_amount")) + .where(gle.account == aca.fixed_asset_account) + .where(gle.is_cancelled == 0) + .where(company.name == filters.company) + .where(asset.docstatus == 1) + ) + + if filters.only_existing_assets: + query = query.where(asset.is_existing_asset == 1) + if filters.asset_category: + query = query.where(asset.asset_category == filters.asset_category) + if filters.cost_center: + query = query.where(asset.cost_center == filters.cost_center) + if filters.status: + if filters.status == "In Location": + query = query.where(asset.status.notin(["Sold", "Scrapped", "Capitalized"])) + else: + query = query.where(asset.status.isin(["Sold", "Scrapped", "Capitalized"])) + if finance_book: + query = query.where((gle.finance_book.isin([cstr(finance_book), ""])) | (gle.finance_book.isnull())) + else: + query = query.where((gle.finance_book.isin([""])) | (gle.finance_book.isnull())) + if filters.filter_based_on in ("Date Range", "Fiscal Year"): + query = query.where(gle.posting_date >= start_date) + query = query.where(gle.posting_date <= end_date) + + query = query.groupby(asset.name) + + asset_adjustment_map = query.run() + + return dict(asset_adjustment_map) + + +def get_group_by_data( + group_by, conditions, assets_linked_to_fb, depreciation_amount_map, revaluation_amount_map +): fields = [ group_by, "name", @@ -307,8 +367,12 @@ def get_group_by_data(group_by, conditions, assets_linked_to_fb, depreciation_am continue a["depreciated_amount"] = depreciation_amount_map.get(a["name"], 0.0) + a["revaluation_amount"] = revaluation_amount_map.get(a["name"], 0.0) a["asset_value"] = ( - a["gross_purchase_amount"] - a["opening_accumulated_depreciation"] - a["depreciated_amount"] + a["gross_purchase_amount"] + - a["opening_accumulated_depreciation"] + - a["depreciated_amount"] + + a["revaluation_amount"] ) del a["name"] From e1121d1c687e38f4541027446a4a9fe45702d86b Mon Sep 17 00:00:00 2001 From: khushi8112 Date: Wed, 6 Aug 2025 16:48:09 +0530 Subject: [PATCH 6/6] chore: format code (cherry picked from commit a33bcb47b3918629df803439f64a9ae6a0cfd432) --- .../fixed_asset_register.py | 90 +++++++++---------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py index 224cdff3f44..dfb33c55ef7 100644 --- a/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py +++ b/erpnext/assets/report/fixed_asset_register/fixed_asset_register.py @@ -31,51 +31,6 @@ def execute(filters=None): return columns, data, None, chart -def get_conditions(filters): - conditions = {"docstatus": 1} - status = filters.status - date_field = frappe.scrub(filters.date_based_on or "Purchase Date") - - if filters.get("company"): - conditions["company"] = filters.company - - if filters.filter_based_on == "Date Range": - if not filters.from_date and not filters.to_date: - filters.from_date = add_months(nowdate(), -12) - filters.to_date = nowdate() - - conditions[date_field] = ["between", [filters.from_date, filters.to_date]] - elif filters.filter_based_on == "Fiscal Year": - if not filters.from_fiscal_year and not filters.to_fiscal_year: - default_fiscal_year = get_fiscal_year(today())[0] - filters.from_fiscal_year = default_fiscal_year - filters.to_fiscal_year = default_fiscal_year - - fiscal_year = get_fiscal_year_data(filters.from_fiscal_year, filters.to_fiscal_year) - validate_fiscal_year(fiscal_year, filters.from_fiscal_year, filters.to_fiscal_year) - filters.year_start_date = getdate(fiscal_year.year_start_date) - filters.year_end_date = getdate(fiscal_year.year_end_date) - - conditions[date_field] = ["between", [filters.year_start_date, filters.year_end_date]] - - if filters.get("only_existing_assets"): - conditions["is_existing_asset"] = filters.get("only_existing_assets") - if filters.get("asset_category"): - conditions["asset_category"] = filters.get("asset_category") - if filters.get("cost_center"): - conditions["cost_center"] = filters.get("cost_center") - - if status: - # In Store assets are those that are not sold or scrapped or capitalized - operand = "not in" - if status not in "In Location": - operand = "in" - - conditions["status"] = (operand, ["Sold", "Scrapped", "Capitalized"]) - - return conditions - - def get_data(filters): data = [] @@ -161,6 +116,51 @@ def get_data(filters): return data +def get_conditions(filters): + conditions = {"docstatus": 1} + status = filters.status + date_field = frappe.scrub(filters.date_based_on or "Purchase Date") + + if filters.get("company"): + conditions["company"] = filters.company + + if filters.filter_based_on == "Date Range": + if not filters.from_date and not filters.to_date: + filters.from_date = add_months(nowdate(), -12) + filters.to_date = nowdate() + + conditions[date_field] = ["between", [filters.from_date, filters.to_date]] + elif filters.filter_based_on == "Fiscal Year": + if not filters.from_fiscal_year and not filters.to_fiscal_year: + default_fiscal_year = get_fiscal_year(today())[0] + filters.from_fiscal_year = default_fiscal_year + filters.to_fiscal_year = default_fiscal_year + + fiscal_year = get_fiscal_year_data(filters.from_fiscal_year, filters.to_fiscal_year) + validate_fiscal_year(fiscal_year, filters.from_fiscal_year, filters.to_fiscal_year) + filters.year_start_date = getdate(fiscal_year.year_start_date) + filters.year_end_date = getdate(fiscal_year.year_end_date) + + conditions[date_field] = ["between", [filters.year_start_date, filters.year_end_date]] + + if filters.get("only_existing_assets"): + conditions["is_existing_asset"] = filters.get("only_existing_assets") + if filters.get("asset_category"): + conditions["asset_category"] = filters.get("asset_category") + if filters.get("cost_center"): + conditions["cost_center"] = filters.get("cost_center") + + if status: + # In Store assets are those that are not sold or scrapped or capitalized + operand = "not in" + if status not in "In Location": + operand = "in" + + conditions["status"] = (operand, ["Sold", "Scrapped", "Capitalized"]) + + return conditions + + def prepare_chart_data(data, filters): if not data: return