Backend services: - targo-hub: extract deepGetValue to helpers.js, DRY disconnect reasons lookup map, compact CAPABILITIES, consolidate vision.js prompts/schemas, extract dispatch scoring weights, trim section dividers across 9 files - modem-bridge: extract getSession() helper (6 occurrences), resetIdleTimer(), consolidate DM query factory, fix duplicate username fill bug, trim headers (server.js -36%, tplink-session.js -47%, docker-compose.yml -57%) Frontend: - useWifiDiagnostic: extract THRESHOLDS const, split processDiagnostic into 6 focused helpers (processOnlineStatus, processWanIPs, processRadios, processMeshNodes, processClients, checkRadioIssues) - EquipmentDetail: merge duplicate ROLE_LABELS, remove verbose comments Documentation (17 → 13 files, -1,400 lines): - New consolidated README.md (architecture, services, dependencies, auth) - Merge ECOSYSTEM-OVERVIEW into ARCHITECTURE.md - Merge MIGRATION-PLAN + ARCHITECTURE-COMPARE + FIELD-GAP + CHANGELOG → MIGRATION.md - Merge COMPETITIVE-ANALYSIS into PLATFORM-STRATEGY.md - Update ROADMAP.md with current phase status - Delete CONTEXT.md (absorbed into README) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Fix Issue owner + _assign from legacy ticket.open_by / assign_to → ERPNext User email.
|
|
Direct PG. Detached.
|
|
"""
|
|
import pymysql
|
|
import psycopg2
|
|
import json
|
|
|
|
LEGACY = {"host": "legacy-db", "user": "facturation", "password": "VD67owoj",
|
|
"database": "gestionclient", "connect_timeout": 30, "read_timeout": 300}
|
|
PG = {"host": "db", "port": 5432, "user": "postgres", "password": "123",
|
|
"dbname": "_eb65bdc0c4b1b2d6"}
|
|
|
|
def log(msg):
|
|
print(msg, flush=True)
|
|
|
|
def main():
|
|
log("=== Fix Issue Owners + Assignees ===")
|
|
|
|
# Staff ID → email
|
|
mc = pymysql.connect(**LEGACY)
|
|
cur = mc.cursor(pymysql.cursors.DictCursor)
|
|
cur.execute("SELECT id, email FROM staff WHERE email IS NOT NULL AND email != ''")
|
|
staff_email = {r["id"]: r["email"] for r in cur.fetchall()}
|
|
|
|
# ticket → open_by, assign_to
|
|
cur.execute("SELECT id, open_by, assign_to FROM ticket ORDER BY id")
|
|
tickets = cur.fetchall()
|
|
mc.close()
|
|
log(" {} tickets, {} staff with email".format(len(tickets), len(staff_email)))
|
|
|
|
pg = psycopg2.connect(**PG)
|
|
pgc = pg.cursor()
|
|
|
|
# ERPNext users (verify they exist)
|
|
pgc.execute('SELECT name FROM "tabUser" WHERE enabled = 1')
|
|
valid_users = set(r[0] for r in pgc.fetchall())
|
|
|
|
# Issue legacy_ticket_id → name
|
|
pgc.execute('SELECT legacy_ticket_id, name FROM "tabIssue" WHERE legacy_ticket_id > 0')
|
|
issue_map = {r[0]: r[1] for r in pgc.fetchall()}
|
|
log(" {} issues mapped".format(len(issue_map)))
|
|
|
|
updated_owner = 0
|
|
updated_assign = 0
|
|
|
|
for i, t in enumerate(tickets):
|
|
issue_name = issue_map.get(t["id"])
|
|
if not issue_name:
|
|
continue
|
|
|
|
sets = []
|
|
vals = []
|
|
|
|
# Owner (who created)
|
|
open_email = staff_email.get(t.get("open_by"))
|
|
if open_email and open_email in valid_users:
|
|
sets.append('owner = %s')
|
|
vals.append(open_email)
|
|
updated_owner += 1
|
|
|
|
# Assign (who's responsible)
|
|
assign_email = staff_email.get(t.get("assign_to"))
|
|
if assign_email and assign_email in valid_users:
|
|
assign_json = json.dumps([assign_email])
|
|
sets.append('"_assign" = %s')
|
|
vals.append(assign_json)
|
|
updated_assign += 1
|
|
|
|
if sets:
|
|
vals.append(issue_name)
|
|
pgc.execute('UPDATE "tabIssue" SET {} WHERE name = %s'.format(", ".join(sets)), vals)
|
|
|
|
if (i + 1) % 5000 == 0:
|
|
pg.commit()
|
|
log(" [{}/{}] owner={} assign={}".format(i+1, len(tickets), updated_owner, updated_assign))
|
|
|
|
pg.commit()
|
|
pg.close()
|
|
|
|
log("")
|
|
log("=" * 50)
|
|
log("Owner updated: {}".format(updated_owner))
|
|
log("Assign updated: {}".format(updated_assign))
|
|
log("=" * 50)
|
|
|
|
if __name__ == "__main__":
|
|
main()
|