From b926b846b14947ea3963ed126455f02a21571fe2 Mon Sep 17 00:00:00 2001 From: Mihir Kandoi Date: Wed, 1 Jul 2026 11:55:40 +0530 Subject: [PATCH] fix(accounts): savepoint auto_create_fiscal_year loop to survive a duplicate year on Postgres The daily scheduler loops creating next-year Fiscal Years (autoname=field:year). A duplicate-year INSERT aborts the statement; on Postgres that poisons the whole transaction, so the next iteration's get_doc/insert dies with InFailedSqlTransaction. MariaDB statement-rolls-back and continues. Wrap each iteration in a savepoint + rollback(save_point=) in the DuplicateEntryError branch -- a strict no-op on MariaDB (same INSERT, same skip), recovers the txn on Postgres. Co-Authored-By: Claude Opus 4.8 --- erpnext/accounts/doctype/fiscal_year/fiscal_year.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py index 553f8d8d9d5..f376047c37b 100644 --- a/erpnext/accounts/doctype/fiscal_year/fiscal_year.py +++ b/erpnext/accounts/doctype/fiscal_year/fiscal_year.py @@ -107,6 +107,9 @@ def auto_create_fiscal_year(): ) for d in fiscal_year: + # savepoint so a duplicate-year INSERT (Fiscal Year autoname=field:year) that aborts the + # statement doesn't poison the whole scheduler transaction on Postgres and kill the next iteration + frappe.db.savepoint("auto_create_fiscal_year") try: current_fy = frappe.get_doc("Fiscal Year", d[0]) @@ -127,7 +130,7 @@ def auto_create_fiscal_year(): new_fy.insert(ignore_permissions=True) except frappe.NameError: - pass + frappe.db.rollback(save_point="auto_create_fiscal_year") def get_from_and_to_date(fiscal_year):