e-taxes settings is single doctype now
This commit is contained in:
parent
2ba3a97227
commit
49d974f366
|
|
@ -29,20 +29,45 @@ def _backup_path():
|
|||
return frappe.get_site_path("private", BACKUP_FILENAME)
|
||||
|
||||
|
||||
def _sql_table_exists(table_name):
|
||||
"""Check if table exists via raw SQL (bypasses Frappe metadata)."""
|
||||
result = frappe.db.sql(
|
||||
"SHOW TABLES LIKE %s",
|
||||
(table_name,),
|
||||
)
|
||||
return bool(result)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def export_etaxes_to_file():
|
||||
"""
|
||||
Run BEFORE bench migrate:
|
||||
bench --site <site> execute invoice_az.migrate_utils.export_etaxes_to_file
|
||||
Saves all E-Taxes Settings data to site/private/etaxes_settings_backup.json
|
||||
"""
|
||||
if not frappe.db.table_exists("tabE-Taxes Settings"):
|
||||
print("ERROR: tabE-Taxes Settings not found")
|
||||
return
|
||||
Export E-Taxes Settings data to a JSON file.
|
||||
Works even after git pull (when doctype JSON already says issingle=1
|
||||
but the old multi-record table still exists in MySQL).
|
||||
|
||||
Usage:
|
||||
bench --site <site> execute invoice_az.migrate_utils.export_etaxes_to_file
|
||||
"""
|
||||
# Try old multi-record table first
|
||||
if _sql_table_exists("tabE-Taxes Settings"):
|
||||
return _export_from_table()
|
||||
|
||||
# Fallback: already migrated to Single — export from tabSingles
|
||||
singles = frappe.db.sql(
|
||||
"SELECT field, value FROM tabSingles WHERE doctype = 'E-Taxes Settings'",
|
||||
as_dict=True,
|
||||
)
|
||||
if singles:
|
||||
return _export_from_singles(singles)
|
||||
|
||||
print("ERROR: No data found — neither tabE-Taxes Settings table nor tabSingles entries exist")
|
||||
|
||||
|
||||
def _export_from_table():
|
||||
"""Export from the old multi-record table."""
|
||||
rows = frappe.db.sql("SELECT * FROM `tabE-Taxes Settings` LIMIT 1", as_dict=True)
|
||||
if not rows:
|
||||
print("ERROR: no records in tabE-Taxes Settings")
|
||||
print("ERROR: tabE-Taxes Settings table exists but is empty")
|
||||
return
|
||||
|
||||
old_row = rows[0]
|
||||
|
|
@ -58,7 +83,7 @@ def export_etaxes_to_file():
|
|||
backup["scalar"][field] = old_row.get(field)
|
||||
|
||||
for fieldname, table in CHILD_TABLES.items():
|
||||
if frappe.db.table_exists(table):
|
||||
if _sql_table_exists(table):
|
||||
child_rows = frappe.db.sql(
|
||||
f"SELECT * FROM `{table}` WHERE parent = %s ORDER BY idx",
|
||||
(old_name,),
|
||||
|
|
@ -66,29 +91,71 @@ def export_etaxes_to_file():
|
|||
)
|
||||
backup["children"][fieldname] = [dict(r) for r in child_rows]
|
||||
|
||||
return _save_backup(backup, old_name)
|
||||
|
||||
|
||||
def _export_from_singles(singles):
|
||||
"""Export from tabSingles (already a Single doctype)."""
|
||||
backup = {
|
||||
"old_name": "E-Taxes Settings",
|
||||
"scalar": {},
|
||||
"children": {},
|
||||
}
|
||||
|
||||
singles_map = {r["field"]: r["value"] for r in singles}
|
||||
for field in SCALAR_FIELDS:
|
||||
backup["scalar"][field] = singles_map.get(field)
|
||||
|
||||
for fieldname, table in CHILD_TABLES.items():
|
||||
if _sql_table_exists(table):
|
||||
child_rows = frappe.db.sql(
|
||||
f"SELECT * FROM `{table}` WHERE parent = 'E-Taxes Settings' ORDER BY idx",
|
||||
as_dict=True,
|
||||
)
|
||||
backup["children"][fieldname] = [dict(r) for r in child_rows]
|
||||
|
||||
return _save_backup(backup, "E-Taxes Settings")
|
||||
|
||||
|
||||
def _save_backup(backup, source_name):
|
||||
"""Save backup dict to JSON file."""
|
||||
path = _backup_path()
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(backup, f, default=str, ensure_ascii=False, indent=2)
|
||||
|
||||
total_children = sum(len(v) for v in backup["children"].values())
|
||||
print(f"Saved to: {path}")
|
||||
print(f"Record: '{old_name}'")
|
||||
print(f"Source: '{source_name}'")
|
||||
print(f"Scalar fields: {sum(1 for v in backup['scalar'].values() if v is not None)}")
|
||||
print(f"Child rows: {total_children}")
|
||||
for fieldname, rows in backup["children"].items():
|
||||
if rows:
|
||||
print(f" {fieldname}: {len(rows)}")
|
||||
return path
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def restore_etaxes_from_file():
|
||||
"""Called from the E-Taxes Settings form button."""
|
||||
"""
|
||||
Restore E-Taxes Settings from backup JSON file.
|
||||
|
||||
Usage (CLI):
|
||||
bench --site <site> execute invoice_az.migrate_utils.restore_etaxes_from_file
|
||||
|
||||
Also callable from the E-Taxes Settings form button.
|
||||
"""
|
||||
path = _backup_path()
|
||||
|
||||
if not os.path.exists(path):
|
||||
return {"success": False, "message": f"Backup file not found: {path}"}
|
||||
msg = f"Backup file not found: {path}"
|
||||
print(f"ERROR: {msg}")
|
||||
return {"success": False, "message": msg}
|
||||
|
||||
with open(path, encoding="utf-8") as f:
|
||||
backup = json.load(f)
|
||||
|
||||
# Scalar fields → tabSingles
|
||||
restored_scalars = 0
|
||||
for field, value in backup.get("scalar", {}).items():
|
||||
if value is None:
|
||||
continue
|
||||
|
|
@ -100,11 +167,13 @@ def restore_etaxes_from_file():
|
|||
""",
|
||||
(field, str(value)),
|
||||
)
|
||||
restored_scalars += 1
|
||||
|
||||
# Child tables → DELETE existing + INSERT from backup
|
||||
restored_children = 0
|
||||
for fieldname, rows in backup.get("children", {}).items():
|
||||
table = CHILD_TABLES.get(fieldname)
|
||||
if not table or not frappe.db.table_exists(table) or not rows:
|
||||
if not table or not _sql_table_exists(table) or not rows:
|
||||
continue
|
||||
|
||||
frappe.db.sql(f"DELETE FROM `{table}` WHERE parent = 'E-Taxes Settings'")
|
||||
|
|
@ -112,6 +181,7 @@ def restore_etaxes_from_file():
|
|||
for row in rows:
|
||||
row["parent"] = "E-Taxes Settings"
|
||||
row["parenttype"] = "E-Taxes Settings"
|
||||
row["parentfield"] = fieldname
|
||||
columns = ", ".join(f"`{col}`" for col in row)
|
||||
placeholders = ", ".join(["%s"] * len(row))
|
||||
try:
|
||||
|
|
@ -119,17 +189,16 @@ def restore_etaxes_from_file():
|
|||
f"INSERT INTO `{table}` ({columns}) VALUES ({placeholders})",
|
||||
list(row.values()),
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
restored_children += 1
|
||||
except Exception as e:
|
||||
print(f" Warning: failed to insert row in {table}: {e}")
|
||||
|
||||
frappe.db.commit()
|
||||
frappe.clear_cache(doctype="E-Taxes Settings")
|
||||
|
||||
total = sum(len(v) for v in backup.get("children", {}).values())
|
||||
return {
|
||||
"success": True,
|
||||
"message": f"Restored from '{backup.get('old_name')}' — {total} child rows",
|
||||
}
|
||||
msg = f"Restored {restored_scalars} fields, {restored_children} child rows"
|
||||
print(f"OK: {msg}")
|
||||
return {"success": True, "message": msg}
|
||||
|
||||
|
||||
def migrate_etaxes_settings_to_single():
|
||||
|
|
|
|||
Loading…
Reference in New Issue