From 88e68168e36624d9ec31993c8f7a9b29add8c1ce Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Fri, 2 Aug 2024 11:49:50 +0530 Subject: [PATCH] refactor: use separate round off for opening entries --- erpnext/accounts/doctype/account/account.json | 4 +- erpnext/accounts/doctype/account/account.py | 1 + .../purchase_invoice/purchase_invoice.py | 6 ++- .../doctype/sales_invoice/sales_invoice.py | 6 ++- erpnext/accounts/general_ledger.py | 49 +++++++++++++++---- erpnext/controllers/accounts_controller.py | 6 ++- erpnext/setup/doctype/company/company.js | 1 + 7 files changed, 59 insertions(+), 14 deletions(-) diff --git a/erpnext/accounts/doctype/account/account.json b/erpnext/accounts/doctype/account/account.json index 5a50d7a1ab5..34e9a691fd2 100644 --- a/erpnext/accounts/doctype/account/account.json +++ b/erpnext/accounts/doctype/account/account.json @@ -124,7 +124,7 @@ "label": "Account Type", "oldfieldname": "account_type", "oldfieldtype": "Select", - "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nCurrent Asset\nCurrent Liability\nDepreciation\nDirect Expense\nDirect Income\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nIndirect Expense\nIndirect Income\nLiability\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary", + "options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nCurrent Asset\nCurrent Liability\nDepreciation\nDirect Expense\nDirect Income\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nIndirect Expense\nIndirect Income\nLiability\nPayable\nReceivable\nRound Off\nRound Off for Opening\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary", "search_index": 1 }, { @@ -194,7 +194,7 @@ "idx": 1, "is_tree": 1, "links": [], - "modified": "2024-06-27 16:23:04.444354", + "modified": "2024-08-19 15:19:11.095045", "modified_by": "Administrator", "module": "Accounts", "name": "Account", diff --git a/erpnext/accounts/doctype/account/account.py b/erpnext/accounts/doctype/account/account.py index 180edc61ced..f6b0a6f8056 100644 --- a/erpnext/accounts/doctype/account/account.py +++ b/erpnext/accounts/doctype/account/account.py @@ -60,6 +60,7 @@ class Account(NestedSet): "Payable", "Receivable", "Round Off", + "Round Off for Opening", "Stock", "Stock Adjustment", "Stock Received But Not Billed", diff --git a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py index 44d8a407017..b9194beccb5 100644 --- a/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py +++ b/erpnext/accounts/doctype/purchase_invoice/purchase_invoice.py @@ -1520,7 +1520,11 @@ class PurchaseInvoice(BuyingController): # eg: rounding_adjustment = 0.01 and exchange rate = 0.05 and precision of base_rounding_adjustment is 2 # then base_rounding_adjustment becomes zero and error is thrown in GL Entry if not self.is_internal_transfer() and self.rounding_adjustment and self.base_rounding_adjustment: - round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( + ( + round_off_account, + round_off_cost_center, + round_off_for_opening, + ) = get_round_off_account_and_cost_center( self.company, "Purchase Invoice", self.name, self.use_company_roundoff_cost_center ) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 4f62ad2f4c4..0ee98114794 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -1626,7 +1626,11 @@ class SalesInvoice(SellingController): and self.base_rounding_adjustment and not self.is_internal_transfer() ): - round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( + ( + round_off_account, + round_off_cost_center, + round_off_for_opening, + ) = get_round_off_account_and_cost_center( self.company, "Sales Invoice", self.name, self.use_company_roundoff_cost_center ) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 4fba1095546..98e1ac2de4a 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -7,7 +7,7 @@ import copy import frappe from frappe import _ from frappe.model.meta import get_field_precision -from frappe.utils import cint, flt, formatdate, getdate, now +from frappe.utils import cint, flt, formatdate, get_link_to_form, getdate, now from frappe.utils.dashboard import cache_source import erpnext @@ -490,16 +490,36 @@ def raise_debit_credit_not_equal_error(debit_credit_diff, voucher_type, voucher_ ) +def has_opening_entries(gl_map: list) -> bool: + for x in gl_map: + if x.is_opening == "Yes": + return True + return False + + def make_round_off_gle(gl_map, debit_credit_diff, precision): - round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( + round_off_account, round_off_cost_center, round_off_for_opening = get_round_off_account_and_cost_center( gl_map[0].company, gl_map[0].voucher_type, gl_map[0].voucher_no ) round_off_gle = frappe._dict() round_off_account_exists = False + has_opening_entry = has_opening_entries(gl_map) + + if has_opening_entry: + if not round_off_for_opening: + frappe.throw( + _("Please set '{0}' in Company: {1}").format( + frappe.bold("Round Off for Opening"), get_link_to_form("Company", gl_map[0].company) + ) + ) + + account = round_off_for_opening + else: + account = round_off_account if gl_map[0].voucher_type != "Period Closing Voucher": for d in gl_map: - if d.account == round_off_account: + if d.account == account: round_off_gle = d if d.debit: debit_credit_diff -= flt(d.debit) - flt(d.credit) @@ -517,7 +537,7 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision): round_off_gle.update( { - "account": round_off_account, + "account": account, "debit_in_account_currency": abs(debit_credit_diff) if debit_credit_diff < 0 else 0, "credit_in_account_currency": debit_credit_diff if debit_credit_diff > 0 else 0, "debit": abs(debit_credit_diff) if debit_credit_diff < 0 else 0, @@ -531,6 +551,9 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision): } ) + if has_opening_entry: + round_off_gle.update({"is_opening": "Yes"}) + update_accounting_dimensions(round_off_gle) if not round_off_account_exists: gl_map.append(round_off_gle) @@ -555,8 +578,8 @@ def update_accounting_dimensions(round_off_gle): def get_round_off_account_and_cost_center(company, voucher_type, voucher_no, use_company_default=False): - round_off_account, round_off_cost_center = frappe.get_cached_value( - "Company", company, ["round_off_account", "round_off_cost_center"] + round_off_account, round_off_cost_center, round_off_for_opening = frappe.get_cached_value( + "Company", company, ["round_off_account", "round_off_cost_center", "round_off_for_opening"] ) or [None, None] # Use expense account as fallback @@ -572,12 +595,20 @@ def get_round_off_account_and_cost_center(company, voucher_type, voucher_no, use round_off_cost_center = parent_cost_center if not round_off_account: - frappe.throw(_("Please mention Round Off Account in Company")) + frappe.throw( + _("Please mention '{0}' in Company: {1}").format( + frappe.bold("Round Off Account"), get_link_to_form("Company", company) + ) + ) if not round_off_cost_center: - frappe.throw(_("Please mention Round Off Cost Center in Company")) + frappe.throw( + _("Please mention '{0}' in Company: {1}").format( + frappe.bold("Round Off Cost Center"), get_link_to_form("Company", company) + ) + ) - return round_off_account, round_off_cost_center + return round_off_account, round_off_cost_center, round_off_for_opening def make_reverse_gl_entries( diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 65f73061008..f81b06546b1 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -1266,7 +1266,11 @@ class AccountsController(TransactionBase): d.exchange_gain_loss = difference def make_precision_loss_gl_entry(self, gl_entries): - round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( + ( + round_off_account, + round_off_cost_center, + round_off_for_opening, + ) = get_round_off_account_and_cost_center( self.company, "Purchase Invoice", self.name, self.use_company_roundoff_cost_center ) diff --git a/erpnext/setup/doctype/company/company.js b/erpnext/setup/doctype/company/company.js index 812d29810e6..29ae1127653 100644 --- a/erpnext/setup/doctype/company/company.js +++ b/erpnext/setup/doctype/company/company.js @@ -251,6 +251,7 @@ erpnext.company.setup_queries = function (frm) { ["default_expense_account", { root_type: "Expense" }], ["default_income_account", { root_type: "Income" }], ["round_off_account", { root_type: "Expense" }], + ["round_off_for_opening", { root_type: "Liability" }], ["write_off_account", { root_type: "Expense" }], ["default_deferred_expense_account", {}], ["default_deferred_revenue_account", {}],