Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix!: ensure multiple PCVs in same fiscal year are considered in patch #44811

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions erpnext/patches.txt
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ erpnext.patches.v15_0.update_asset_value_for_manual_depr_entries
erpnext.patches.v15_0.update_gpa_and_ndb_for_assdeprsch
erpnext.patches.v14_0.create_accounting_dimensions_for_closing_balance
erpnext.patches.v14_0.set_period_start_end_date_in_pcv
erpnext.patches.v14_0.update_closing_balances #08-11-2024
erpnext.patches.v14_0.update_closing_balances #20-12-2024
execute:frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
erpnext.patches.v14_0.update_reference_type_in_journal_entry_accounts
erpnext.patches.v14_0.update_subscription_details
Expand Down Expand Up @@ -392,4 +392,4 @@ erpnext.patches.v15_0.migrate_old_item_wise_tax_detail_data_format
erpnext.patches.v15_0.set_is_exchange_gain_loss_in_payment_entry_deductions
erpnext.patches.v14_0.update_stock_uom_in_work_order_item
erpnext.patches.v15_0.enable_allow_existing_serial_no
erpnext.patches.v15_0.update_cc_in_process_statement_of_accounts
erpnext.patches.v15_0.update_cc_in_process_statement_of_accounts
140 changes: 83 additions & 57 deletions erpnext/patches/v14_0/update_closing_balances.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# License: MIT. See LICENSE

import itertools

import frappe

Expand All @@ -10,34 +11,91 @@
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
get_accounting_dimensions,
)
from erpnext.accounts.utils import get_fiscal_year


def execute():
# clear balances, they will be recalculated
frappe.db.truncate("Account Closing Balance")

gle_fields = get_gle_fields()
pcv_list = get_period_closing_vouchers()
gl_entries = get_gl_entries(pcv_list)

for _, pcvs in itertools.groupby(pcv_list, key=lambda pcv: (pcv.company, pcv.period_start_date)):
process_grouped_pcvs(list(pcvs), gl_entries)


def process_grouped_pcvs(pcvs, gl_entries):
pl_account_entries = []
closing_account_entries = []
first_pcv = pcvs[0]

for pcv in pcvs:
pcv_entries = gl_entries.get(pcv.name) or []
for entry in pcv_entries:
entry["closing_date"] = first_pcv.period_end_date
entry["period_closing_voucher"] = first_pcv.name
entry["voucher_no"] = first_pcv.name

list_to_update = (
pl_account_entries if entry.account != pcv.closing_account_head else closing_account_entries
)
list_to_update.append(entry)

# hacky!!
if to_cancel := pcvs[1:]:
to_cancel = [pcv.name for pcv in to_cancel]

# update voucher number
gle_to_update = [entry.name for entry in closing_account_entries + pl_account_entries]
frappe.db.set_value(
"GL Entry",
{
"name": ("in", gle_to_update),
"voucher_no": ("in", to_cancel),
},
"voucher_no",
first_pcv.name,
update_modified=False,
)

# mark as cancelled
frappe.db.set_value(
"Period Closing Voucher",
{"name": ("in", to_cancel)},
"docstatus",
2,
update_modified=False,
)

pcv_doc = frappe.get_doc("Period Closing Voucher", first_pcv.name)
pcv_doc.pl_accounts_reverse_gle = pl_account_entries
pcv_doc.closing_account_gle = closing_account_entries
closing_entries = pcv_doc.get_account_closing_balances()
make_closing_entries(closing_entries, pcv_doc.name, pcv_doc.company, pcv_doc.period_end_date)


def get_period_closing_vouchers():
return frappe.db.get_all(
"Period Closing Voucher",
fields=["name", "closing_account_head", "period_start_date", "period_end_date", "company"],
filters={"docstatus": 1},
order_by="period_start_date asc, period_end_date desc",
)


for company in frappe.get_all("Company", pluck="name"):
i = 0
company_wise_order = {}
for pcv in get_period_closing_vouchers(company):
company_wise_order.setdefault(pcv.company, [])
if pcv.period_end_date not in company_wise_order[pcv.company]:
pcv_doc = frappe.get_doc("Period Closing Voucher", pcv.name)
pcv_doc.pl_accounts_reverse_gle = get_pcv_gl_entries_for_pl_accounts(pcv, gle_fields)
pcv_doc.closing_account_gle = get_pcv_gl_entries_for_closing_accounts(pcv, gle_fields)
closing_entries = pcv_doc.get_account_closing_balances()
make_closing_entries(closing_entries, pcv.name, pcv.company, pcv.period_end_date)
def get_gl_entries(pcv_list):
gl_entries = frappe.get_all(
"GL Entry",
filters={"voucher_no": ("in", [pcv.name for pcv in pcv_list]), "is_cancelled": 0},
fields=get_gle_fields(),
update={"is_period_closing_voucher_entry": 1},
)

company_wise_order[pcv.company].append(pcv.period_end_date)
i += 1
return {k: list(v) for k, v in itertools.groupby(gl_entries, key=lambda gle: gle.voucher_no)}


def get_gle_fields():
default_diemnsion_fields = ["cost_center", "finance_book", "project"]
accounting_dimension_fields = get_accounting_dimensions()
gle_fields = [
return [
"name",
"company",
"posting_date",
Expand All @@ -47,43 +105,11 @@ def get_gle_fields():
"credit",
"debit_in_account_currency",
"credit_in_account_currency",
*default_diemnsion_fields,
*accounting_dimension_fields,
"voucher_no",
# default dimension fields
"cost_center",
"finance_book",
"project",
# accounting dimensions
*get_accounting_dimensions(),
]

return gle_fields


def get_period_closing_vouchers(company):
return frappe.db.get_all(
"Period Closing Voucher",
fields=["name", "closing_account_head", "period_start_date", "period_end_date", "company"],
filters={"docstatus": 1, "company": company},
order_by="period_end_date",
)


def get_pcv_gl_entries_for_pl_accounts(pcv, gle_fields):
return get_gl_entries(pcv, gle_fields, {"account": ["!=", pcv.closing_account_head]})


def get_pcv_gl_entries_for_closing_accounts(pcv, gle_fields):
return get_gl_entries(pcv, gle_fields, {"account": pcv.closing_account_head})


def get_gl_entries(pcv, gle_fields, accounts_filter=None):
filters = {"voucher_no": pcv.name, "is_cancelled": 0}
if accounts_filter:
filters.update(accounts_filter)

gl_entries = frappe.db.get_all(
"GL Entry",
filters=filters,
fields=gle_fields,
)
for entry in gl_entries:
entry["is_period_closing_voucher_entry"] = 1
entry["closing_date"] = pcv.period_end_date
entry["period_closing_voucher"] = pcv.name

return gl_entries
Loading