""" Import payment arrangements (accord_paiement) from legacy. Creates Payment Arrangement records linked to Customer. Run inside erpnext-backend-1: /home/frappe/frappe-bench/env/bin/python /home/frappe/frappe-bench/import_payment_arrangements.py """ import frappe import pymysql import os, sys, time from datetime import datetime, timezone sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1) os.chdir("/home/frappe/frappe-bench/sites") frappe.init(site="erp.gigafibre.ca", sites_path=".") frappe.connect() frappe.local.flags.ignore_permissions = True print("Connected:", frappe.local.site) legacy = pymysql.connect( host="legacy-db", user="facturation", password="VD67owoj", database="gestionclient", cursorclass=pymysql.cursors.DictCursor ) # Build mappings cust_map = {} for r in frappe.db.sql('SELECT name, legacy_account_id FROM "tabCustomer" WHERE legacy_account_id > 0', as_dict=True): cust_map[int(r['legacy_account_id'])] = r['name'] print(f" {len(cust_map)} customers mapped") staff_map = {} # Employee names are HR-EMP-{N}, no legacy_staff_id field — map by name for display only STATUS_MAP = {-1: "Pending", 0: "Open", 1: "Completed"} METHOD_MAP = {0: "", 1: "Portail", 2: "Cheque", 3: "Telephone", 4: "PPA"} def ts_to_date(unix_ts): if not unix_ts or unix_ts <= 0: return None try: return datetime.fromtimestamp(int(unix_ts), tz=timezone.utc).strftime("%Y-%m-%d") except (ValueError, OSError): return None # Clear existing existing = frappe.db.sql('SELECT COUNT(*) FROM "tabPayment Arrangement"')[0][0] if existing: frappe.db.sql('DELETE FROM "tabPayment Arrangement"') frappe.db.commit() print(f" Cleared {existing} existing Payment Arrangements") # Load all print("\n=== Loading legacy accords ===") with legacy.cursor() as cur: cur.execute("SELECT * FROM accord_paiement ORDER BY id") rows = cur.fetchall() legacy.close() print(f" {len(rows)} accords to import") T0 = time.time() created = skipped = 0 batch = [] for r in rows: cust = cust_map.get(r['account_id']) if not cust: skipped += 1 continue staff_name = f"Staff #{r['staff_id']}" if r.get('staff_id') and r['staff_id'] > 0 else '' doc = frappe.get_doc({ "doctype": "Payment Arrangement", "customer": cust, "status": STATUS_MAP.get(r['status'], "Open"), "amount": float(r['montant'] or 0), "method": METHOD_MAP.get(r['method'], ""), "date_agreed": ts_to_date(r['date_accord']), "date_due": ts_to_date(r['date_echeance']), "date_cutoff": ts_to_date(r['date_coupure']), "staff": staff_name, "note": (r['note'] or '').strip(), "reason": (r['raison_changement'] or '').strip(), "legacy_accord_id": r['id'], "legacy_account_id": r['account_id'], }) doc.insert(ignore_if_duplicate=True) created += 1 if created % 500 == 0: frappe.db.commit() print(f" [{created}/{len(rows)}] [{time.time()-T0:.0f}s]") frappe.db.commit() # ── Verify ── print(f"\n=== Summary ===") dist = frappe.db.sql('SELECT status, COUNT(*) FROM "tabPayment Arrangement" GROUP BY status ORDER BY COUNT(*) DESC') for r in dist: print(f" {r[0]:15s} {r[1]}") print(f" Created: {created}, Skipped (no customer): {skipped}") print(f" Time: {time.time()-T0:.0f}s") frappe.destroy() print("Done!")