From 9985a03f392d36a20faabcfcfb764184484f42ec Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 21 Jan 2025 13:45:25 +0530 Subject: [PATCH 01/14] perf: Ignore is_opening column in GL Queries (#45327) * perf: Ignore is_opening column in GL Queries * chore: Remove unwanted changes * chore: Remove unwanted changes * chore: Remove unwanted changes * chore: Remove unwanted changes * chore: Remove unwanted changes * chore: Remove unwanted changes (cherry picked from commit 993f40fa431a6a9644c53d57109c4780919778cb) # Conflicts: # erpnext/accounts/doctype/accounts_settings/accounts_settings.json # erpnext/accounts/doctype/accounts_settings/accounts_settings.py --- .../accounts_settings/accounts_settings.json | 65 +++++++++++++++++++ .../accounts_settings/accounts_settings.py | 55 ++++++++++++++++ .../accounts/report/financial_statements.py | 6 +- .../report/general_ledger/general_ledger.py | 14 +++- .../report/trial_balance/trial_balance.json | 6 +- .../report/trial_balance/trial_balance.py | 59 ++++++++++++----- 6 files changed, 184 insertions(+), 21 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index 16c5479c210..cb7e493e28c 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -73,6 +73,7 @@ "reports_tab", "remarks_section", "general_ledger_remarks_length", + "ignore_is_opening_check_for_reporting", "column_break_lvjk", "receivable_payable_remarks_length" ], @@ -465,12 +466,72 @@ "label": "Remarks Column Length" }, { +<<<<<<< HEAD "default": "Payment", "description": "Only applies for Normal Payments", "fieldname": "exchange_gain_loss_posting_date", "fieldtype": "Select", "label": "Posting Date Inheritance for Exchange Gain / Loss", "options": "Invoice\nPayment\nReconciliation Date" +======= + "default": "0", + "description": "On enabling this cancellation entries will be posted on the actual cancellation date and reports will consider cancelled entries as well", + "fieldname": "enable_immutable_ledger", + "fieldtype": "Check", + "label": "Enable Immutable Ledger" + }, + { + "fieldname": "column_break_gjcc", + "fieldtype": "Column Break" + }, + { + "default": "0", + "description": "Enable this option to calculate daily depreciation by considering the total number of days in the entire depreciation period, (including leap years) while using daily pro-rata based depreciation", + "fieldname": "calculate_depr_using_total_days", + "fieldtype": "Check", + "label": "Calculate daily depreciation using total days in depreciation period" + }, + { + "description": "Payment Request created from Sales Order or Purchase Order will be in Draft status. When disabled document will be in unsaved state.", + "fieldname": "payment_request_settings", + "fieldtype": "Tab Break", + "label": "Payment Request" + }, + { + "default": "1", + "fieldname": "create_pr_in_draft_status", + "fieldtype": "Check", + "label": "Create in Draft Status" + }, + { + "fieldname": "column_break_yuug", + "fieldtype": "Column Break" + }, + { + "fieldname": "column_break_resa", + "fieldtype": "Column Break" + }, + { + "default": "15", + "description": "Interval should be between 1 to 59 MInutes", + "fieldname": "auto_reconciliation_job_trigger", + "fieldtype": "Int", + "label": "Auto Reconciliation Job Trigger" + }, + { + "default": "5", + "description": "Documents Processed on each trigger. Queue Size should be between 5 and 100", + "fieldname": "reconciliation_queue_size", + "fieldtype": "Int", + "label": "Reconciliation Queue Size" + }, + { + "default": "0", + "description": "Ignores legacy Is Opening field in GL Entry that allows adding opening balance post the system is in use while generating reports", + "fieldname": "ignore_is_opening_check_for_reporting", + "fieldtype": "Check", + "label": "Ignore Is Opening check for reporting" +>>>>>>> 993f40fa43 (perf: Ignore is_opening column in GL Queries (#45327)) } ], "icon": "icon-cog", @@ -478,7 +539,11 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], +<<<<<<< HEAD "modified": "2025-01-23 13:15:44.077853", +======= + "modified": "2025-01-18 21:24:19.840745", +>>>>>>> 993f40fa43 (perf: Ignore is_opening column in GL Queries (#45327)) "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index ac3d44bb5e7..d9fcd33b1b0 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -14,6 +14,61 @@ from erpnext.stock.utils import check_pending_reposting class AccountsSettings(Document): +<<<<<<< HEAD +======= + # begin: auto-generated types + # This code is auto-generated. Do not modify anything in this block. + + from typing import TYPE_CHECKING + + if TYPE_CHECKING: + from frappe.types import DF + + acc_frozen_upto: DF.Date | None + add_taxes_from_item_tax_template: DF.Check + allow_multi_currency_invoices_against_single_party_account: DF.Check + allow_stale: DF.Check + auto_reconcile_payments: DF.Check + auto_reconciliation_job_trigger: DF.Int + automatically_fetch_payment_terms: DF.Check + automatically_process_deferred_accounting_entry: DF.Check + book_asset_depreciation_entry_automatically: DF.Check + book_deferred_entries_based_on: DF.Literal["Days", "Months"] + book_deferred_entries_via_journal_entry: DF.Check + book_tax_discount_loss: DF.Check + calculate_depr_using_total_days: DF.Check + check_supplier_invoice_uniqueness: DF.Check + create_pr_in_draft_status: DF.Check + credit_controller: DF.Link | None + delete_linked_ledger_entries: DF.Check + determine_address_tax_category_from: DF.Literal["Billing Address", "Shipping Address"] + enable_common_party_accounting: DF.Check + enable_fuzzy_matching: DF.Check + enable_immutable_ledger: DF.Check + enable_party_matching: DF.Check + frozen_accounts_modifier: DF.Link | None + general_ledger_remarks_length: DF.Int + ignore_account_closing_balance: DF.Check + ignore_is_opening_check_for_reporting: DF.Check + make_payment_via_journal_entry: DF.Check + merge_similar_account_heads: DF.Check + over_billing_allowance: DF.Currency + post_change_gl_entries: DF.Check + receivable_payable_remarks_length: DF.Int + reconciliation_queue_size: DF.Int + role_allowed_to_over_bill: DF.Link | None + round_row_wise_tax: DF.Check + show_balance_in_coa: DF.Check + show_inclusive_tax_in_print: DF.Check + show_payment_schedule_in_print: DF.Check + show_taxes_as_table_in_print: DF.Check + stale_days: DF.Int + submit_journal_entries: DF.Check + unlink_advance_payment_on_cancelation_of_order: DF.Check + unlink_payment_on_cancellation_of_invoice: DF.Check + # end: auto-generated types + +>>>>>>> 993f40fa43 (perf: Ignore is_opening column in GL Queries (#45327)) def validate(self): old_doc = self.get_doc_before_save() clear_cache = False diff --git a/erpnext/accounts/report/financial_statements.py b/erpnext/accounts/report/financial_statements.py index 02f9c827b52..cd70639d2f0 100644 --- a/erpnext/accounts/report/financial_statements.py +++ b/erpnext/accounts/report/financial_statements.py @@ -512,12 +512,16 @@ def get_accounting_entries( .where(gl_entry.company == filters.company) ) + ignore_is_opening = frappe.db.get_single_value( + "Accounts Settings", "ignore_is_opening_check_for_reporting" + ) + if doctype == "GL Entry": query = query.select(gl_entry.posting_date, gl_entry.is_opening, gl_entry.fiscal_year) query = query.where(gl_entry.is_cancelled == 0) query = query.where(gl_entry.posting_date <= to_date) - if ignore_opening_entries: + if ignore_opening_entries and not ignore_is_opening: query = query.where(gl_entry.is_opening == "No") else: query = query.select(gl_entry.closing_date.as_("posting_date")) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 0436dc51214..aa06dffb043 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -209,6 +209,10 @@ def get_gl_entries(filters, accounting_dimensions): def get_conditions(filters): conditions = [] + ignore_is_opening = frappe.db.get_single_value( + "Accounts Settings", "ignore_is_opening_check_for_reporting" + ) + if filters.get("account"): filters.account = get_accounts_with_children(filters.account) if filters.account: @@ -268,9 +272,15 @@ def get_conditions(filters): or filters.get("party") or filters.get("group_by") in ["Group by Account", "Group by Party"] ): - conditions.append("(posting_date >=%(from_date)s or is_opening = 'Yes')") + if not ignore_is_opening: + conditions.append("(posting_date >=%(from_date)s or is_opening = 'Yes')") + else: + conditions.append("posting_date >=%(from_date)s") - conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") + if not ignore_is_opening: + conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") + else: + conditions.append("posting_date <=%(to_date)s") if filters.get("project"): conditions.append("project in %(project)s") diff --git a/erpnext/accounts/report/trial_balance/trial_balance.json b/erpnext/accounts/report/trial_balance/trial_balance.json index 8ed96a7161a..af586f7f17d 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.json +++ b/erpnext/accounts/report/trial_balance/trial_balance.json @@ -14,14 +14,14 @@ "owner": "Administrator", "ref_doctype": "GL Entry", "report_name": "Trial Balance", - "report_type": "Script Report", + "report_type": "Script Report", "roles": [ { "role": "Accounts User" - }, + }, { "role": "Accounts Manager" - }, + }, { "role": "Auditor" } diff --git a/erpnext/accounts/report/trial_balance/trial_balance.py b/erpnext/accounts/report/trial_balance/trial_balance.py index e65f479f056..4ae314bdff7 100644 --- a/erpnext/accounts/report/trial_balance/trial_balance.py +++ b/erpnext/accounts/report/trial_balance/trial_balance.py @@ -89,6 +89,10 @@ def get_data(filters): ) company_currency = filters.presentation_currency or erpnext.get_company_currency(filters.company) + ignore_is_opening = frappe.db.get_single_value( + "Accounts Settings", "ignore_is_opening_check_for_reporting" + ) + if not accounts: return None @@ -102,7 +106,7 @@ def get_data(filters): gl_entries_by_account = {} - opening_balances = get_opening_balances(filters) + opening_balances = get_opening_balances(filters, ignore_is_opening) # add filter inside list so that the query in financial_statements.py doesn't break if filters.project: @@ -120,7 +124,13 @@ def get_data(filters): ignore_opening_entries=True, ) - calculate_values(accounts, gl_entries_by_account, opening_balances, filters.get("show_net_values")) + calculate_values( + accounts, + gl_entries_by_account, + opening_balances, + filters.get("show_net_values"), + ignore_is_opening=ignore_is_opening, + ) accumulate_values_into_parents(accounts, accounts_by_name) data = prepare_data(accounts, filters, parent_children_map, company_currency) @@ -131,15 +141,15 @@ def get_data(filters): return data -def get_opening_balances(filters): - balance_sheet_opening = get_rootwise_opening_balances(filters, "Balance Sheet") - pl_opening = get_rootwise_opening_balances(filters, "Profit and Loss") +def get_opening_balances(filters, ignore_is_opening): + balance_sheet_opening = get_rootwise_opening_balances(filters, "Balance Sheet", ignore_is_opening) + pl_opening = get_rootwise_opening_balances(filters, "Profit and Loss", ignore_is_opening) balance_sheet_opening.update(pl_opening) return balance_sheet_opening -def get_rootwise_opening_balances(filters, report_type): +def get_rootwise_opening_balances(filters, report_type, ignore_is_opening): gle = [] last_period_closing_voucher = "" @@ -165,16 +175,24 @@ def get_rootwise_opening_balances(filters, report_type): report_type, accounting_dimensions, period_closing_voucher=last_period_closing_voucher[0].name, + ignore_is_opening=ignore_is_opening, ) # Report getting generate from the mid of a fiscal year if getdate(last_period_closing_voucher[0].posting_date) < getdate(add_days(filters.from_date, -1)): start_date = add_days(last_period_closing_voucher[0].posting_date, 1) gle += get_opening_balance( - "GL Entry", filters, report_type, accounting_dimensions, start_date=start_date + "GL Entry", + filters, + report_type, + accounting_dimensions, + start_date=start_date, + ignore_is_opening=ignore_is_opening, ) else: - gle = get_opening_balance("GL Entry", filters, report_type, accounting_dimensions) + gle = get_opening_balance( + "GL Entry", filters, report_type, accounting_dimensions, ignore_is_opening=ignore_is_opening + ) opening = frappe._dict() for d in gle: @@ -193,7 +211,13 @@ def get_rootwise_opening_balances(filters, report_type): def get_opening_balance( - doctype, filters, report_type, accounting_dimensions, period_closing_voucher=None, start_date=None + doctype, + filters, + report_type, + accounting_dimensions, + period_closing_voucher=None, + start_date=None, + ignore_is_opening=0, ): closing_balance = frappe.qb.DocType(doctype) account = frappe.qb.DocType("Account") @@ -229,11 +253,16 @@ def get_opening_balance( (closing_balance.posting_date >= start_date) & (closing_balance.posting_date < filters.from_date) ) - opening_balance = opening_balance.where(closing_balance.is_opening == "No") + + if not ignore_is_opening: + opening_balance = opening_balance.where(closing_balance.is_opening == "No") else: - opening_balance = opening_balance.where( - (closing_balance.posting_date < filters.from_date) | (closing_balance.is_opening == "Yes") - ) + if not ignore_is_opening: + opening_balance = opening_balance.where( + (closing_balance.posting_date < filters.from_date) | (closing_balance.is_opening == "Yes") + ) + else: + opening_balance = opening_balance.where(closing_balance.posting_date < filters.from_date) if doctype == "GL Entry": opening_balance = opening_balance.where(closing_balance.is_cancelled == 0) @@ -304,7 +333,7 @@ def get_opening_balance( return gle -def calculate_values(accounts, gl_entries_by_account, opening_balances, show_net_values): +def calculate_values(accounts, gl_entries_by_account, opening_balances, show_net_values, ignore_is_opening=0): init = { "opening_debit": 0.0, "opening_credit": 0.0, @@ -322,7 +351,7 @@ def calculate_values(accounts, gl_entries_by_account, opening_balances, show_net d["opening_credit"] = opening_balances.get(d.name, {}).get("opening_credit", 0) for entry in gl_entries_by_account.get(d.name, []): - if cstr(entry.is_opening) != "Yes": + if cstr(entry.is_opening) != "Yes" or ignore_is_opening: d["debit"] += flt(entry.debit) d["credit"] += flt(entry.credit) From 222bd9351d02fbe902c2e2f54fb70421caf834d1 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 7 Feb 2025 15:38:23 +0530 Subject: [PATCH 02/14] chore: resolve conflicts --- .../accounts_settings/accounts_settings.json | 57 ------------------- .../accounts_settings/accounts_settings.py | 55 ------------------ 2 files changed, 112 deletions(-) diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json index cb7e493e28c..db1926b77cf 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.json +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.json @@ -466,64 +466,12 @@ "label": "Remarks Column Length" }, { -<<<<<<< HEAD "default": "Payment", "description": "Only applies for Normal Payments", "fieldname": "exchange_gain_loss_posting_date", "fieldtype": "Select", "label": "Posting Date Inheritance for Exchange Gain / Loss", "options": "Invoice\nPayment\nReconciliation Date" -======= - "default": "0", - "description": "On enabling this cancellation entries will be posted on the actual cancellation date and reports will consider cancelled entries as well", - "fieldname": "enable_immutable_ledger", - "fieldtype": "Check", - "label": "Enable Immutable Ledger" - }, - { - "fieldname": "column_break_gjcc", - "fieldtype": "Column Break" - }, - { - "default": "0", - "description": "Enable this option to calculate daily depreciation by considering the total number of days in the entire depreciation period, (including leap years) while using daily pro-rata based depreciation", - "fieldname": "calculate_depr_using_total_days", - "fieldtype": "Check", - "label": "Calculate daily depreciation using total days in depreciation period" - }, - { - "description": "Payment Request created from Sales Order or Purchase Order will be in Draft status. When disabled document will be in unsaved state.", - "fieldname": "payment_request_settings", - "fieldtype": "Tab Break", - "label": "Payment Request" - }, - { - "default": "1", - "fieldname": "create_pr_in_draft_status", - "fieldtype": "Check", - "label": "Create in Draft Status" - }, - { - "fieldname": "column_break_yuug", - "fieldtype": "Column Break" - }, - { - "fieldname": "column_break_resa", - "fieldtype": "Column Break" - }, - { - "default": "15", - "description": "Interval should be between 1 to 59 MInutes", - "fieldname": "auto_reconciliation_job_trigger", - "fieldtype": "Int", - "label": "Auto Reconciliation Job Trigger" - }, - { - "default": "5", - "description": "Documents Processed on each trigger. Queue Size should be between 5 and 100", - "fieldname": "reconciliation_queue_size", - "fieldtype": "Int", - "label": "Reconciliation Queue Size" }, { "default": "0", @@ -531,7 +479,6 @@ "fieldname": "ignore_is_opening_check_for_reporting", "fieldtype": "Check", "label": "Ignore Is Opening check for reporting" ->>>>>>> 993f40fa43 (perf: Ignore is_opening column in GL Queries (#45327)) } ], "icon": "icon-cog", @@ -539,11 +486,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], -<<<<<<< HEAD "modified": "2025-01-23 13:15:44.077853", -======= - "modified": "2025-01-18 21:24:19.840745", ->>>>>>> 993f40fa43 (perf: Ignore is_opening column in GL Queries (#45327)) "modified_by": "Administrator", "module": "Accounts", "name": "Accounts Settings", diff --git a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py index d9fcd33b1b0..ac3d44bb5e7 100644 --- a/erpnext/accounts/doctype/accounts_settings/accounts_settings.py +++ b/erpnext/accounts/doctype/accounts_settings/accounts_settings.py @@ -14,61 +14,6 @@ from erpnext.stock.utils import check_pending_reposting class AccountsSettings(Document): -<<<<<<< HEAD -======= - # begin: auto-generated types - # This code is auto-generated. Do not modify anything in this block. - - from typing import TYPE_CHECKING - - if TYPE_CHECKING: - from frappe.types import DF - - acc_frozen_upto: DF.Date | None - add_taxes_from_item_tax_template: DF.Check - allow_multi_currency_invoices_against_single_party_account: DF.Check - allow_stale: DF.Check - auto_reconcile_payments: DF.Check - auto_reconciliation_job_trigger: DF.Int - automatically_fetch_payment_terms: DF.Check - automatically_process_deferred_accounting_entry: DF.Check - book_asset_depreciation_entry_automatically: DF.Check - book_deferred_entries_based_on: DF.Literal["Days", "Months"] - book_deferred_entries_via_journal_entry: DF.Check - book_tax_discount_loss: DF.Check - calculate_depr_using_total_days: DF.Check - check_supplier_invoice_uniqueness: DF.Check - create_pr_in_draft_status: DF.Check - credit_controller: DF.Link | None - delete_linked_ledger_entries: DF.Check - determine_address_tax_category_from: DF.Literal["Billing Address", "Shipping Address"] - enable_common_party_accounting: DF.Check - enable_fuzzy_matching: DF.Check - enable_immutable_ledger: DF.Check - enable_party_matching: DF.Check - frozen_accounts_modifier: DF.Link | None - general_ledger_remarks_length: DF.Int - ignore_account_closing_balance: DF.Check - ignore_is_opening_check_for_reporting: DF.Check - make_payment_via_journal_entry: DF.Check - merge_similar_account_heads: DF.Check - over_billing_allowance: DF.Currency - post_change_gl_entries: DF.Check - receivable_payable_remarks_length: DF.Int - reconciliation_queue_size: DF.Int - role_allowed_to_over_bill: DF.Link | None - round_row_wise_tax: DF.Check - show_balance_in_coa: DF.Check - show_inclusive_tax_in_print: DF.Check - show_payment_schedule_in_print: DF.Check - show_taxes_as_table_in_print: DF.Check - stale_days: DF.Int - submit_journal_entries: DF.Check - unlink_advance_payment_on_cancelation_of_order: DF.Check - unlink_payment_on_cancellation_of_invoice: DF.Check - # end: auto-generated types - ->>>>>>> 993f40fa43 (perf: Ignore is_opening column in GL Queries (#45327)) def validate(self): old_doc = self.get_doc_before_save() clear_cache = False From 573ce645b2e89c2c1dc98f74477114674fe3981c Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Thu, 6 Feb 2025 17:55:37 +0530 Subject: [PATCH 03/14] fix: update ctx to args (cherry picked from commit d4bc3d182fb7bb4409fcca949b7ff338984496f7) --- erpnext/public/js/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/public/js/utils.js b/erpnext/public/js/utils.js index b51d10666a8..c2b068b6e62 100755 --- a/erpnext/public/js/utils.js +++ b/erpnext/public/js/utils.js @@ -635,7 +635,7 @@ erpnext.utils.update_child_items = function (opts) { method: "erpnext.stock.get_item_details.get_item_details", args: { doc: frm.doc, - ctx: { + args: { item_code: this.value, set_warehouse: frm.doc.set_warehouse, customer: frm.doc.customer || frm.doc.party_name, From 91caca05bbf7347011fb68a89708c280b97b0a8e Mon Sep 17 00:00:00 2001 From: Asmita Hase Date: Fri, 7 Feb 2025 17:27:44 +0530 Subject: [PATCH 04/14] fix: unable to remove image from employee fix: employee image disappears when newly created user_id is linked to employee (cherry picked from commit 0207d2d7b69558f5a8a203a3f1036b8cd7378ac2) # Conflicts: # erpnext/setup/doctype/employee/employee.json --- erpnext/setup/doctype/employee/employee.json | 8 +++++--- erpnext/setup/doctype/employee/employee.py | 4 +--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/setup/doctype/employee/employee.json b/erpnext/setup/doctype/employee/employee.json index 8948211b2e5..c07e14fc3be 100644 --- a/erpnext/setup/doctype/employee/employee.json +++ b/erpnext/setup/doctype/employee/employee.json @@ -182,8 +182,6 @@ "read_only": 1 }, { - "fetch_from": "user_id.user_image", - "fetch_if_empty": 1, "fieldname": "image", "fieldtype": "Attach Image", "hidden": 1, @@ -824,7 +822,11 @@ "image_field": "image", "is_tree": 1, "links": [], +<<<<<<< HEAD "modified": "2024-01-03 17:36:20.984421", +======= + "modified": "2025-02-07 13:54:40.122345", +>>>>>>> 0207d2d7b6 (fix: unable to remove image from employee) "modified_by": "Administrator", "module": "Setup", "name": "Employee", @@ -873,4 +875,4 @@ "states": [], "title_field": "employee_name", "track_changes": 1 -} +} \ No newline at end of file diff --git a/erpnext/setup/doctype/employee/employee.py b/erpnext/setup/doctype/employee/employee.py index 3dc6f4b73e8..899d2cabfcd 100755 --- a/erpnext/setup/doctype/employee/employee.py +++ b/erpnext/setup/doctype/employee/employee.py @@ -65,14 +65,12 @@ class Employee(NestedSet): def validate_user_details(self): if self.user_id: - data = frappe.db.get_value("User", self.user_id, ["enabled", "user_image"], as_dict=1) + data = frappe.db.get_value("User", self.user_id, ["enabled"], as_dict=1) if not data: self.user_id = None return - if data.get("user_image") and self.image == "": - self.image = data.get("user_image") self.validate_for_enabled_user_id(data.get("enabled", 0)) self.validate_duplicate_user_id() From 256318bb1c1120a3c7a436246f98739e5828694d Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 10 Feb 2025 10:37:50 +0530 Subject: [PATCH 05/14] chore: resolve conflict --- erpnext/setup/doctype/employee/employee.json | 4 ---- 1 file changed, 4 deletions(-) diff --git a/erpnext/setup/doctype/employee/employee.json b/erpnext/setup/doctype/employee/employee.json index c07e14fc3be..22c1ce7927a 100644 --- a/erpnext/setup/doctype/employee/employee.json +++ b/erpnext/setup/doctype/employee/employee.json @@ -822,11 +822,7 @@ "image_field": "image", "is_tree": 1, "links": [], -<<<<<<< HEAD - "modified": "2024-01-03 17:36:20.984421", -======= "modified": "2025-02-07 13:54:40.122345", ->>>>>>> 0207d2d7b6 (fix: unable to remove image from employee) "modified_by": "Administrator", "module": "Setup", "name": "Employee", From 6b9dad7768a8f1878e4353451821a91fd2e5cb70 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 16:33:21 +0530 Subject: [PATCH 06/14] fix: pos numpad editable action buttons (backport #45823) (#45825) fix: pos numpad editable action buttons (#45823) (cherry picked from commit 0b9c28620faae004fd1a88774e5cbc2687b0338a) Co-authored-by: Diptanil Saha --- erpnext/selling/page/point_of_sale/pos_item_cart.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/selling/page/point_of_sale/pos_item_cart.js b/erpnext/selling/page/point_of_sale/pos_item_cart.js index e4af306a488..b29a99f0360 100644 --- a/erpnext/selling/page/point_of_sale/pos_item_cart.js +++ b/erpnext/selling/page/point_of_sale/pos_item_cart.js @@ -733,6 +733,7 @@ erpnext.PointOfSale.ItemCart = class { frappe.utils.play_sound("error"); return; } + this.highlight_numpad_btn($btn, current_action); if (first_click_event || field_to_edit_changed) { this.prev_action = current_action; @@ -778,7 +779,6 @@ erpnext.PointOfSale.ItemCart = class { this.numpad_value = current_action; } - this.highlight_numpad_btn($btn, current_action); this.events.numpad_event(this.numpad_value, this.prev_action); } From 49074aa2faa766f12a1f6cec7bfb6c7eedab81d5 Mon Sep 17 00:00:00 2001 From: Sanket322 Date: Fri, 7 Feb 2025 12:37:33 +0530 Subject: [PATCH 07/14] fix: add total row in non_grouped_invoices (cherry picked from commit 2d32ddacc3397e118ab65ffa892706589b933f63) --- .../report/gross_profit/gross_profit.py | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/erpnext/accounts/report/gross_profit/gross_profit.py b/erpnext/accounts/report/gross_profit/gross_profit.py index 07d85983a84..3ee1d4e1c14 100644 --- a/erpnext/accounts/report/gross_profit/gross_profit.py +++ b/erpnext/accounts/report/gross_profit/gross_profit.py @@ -207,15 +207,34 @@ def get_data_when_grouped_by_invoice(columns, gross_profit_data, filters, group_ def get_data_when_not_grouped_by_invoice(gross_profit_data, filters, group_wise_columns, data): - for src in gross_profit_data.grouped_data: - row = [] - for col in group_wise_columns.get(scrub(filters.group_by)): - row.append(src.get(col)) + total_base_amount = 0 + total_buying_amount = 0 - row.append(filters.currency) + group_columns = group_wise_columns.get(scrub(filters.group_by)) + + for src in gross_profit_data.grouped_data: + total_base_amount += src.base_amount or 0.00 + total_buying_amount += src.buying_amount or 0.00 + + row = [src.get(col) for col in group_columns] + [filters.currency] data.append(row) + total_gross_profit = total_base_amount - total_buying_amount + currency_precision = cint(frappe.db.get_default("currency_precision")) or 3 + gross_profit_percent = (total_gross_profit / total_base_amount * 100.0) if total_base_amount else 0 + + total_row = { + group_columns[0]: "Total", + "base_amount": total_base_amount, + "buying_amount": total_buying_amount, + "gross_profit": total_gross_profit, + "gross_profit_percent": flt(gross_profit_percent, currency_precision), + } + + total_row = [total_row.get(col, None) for col in [*group_columns, "currency"]] + data.append(total_row) + def get_columns(group_wise_columns, filters): columns = [] From 9f79da0015cf4b0435104a0dfc5273f84688b9c5 Mon Sep 17 00:00:00 2001 From: ljain112 Date: Fri, 7 Feb 2025 18:30:26 +0530 Subject: [PATCH 08/14] fix: do not validate party against Receivable and Payable account for cancelled gl entries (cherry picked from commit 0809e00455b3b94de1b3731afd096f4d77414b81) --- erpnext/accounts/doctype/gl_entry/gl_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 6ca5e6377c5..b2797fc9db3 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -83,7 +83,7 @@ class GLEntry(Document): if not self.get(k): frappe.throw(_("{0} is required").format(_(self.meta.get_label(k)))) - if not (self.party_type and self.party): + if not self.is_cancelled and not (self.party_type and self.party): account_type = frappe.get_cached_value("Account", self.account, "account_type") if account_type == "Receivable": frappe.throw( From c4358c049a1a5be99018723316d92646b2856197 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 14:52:21 +0530 Subject: [PATCH 09/14] fix: map project from rfq to supplier quotation (backport #45745) (#45827) * fix: map project from rfq to supplier quotation (cherry picked from commit d0479036bbfc72b531976809e8e8c33b2fdc61e4) * fix: add project field map from mr to rfq (cherry picked from commit 8fa39bec618dd490432c88c3e6d53ca4ae232e27) --------- Co-authored-by: HenningWendtland <156231187+HenningWendtland@users.noreply.github.com> --- .../doctype/request_for_quotation/request_for_quotation.py | 6 +++++- erpnext/stock/doctype/material_request/material_request.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py index a65fe30f050..08685f35148 100644 --- a/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py +++ b/erpnext/buying/doctype/request_for_quotation/request_for_quotation.py @@ -330,7 +330,11 @@ def make_supplier_quotation_from_rfq(source_name, target_doc=None, for_supplier= }, "Request for Quotation Item": { "doctype": "Supplier Quotation Item", - "field_map": {"name": "request_for_quotation_item", "parent": "request_for_quotation"}, + "field_map": { + "name": "request_for_quotation_item", + "parent": "request_for_quotation", + "project_name": "project", + }, }, }, target_doc, diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 9381bbb4706..310d26a52cc 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -430,7 +430,7 @@ def make_request_for_quotation(source_name, target_doc=None): "field_map": [ ["name", "material_request_item"], ["parent", "material_request"], - ["uom", "uom"], + ["project", "project_name"], ], }, }, From 46eba50c8cbb1cee03d118c09e44a6be3a7e13bb Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:41:04 +0530 Subject: [PATCH 10/14] fix: Party name in Supplier Portal for Purchase Order (backport #45772) (#45857) fix: Party name in Supplier Portal for Purchase Order (cherry picked from commit fc8663421be7499dadb1019d9db7e520a8b01f6a) Co-authored-by: ljain112 --- erpnext/templates/pages/order.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html index d9cb75ac5ac..517c5cff6ee 100644 --- a/erpnext/templates/pages/order.html +++ b/erpnext/templates/pages/order.html @@ -72,8 +72,7 @@
- {%- set party_name = doc.supplier_name if doc.doctype in ['Supplier Quotation', 'Purchase Invoice', 'Purchase - Order'] else doc.customer_name %} + {%- set party_name = doc.supplier_name if doc.doctype in ['Supplier Quotation', 'Purchase Invoice', 'Purchase Order'] else doc.customer_name %} {{ party_name }} {% if doc.contact_display and doc.contact_display != party_name %} From de14bf1010d92756c73d6c142fe2ab19663793de Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:41:39 +0530 Subject: [PATCH 11/14] fix(regional): removed payment schedule validation in sales invoice for italy (backport #45852) (#45853) fix(regional): removed payment schedule validation in sales invoice for italy (#45852) (cherry picked from commit 494310293cfd896e7b6ed6a4863a0fa3e4b2aa2b) Co-authored-by: Lakshit Jain <108322669+ljain112@users.noreply.github.com> --- erpnext/regional/italy/utils.py | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/erpnext/regional/italy/utils.py b/erpnext/regional/italy/utils.py index 1e0a8805075..43ff59a1006 100644 --- a/erpnext/regional/italy/utils.py +++ b/erpnext/regional/italy/utils.py @@ -331,22 +331,19 @@ def sales_invoice_on_submit(doc, method): ]: return - if not len(doc.payment_schedule): - frappe.throw(_("Please set the Payment Schedule"), title=_("E-Invoicing Information Missing")) - else: - for schedule in doc.payment_schedule: - if not schedule.mode_of_payment: - frappe.throw( - _("Row {0}: Please set the Mode of Payment in Payment Schedule").format(schedule.idx), - title=_("E-Invoicing Information Missing"), - ) - elif not frappe.db.get_value("Mode of Payment", schedule.mode_of_payment, "mode_of_payment_code"): - frappe.throw( - _("Row {0}: Please set the correct code on Mode of Payment {1}").format( - schedule.idx, schedule.mode_of_payment - ), - title=_("E-Invoicing Information Missing"), - ) + for schedule in doc.payment_schedule: + if not schedule.mode_of_payment: + frappe.throw( + _("Row {0}: Please set the Mode of Payment in Payment Schedule").format(schedule.idx), + title=_("E-Invoicing Information Missing"), + ) + elif not frappe.db.get_value("Mode of Payment", schedule.mode_of_payment, "mode_of_payment_code"): + frappe.throw( + _("Row {0}: Please set the correct code on Mode of Payment {1}").format( + schedule.idx, schedule.mode_of_payment + ), + title=_("E-Invoicing Information Missing"), + ) prepare_and_attach_invoice(doc) From 08ba77538b89f79316623ae1f6f0446acd2cc40b Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:42:27 +0530 Subject: [PATCH 12/14] fix: do not allow "Finance Book" in Accounting Dimensions (backport #45696) (#45855) fix: do not allow "Finance Book" in Accounting Dimensions (cherry picked from commit a44be73a98989bd53ffa6b295ac29530065e3a62) Co-authored-by: ljain112 --- .../doctype/accounting_dimension/accounting_dimension.py | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py index edddcb54df0..1af44d3f52c 100644 --- a/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py +++ b/erpnext/accounts/doctype/accounting_dimension/accounting_dimension.py @@ -25,6 +25,7 @@ class AccountingDimension(Document): "Accounting Dimension Detail", "Company", "Account", + "Finance Book", ): msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type) frappe.throw(msg) From c61e4e2ddfd9e32f9433fd65d076e2b2bce8288e Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 16:05:35 +0530 Subject: [PATCH 13/14] fix: correct amt in account currency for lcv with manually distributed charges. (backport #45532) (#45863) fix: correct amt in account currency for lcv with manually distributed charges. (cherry picked from commit db38e7bf5a8e088578f1c84b7b095ff8abdda32f) Co-authored-by: ljain112 --- .../purchase_receipt/purchase_receipt.py | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index b293a45580a..4a9e0d08bd8 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -1165,26 +1165,25 @@ def get_item_account_wise_additional_cost(purchase_document): for item in landed_cost_voucher_doc.items: if item.receipt_document == purchase_document: for account in landed_cost_voucher_doc.taxes: + exchange_rate = account.exchange_rate or 1 item_account_wise_cost.setdefault((item.item_code, item.purchase_receipt_item), {}) item_account_wise_cost[(item.item_code, item.purchase_receipt_item)].setdefault( account.expense_account, {"amount": 0.0, "base_amount": 0.0} ) - if total_item_cost > 0: - item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][ - account.expense_account - ]["amount"] += account.amount * item.get(based_on_field) / total_item_cost + item_row = item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][ + account.expense_account + ] - item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][ - account.expense_account - ]["base_amount"] += account.base_amount * item.get(based_on_field) / total_item_cost + if total_item_cost > 0: + item_row["amount"] += account.amount * item.get(based_on_field) / total_item_cost + + item_row["base_amount"] += ( + account.base_amount * item.get(based_on_field) / total_item_cost + ) else: - item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][ - account.expense_account - ]["amount"] += item.applicable_charges - item_account_wise_cost[(item.item_code, item.purchase_receipt_item)][ - account.expense_account - ]["base_amount"] += item.applicable_charges + item_row["amount"] += item.applicable_charges / exchange_rate + item_row["base_amount"] += item.applicable_charges return item_account_wise_cost From 2ed3bdcc2e3b9deabd9de5b01b539213c7bf62d1 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Fri, 7 Feb 2025 11:43:25 +0100 Subject: [PATCH 14/14] fix: skip warning for free items (cherry picked from commit 772776ad8a91d082b66dc8c45052f703902b3691) --- erpnext/controllers/accounts_controller.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 160c478f299..14dc038b0d6 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1728,22 +1728,22 @@ class AccountsController(TransactionBase): continue ref_amt = flt(reference_details.get(item.get(item_ref_dn)), self.precision(based_on, item)) + based_on_amt = flt(item.get(based_on)) if not ref_amt: - frappe.msgprint( - _("System will not check over billing since amount for Item {0} in {1} is zero").format( - item.item_code, ref_dt - ), - title=_("Warning"), - indicator="orange", - ) + if based_on_amt: # Skip warning for free items + frappe.msgprint( + _( + "System will not check over billing since amount for Item {0} in {1} is zero" + ).format(item.item_code, ref_dt), + title=_("Warning"), + indicator="orange", + ) continue already_billed = self.get_billed_amount_for_item(item, item_ref_dn, based_on) - total_billed_amt = flt( - flt(already_billed) + flt(item.get(based_on)), self.precision(based_on, item) - ) + total_billed_amt = flt(flt(already_billed) + based_on_amt, self.precision(based_on, item)) allowance, item_allowance, global_qty_allowance, global_amount_allowance = get_allowance_for( item.item_code, item_allowance, global_qty_allowance, global_amount_allowance, "amount"