jey_erp/jey_erp/bank_integration/cascade_delete.py

87 lines
2.8 KiB
Python

"""Cascade-delete endpoint for Bank Statement Importer.
By default Frappe refuses to delete a Bank Statement Importer that still has
dependent registry rows (Customer/Supplier/Purpose) or Bank Accounts pointing
at it via the bank_integration Dynamic Link. This module exposes:
- `get_dependents(name)` — preview counts so the UI can warn the user
- `cascade_delete(name)` — unlinks Bank Accounts and deletes registry rows,
then deletes the importer itself. Caller is expected to have shown a
confirm dialog with the counts from get_dependents.
"""
import frappe
from frappe import _
DOCTYPE = "Bank Statement Importer"
_REGISTRY_DOCTYPES = (
("Bank Integration Customer", "Customers"),
("Bank Integration Supplier", "Suppliers"),
("Bank Integration Purpose", "Purposes"),
)
@frappe.whitelist()
def get_dependents(name):
"""Return counts of records that would be touched by a cascade delete."""
if not name or not frappe.db.exists(DOCTYPE, name):
frappe.throw(_("Bank Statement Importer '{0}' not found").format(name))
counts = {}
for dt, _label in _REGISTRY_DOCTYPES:
counts[dt] = frappe.db.count(dt, {"parent_bank_integration": name})
counts["Bank Account"] = frappe.db.count("Bank Account", {
"bank_integration_type": DOCTYPE,
"bank_integration": name,
})
return counts
@frappe.whitelist()
def cascade_delete(name):
"""Delete a Bank Statement Importer and everything that depends on it.
Steps (executed in this order so Frappe's link-check doesn't block the
final delete_doc on the importer):
1. Unlink Bank Accounts: clear bank_integration_type / bank_integration
2. Delete registry rows (Customer / Supplier / Purpose) by parent_bank_integration
3. Delete the importer itself (its mapping child tables go with it)
"""
if not name or not frappe.db.exists(DOCTYPE, name):
frappe.throw(_("Bank Statement Importer '{0}' not found").format(name))
frappe.only_for(("System Manager", "Accounts Manager"))
# 1. Unlink Bank Accounts
unlinked_accounts = 0
ba_names = frappe.get_all("Bank Account", filters={
"bank_integration_type": DOCTYPE,
"bank_integration": name,
}, pluck="name")
for ba in ba_names:
frappe.db.set_value("Bank Account", ba, {
"bank_integration_type": None,
"bank_integration": None,
}, update_modified=False)
unlinked_accounts += 1
# 2. Delete registries
deleted = {}
for dt, _label in _REGISTRY_DOCTYPES:
rows = frappe.get_all(dt, filters={"parent_bank_integration": name}, pluck="name")
for r in rows:
frappe.delete_doc(dt, r, ignore_permissions=True, force=True, delete_permanently=True)
deleted[dt] = len(rows)
# 3. Delete the importer (child mapping tables cascade automatically)
frappe.delete_doc(DOCTYPE, name, ignore_permissions=True, force=True, delete_permanently=True)
frappe.db.commit()
return {
"success": True,
"deleted": deleted,
"unlinked_bank_accounts": unlinked_accounts,
}