e-taxes settings is single doctype now

This commit is contained in:
Ali 2026-03-03 16:52:15 +04:00
parent d78781d9b8
commit 0b46271628
1 changed files with 38 additions and 31 deletions

View File

@ -2,10 +2,10 @@
Migration utilities for E-Taxes Settings Single doctype conversion.
backup_etaxes_settings() is called by the before_migrate hook at that point
the doctype is still a regular doctype, so frappe.db works normally.
the doctype is still a regular doctype and ORM works normally.
restore_etaxes_settings() is called by the patch at that point the doctype
is already Single, so we read from the backup file and write via raw SQL.
is already Single, so we use raw SQL and restore everything from the backup file.
"""
import json
@ -26,13 +26,14 @@ SCALAR_FIELDS = [
"default_payment_terms",
]
CHILD_TABLES = [
"tabE-Taxes Item Mapping",
"tabE-Taxes Customer Mappings",
"tabE-Taxes Supplier Mappings",
"tabE-Taxes Unit Mapping",
"tabE-Taxes VAT Account Mapping",
]
# SQL table name → parentfield name in E-Taxes Settings
CHILD_TABLES = {
"tabE-Taxes Item Mapping": "item_mappings",
"tabE-Taxes Customer Mappings": "customer_mappings",
"tabE-Taxes Supplier Mappings": "supplier_mappings",
"tabE-Taxes Unit Mapping": "unit_mappings",
"tabE-Taxes VAT Account Mapping": "vat_account_mappings",
}
def _backup_path():
@ -41,14 +42,13 @@ def _backup_path():
def backup_etaxes_settings():
"""
Called before_migrate.
Dumps the active E-Taxes Settings record (scalar fields + child rows) to a JSON file.
Called before_migrate (before schema sync).
Dumps scalar fields + all child table rows to a JSON file.
"""
if not frappe.db.table_exists("tabE-Taxes Settings"):
return
# Find the best record using raw SQL — ORM still works normally here,
# but we avoid referencing is_default/is_active which may have been dropped.
# Find the best old record — ORM still works normally here
rows = None
for query in [
"SELECT * FROM `tabE-Taxes Settings` WHERE name != 'E-Taxes Settings' ORDER BY modified DESC LIMIT 1",
@ -73,6 +73,7 @@ def backup_etaxes_settings():
"children": {},
}
# Save ALL columns of each child table row so we can re-insert them if needed
for table in CHILD_TABLES:
if frappe.db.table_exists(table):
child_rows = frappe.db.sql(
@ -89,8 +90,8 @@ def backup_etaxes_settings():
def restore_etaxes_settings():
"""
Called from the migration patch (after schema sync).
Reads the backup file, writes scalar fields into tabSingles,
re-parents child rows, then deletes the file.
Reads backup file writes scalar fields to tabSingles
deletes + re-inserts child table rows deletes the file.
"""
path = _backup_path()
@ -100,7 +101,7 @@ def restore_etaxes_settings():
with open(path, encoding="utf-8") as f:
backup = json.load(f)
# Write scalar fields into tabSingles
# --- Scalar fields → tabSingles ---
for field, value in backup.get("scalar", {}).items():
if value is None:
continue
@ -113,23 +114,29 @@ def restore_etaxes_settings():
(field, str(value)),
)
# Re-parent child rows
old_name = backup.get("old_name")
if old_name:
for table in CHILD_TABLES:
if frappe.db.table_exists(table):
frappe.db.sql(
f"""
UPDATE `{table}`
SET parent = 'E-Taxes Settings',
parenttype = 'E-Taxes Settings'
WHERE parent = %s
""",
(old_name,),
)
# --- Child tables: delete existing rows, then re-insert from backup ---
for table, rows in backup.get("children", {}).items():
if not frappe.db.table_exists(table) or not rows:
continue
# Remove any rows already parented to the Single (e.g., from a broken previous run)
frappe.db.sql(
f"DELETE FROM `{table}` WHERE parent = 'E-Taxes Settings'"
)
for row in rows:
row["parent"] = "E-Taxes Settings"
row["parenttype"] = "E-Taxes Settings"
columns = ", ".join(f"`{col}`" for col in row)
placeholders = ", ".join(["%s"] * len(row))
frappe.db.sql(
f"INSERT INTO `{table}` ({columns}) VALUES ({placeholders})",
list(row.values()),
)
frappe.db.commit()
frappe.clear_cache(doctype="E-Taxes Settings")
# Clean up — file is no longer needed
os.remove(path)