e-taxes settings is single doctype now
This commit is contained in:
parent
331aabe1d7
commit
2ba3a97227
|
|
@ -12,17 +12,17 @@ frappe.ui.form.on('E-Taxes Settings', {
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: function(frm) {
|
refresh: function(frm) {
|
||||||
frm.add_custom_button(__('Restore from old data'), function() {
|
frm.add_custom_button(__('Restore from file'), function() {
|
||||||
frappe.confirm(
|
frappe.confirm(
|
||||||
__('This will restore all settings and mappings from the pre-migration database record. Continue?'),
|
__('Restore all settings and mappings from backup file? Current data will be overwritten.'),
|
||||||
function() {
|
function() {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: 'invoice_az.migrate_utils.restore_etaxes_settings_from_old_table',
|
method: 'invoice_az.migrate_utils.restore_etaxes_from_file',
|
||||||
freeze: true,
|
freeze: true,
|
||||||
freeze_message: __('Restoring...'),
|
freeze_message: __('Restoring...'),
|
||||||
callback: function(r) {
|
callback: function(r) {
|
||||||
if (r.message && r.message.success) {
|
if (r.message && r.message.success) {
|
||||||
frappe.show_alert({ message: __(r.message.message), indicator: 'green' }, 5);
|
frappe.show_alert({ message: r.message.message, indicator: 'green' }, 5);
|
||||||
frm.reload_doc();
|
frm.reload_doc();
|
||||||
} else {
|
} else {
|
||||||
frappe.msgprint({
|
frappe.msgprint({
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
"""
|
import json
|
||||||
Migration utilities for E-Taxes Settings → Single doctype.
|
import os
|
||||||
"""
|
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
|
BACKUP_FILENAME = "etaxes_settings_backup.json"
|
||||||
|
|
||||||
SCALAR_FIELDS = [
|
SCALAR_FIELDS = [
|
||||||
"similarity_threshold",
|
"similarity_threshold",
|
||||||
"consider_azeri_chars",
|
"consider_azeri_chars",
|
||||||
|
|
@ -15,47 +16,80 @@ SCALAR_FIELDS = [
|
||||||
"default_payment_terms",
|
"default_payment_terms",
|
||||||
]
|
]
|
||||||
|
|
||||||
CHILD_TABLES = [
|
CHILD_TABLES = {
|
||||||
"tabE-Taxes Item Mapping",
|
"item_mappings": "tabE-Taxes Item Mapping",
|
||||||
"tabE-Taxes Customer Mappings",
|
"customer_mappings": "tabE-Taxes Customer Mappings",
|
||||||
"tabE-Taxes Supplier Mappings",
|
"supplier_mappings": "tabE-Taxes Supplier Mappings",
|
||||||
"tabE-Taxes Unit Mapping",
|
"unit_mappings": "tabE-Taxes Unit Mapping",
|
||||||
"tabE-Taxes VAT Account Mapping",
|
"vat_account_mappings": "tabE-Taxes VAT Account Mapping",
|
||||||
]
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _backup_path():
|
||||||
|
return frappe.get_site_path("private", BACKUP_FILENAME)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def restore_etaxes_settings_from_old_table():
|
def export_etaxes_to_file():
|
||||||
"""
|
"""
|
||||||
Called from the E-Taxes Settings form button.
|
Run BEFORE bench migrate:
|
||||||
Reads data from the old tabE-Taxes Settings (still exists after migration)
|
bench --site <site> execute invoice_az.migrate_utils.export_etaxes_to_file
|
||||||
and populates the current Single doctype.
|
Saves all E-Taxes Settings data to site/private/etaxes_settings_backup.json
|
||||||
"""
|
"""
|
||||||
if not frappe.db.table_exists("tabE-Taxes Settings"):
|
if not frappe.db.table_exists("tabE-Taxes Settings"):
|
||||||
return {"success": False, "message": "Old table not found"}
|
print("ERROR: tabE-Taxes Settings not found")
|
||||||
|
return
|
||||||
|
|
||||||
# Get the old record
|
rows = frappe.db.sql("SELECT * FROM `tabE-Taxes Settings` LIMIT 1", as_dict=True)
|
||||||
old_row = None
|
if not rows:
|
||||||
for query in [
|
print("ERROR: no records in tabE-Taxes Settings")
|
||||||
"SELECT * FROM `tabE-Taxes Settings` WHERE name != 'E-Taxes Settings' LIMIT 1",
|
return
|
||||||
"SELECT * FROM `tabE-Taxes Settings` LIMIT 1",
|
|
||||||
]:
|
|
||||||
try:
|
|
||||||
rows = frappe.db.sql(query, as_dict=True)
|
|
||||||
if rows:
|
|
||||||
old_row = rows[0]
|
|
||||||
break
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not old_row:
|
old_row = rows[0]
|
||||||
return {"success": False, "message": "No old settings record found in database"}
|
old_name = old_row["name"]
|
||||||
|
|
||||||
old_name = old_row.get("name")
|
backup = {
|
||||||
|
"old_name": old_name,
|
||||||
|
"scalar": {},
|
||||||
|
"children": {},
|
||||||
|
}
|
||||||
|
|
||||||
# Write scalar fields to tabSingles
|
|
||||||
for field in SCALAR_FIELDS:
|
for field in SCALAR_FIELDS:
|
||||||
value = old_row.get(field)
|
backup["scalar"][field] = old_row.get(field)
|
||||||
|
|
||||||
|
for fieldname, table in CHILD_TABLES.items():
|
||||||
|
if frappe.db.table_exists(table):
|
||||||
|
child_rows = frappe.db.sql(
|
||||||
|
f"SELECT * FROM `{table}` WHERE parent = %s ORDER BY idx",
|
||||||
|
(old_name,),
|
||||||
|
as_dict=True,
|
||||||
|
)
|
||||||
|
backup["children"][fieldname] = [dict(r) for r in child_rows]
|
||||||
|
|
||||||
|
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"Child rows: {total_children}")
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def restore_etaxes_from_file():
|
||||||
|
"""Called 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}"}
|
||||||
|
|
||||||
|
with open(path, encoding="utf-8") as f:
|
||||||
|
backup = json.load(f)
|
||||||
|
|
||||||
|
# Scalar fields → tabSingles
|
||||||
|
for field, value in backup.get("scalar", {}).items():
|
||||||
if value is None:
|
if value is None:
|
||||||
continue
|
continue
|
||||||
frappe.db.sql(
|
frappe.db.sql(
|
||||||
|
|
@ -67,26 +101,15 @@ def restore_etaxes_settings_from_old_table():
|
||||||
(field, str(value)),
|
(field, str(value)),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Restore child table rows
|
# Child tables → DELETE existing + INSERT from backup
|
||||||
restored_children = {}
|
for fieldname, rows in backup.get("children", {}).items():
|
||||||
for table in CHILD_TABLES:
|
table = CHILD_TABLES.get(fieldname)
|
||||||
if not frappe.db.table_exists(table):
|
if not table or not frappe.db.table_exists(table) or not rows:
|
||||||
continue
|
|
||||||
try:
|
|
||||||
child_rows = frappe.db.sql(
|
|
||||||
f"SELECT * FROM `{table}` WHERE parent = %s ORDER BY idx",
|
|
||||||
(old_name,),
|
|
||||||
as_dict=True,
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not child_rows:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
frappe.db.sql(f"DELETE FROM `{table}` WHERE parent = 'E-Taxes Settings'")
|
frappe.db.sql(f"DELETE FROM `{table}` WHERE parent = 'E-Taxes Settings'")
|
||||||
|
|
||||||
for row in child_rows:
|
for row in rows:
|
||||||
row["parent"] = "E-Taxes Settings"
|
row["parent"] = "E-Taxes Settings"
|
||||||
row["parenttype"] = "E-Taxes Settings"
|
row["parenttype"] = "E-Taxes Settings"
|
||||||
columns = ", ".join(f"`{col}`" for col in row)
|
columns = ", ".join(f"`{col}`" for col in row)
|
||||||
|
|
@ -99,100 +122,16 @@ def restore_etaxes_settings_from_old_table():
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
restored_children[table] = len(child_rows)
|
|
||||||
|
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
frappe.clear_cache(doctype="E-Taxes Settings")
|
frappe.clear_cache(doctype="E-Taxes Settings")
|
||||||
|
|
||||||
|
total = sum(len(v) for v in backup.get("children", {}).values())
|
||||||
return {
|
return {
|
||||||
"success": True,
|
"success": True,
|
||||||
"message": f"Restored from record '{old_name}'",
|
"message": f"Restored from '{backup.get('old_name')}' — {total} child rows",
|
||||||
"children": restored_children,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def migrate_etaxes_settings_to_single():
|
def migrate_etaxes_settings_to_single():
|
||||||
"""
|
"""Called from after_migrate hook — no-op if old table is gone."""
|
||||||
Called from after_migrate hook.
|
pass
|
||||||
Reads the old tabE-Taxes Settings (Frappe never drops old tables during sync)
|
|
||||||
and writes scalar fields to tabSingles + re-parents child table rows.
|
|
||||||
Safe to call multiple times — skips if tabSingles already has data.
|
|
||||||
"""
|
|
||||||
# Skip if already migrated
|
|
||||||
already_migrated = frappe.db.sql(
|
|
||||||
"SELECT COUNT(*) as cnt FROM `tabSingles` WHERE doctype = 'E-Taxes Settings'",
|
|
||||||
as_dict=True,
|
|
||||||
)
|
|
||||||
if already_migrated and already_migrated[0].get("cnt", 0) > 0:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Old table must exist
|
|
||||||
if not frappe.db.table_exists("tabE-Taxes Settings"):
|
|
||||||
return
|
|
||||||
|
|
||||||
# Get the old record — try any row (old name could even be "E-Taxes Settings")
|
|
||||||
old_row = None
|
|
||||||
for query in [
|
|
||||||
"SELECT * FROM `tabE-Taxes Settings` WHERE name != 'E-Taxes Settings' LIMIT 1",
|
|
||||||
"SELECT * FROM `tabE-Taxes Settings` LIMIT 1",
|
|
||||||
]:
|
|
||||||
try:
|
|
||||||
rows = frappe.db.sql(query, as_dict=True)
|
|
||||||
if rows:
|
|
||||||
old_row = rows[0]
|
|
||||||
break
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not old_row:
|
|
||||||
return
|
|
||||||
|
|
||||||
old_name = old_row.get("name")
|
|
||||||
|
|
||||||
# Write scalar fields to tabSingles
|
|
||||||
for field in SCALAR_FIELDS:
|
|
||||||
value = old_row.get(field)
|
|
||||||
if value is None:
|
|
||||||
continue
|
|
||||||
frappe.db.sql(
|
|
||||||
"""
|
|
||||||
INSERT INTO `tabSingles` (doctype, field, value)
|
|
||||||
VALUES ('E-Taxes Settings', %s, %s)
|
|
||||||
ON DUPLICATE KEY UPDATE value = VALUES(value)
|
|
||||||
""",
|
|
||||||
(field, str(value)),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Restore child table rows
|
|
||||||
for table in CHILD_TABLES:
|
|
||||||
if not frappe.db.table_exists(table):
|
|
||||||
continue
|
|
||||||
try:
|
|
||||||
child_rows = frappe.db.sql(
|
|
||||||
f"SELECT * FROM `{table}` WHERE parent = %s ORDER BY idx",
|
|
||||||
(old_name,),
|
|
||||||
as_dict=True,
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not child_rows:
|
|
||||||
continue
|
|
||||||
|
|
||||||
frappe.db.sql(f"DELETE FROM `{table}` WHERE parent = 'E-Taxes Settings'")
|
|
||||||
|
|
||||||
for row in child_rows:
|
|
||||||
row["parent"] = "E-Taxes Settings"
|
|
||||||
row["parenttype"] = "E-Taxes Settings"
|
|
||||||
columns = ", ".join(f"`{col}`" for col in row)
|
|
||||||
placeholders = ", ".join(["%s"] * len(row))
|
|
||||||
try:
|
|
||||||
frappe.db.sql(
|
|
||||||
f"INSERT INTO `{table}` ({columns}) VALUES ({placeholders})",
|
|
||||||
list(row.values()),
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
frappe.db.commit()
|
|
||||||
frappe.clear_cache(doctype="E-Taxes Settings")
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue