From 1999de0b7591cd5454272008017f2b27bb3f923a Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Mon, 13 Oct 2025 13:40:40 +0530 Subject: [PATCH] refactor: store closing balance as JSON (cherry picked from commit 1a31825409a211225e7c139fb3779b200efe15ee) --- .../process_period_closing_voucher.py | 103 ++++++++++++++---- 1 file changed, 79 insertions(+), 24 deletions(-) diff --git a/erpnext/accounts/doctype/process_period_closing_voucher/process_period_closing_voucher.py b/erpnext/accounts/doctype/process_period_closing_voucher/process_period_closing_voucher.py index 8a72dca2245..e68aaa6b8cb 100644 --- a/erpnext/accounts/doctype/process_period_closing_voucher/process_period_closing_voucher.py +++ b/erpnext/accounts/doctype/process_period_closing_voucher/process_period_closing_voucher.py @@ -4,10 +4,14 @@ from datetime import timedelta import frappe +from frappe import qb from frappe.model.document import Document +from frappe.query_builder.functions import Sum from frappe.utils import add_days, get_datetime from frappe.utils.scheduler import is_scheduler_inactive +BACKGROUND = True + class ProcessPeriodClosingVoucher(Document): # begin: auto-generated types @@ -55,43 +59,94 @@ def start_pcv_processing(docname: str): ): if not is_scheduler_inactive(): for x in dates_to_process: - frappe.enqueue( - method="erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.process_individual_date", - queue="long", - is_async=True, - enqueue_after_commit=True, - docname=docname, - date=x.processing_date, - ) + if BACKGROUND: + frappe.enqueue( + method="erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.process_individual_date", + queue="long", + is_async=True, + enqueue_after_commit=True, + docname=docname, + date=x.processing_date, + ) + else: + process_individual_date(docname, x.processing_date) else: frappe.db.set_value("Process Period Closing Voucher", docname, "status", "Completed") @frappe.whitelist() def pause_pcv_processing(docname: str): - frappe.db.set_value("Process Period Closing Voucher", docname, "status", "Paused") + queued_dates = frappe.db.get_all( + "Process Period Closing Voucher Detail", + filters={"parent": docname, "status": "Queued"}, + fields=["name"], + ) + ppcv = qb.DocType("Process Period Closing Voucher") + qb.update(ppcv).set(ppcv.status, "Paused").where(ppcv.name.isin(queued_dates)).run() -def process_individual_date(docname: str, date: str): - if frappe.db.get_value("Process Period Closing Voucher", docname, "status") == "Running": - frappe.db.set_value( - "Process Period Closing Voucher Detail", {"processing_date": date}, "status", "Completed" - ) - if next_date_to_process := frappe.db.get_all( - "Process Period Closing Voucher Detail", - filters={"parent": docname, "status": "Queued"}, - fields=["processing_date"], - order_by="processing_date", - limit=1, - ): - if not is_scheduler_inactive(): +def call_next_date(docname: str): + if next_date_to_process := frappe.db.get_all( + "Process Period Closing Voucher Detail", + filters={"parent": docname, "status": "Queued"}, + fields=["processing_date"], + order_by="processing_date", + limit=1, + ): + next_date_to_process = next_date_to_process[0].processing_date + if not is_scheduler_inactive(): + frappe.db.set_value( + "Process Period Closing Voucher Detail", + {"processing_date": next_date_to_process, "parent": docname}, + "status", + "Running", + ) + if BACKGROUND: frappe.enqueue( method="erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.process_individual_date", queue="long", is_async=True, enqueue_after_commit=True, docname=docname, - date=next_date_to_process[0].processing_date, + date=next_date_to_process, ) - else: + else: + process_individual_date(docname, next_date_to_process) + else: + running = frappe.db.get_all( + "Process Period Closing Voucher Detail", + filters={"parent": docname, "status": "Running"}, + fields=["processing_date"], + order_by="processing_date", + limit=1, + ) + if not running: frappe.db.set_value("Process Period Closing Voucher", docname, "status", "Completed") + + +def process_individual_date(docname: str, date: str): + if frappe.db.get_value("Process Period Closing Voucher", docname, "status") == "Running": + pcv_name = frappe.db.get_value("Process Period Closing Voucher", docname, "parent_pcv") + pcv = frappe.get_doc("Period Closing Voucher", pcv_name) + gle = qb.DocType("GL Entry") + res = ( + qb.from_(gle) + .select(gle.account, Sum(gle.debit).as_("debit"), Sum(gle.credit).as_("credit")) + .where((gle.company.eq(pcv.company)) & (gle.is_cancelled.eq(False)) & (gle.posting_date.eq(date))) + .groupby(gle.account) + .run(as_dict=True) + ) + frappe.db.set_value( + "Process Period Closing Voucher Detail", + {"processing_date": date, "parent": docname}, + "status", + "Completed", + ) + frappe.db.set_value( + "Process Period Closing Voucher Detail", + {"processing_date": date, "parent": docname}, + "closing_balance", + frappe.json.dumps(res), + ) + + call_next_date(docname)