gigafibre-fsm/scripts/migration/debug_match.py
louispaulb 607ea54b5c refactor: reduce token count, DRY code, consolidate docs
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>
2026-04-13 08:39:58 -04:00

76 lines
2.8 KiB
Python

"""Debug the exact matching logic."""
import frappe, pymysql, os, sys
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()
DEFAULT_INCOME = "Autres produits d'exploitation - T"
# Build the same mapping as fix script
legacy = pymysql.connect(
host="legacy-db", user="facturation", password="VD67owoj",
database="gestionclient", cursorclass=pymysql.cursors.DictCursor
)
with legacy.cursor() as cur:
cur.execute("""SELECT p.sku, pc.num_compte FROM product p JOIN product_cat pc ON p.category = pc.id
WHERE p.sku IS NOT NULL AND p.sku != '' AND pc.num_compte IS NOT NULL""")
sku_to_gl_num = {r['sku']: str(int(r['num_compte'])) for r in cur.fetchall() if r['num_compte']}
accts = frappe.db.sql("""SELECT account_number, name FROM "tabAccount"
WHERE root_type IN ('Income','Expense') AND company='TARGO' AND is_group=0
AND account_number IS NOT NULL AND account_number != ''""")
gl_by_number = {r[0]: r[1] for r in accts}
sku_to_income = {sku: gl_by_number[num] for sku, num in sku_to_gl_num.items() if num in gl_by_number}
# Test with legacy_id 609669
legacy_id = 609669
with legacy.cursor() as cur:
cur.execute("""SELECT invoice_id, sku,
ROW_NUMBER() OVER (PARTITION BY invoice_id ORDER BY id) as rn
FROM invoice_item WHERE invoice_id = %s ORDER BY id""", (legacy_id,))
items = cur.fetchall()
legacy.close()
inv_item_map = {}
for li in items:
sku = li['sku'] or ''
acct = sku_to_income.get(sku)
if acct:
idx = li['rn']
inv_item_map[idx] = acct
print(f" rn={idx} sku={sku}{acct}")
else:
print(f" rn={li['rn']} sku={li['sku']} → NOT MAPPED")
print(f"\nMapping for 609669: {inv_item_map}")
# Now simulate the fix script logic
inv_rows = frappe.db.sql("""
SELECT name, legacy_invoice_id FROM "tabSales Invoice"
WHERE legacy_invoice_id = %s
""", (legacy_id,))
print(f"\nERPNext invoice: {inv_rows}")
inv_names = [r[0] for r in inv_rows]
inv_id_map = {r[0]: int(r[1]) for r in inv_rows}
print(f"inv_id_map: {inv_id_map}")
# The fix script uses inv_item_map[legacy_id][idx]
# But we built it as inv_item_map[idx] for this test
# In the actual script, it's inv_item_map = { legacy_invoice_id: { idx: acct } }
# Let's check types
r = frappe.db.sql('SELECT legacy_invoice_id FROM "tabSales Invoice" WHERE name = %s', (inv_names[0],))
print(f"\nlegacy_invoice_id raw value: {repr(r[0][0])}, type: {type(r[0][0])}")
# Check if the bug is type mismatch
full_map = {legacy_id: inv_item_map}
lid = inv_id_map[inv_names[0]]
print(f"Looking up lid={repr(lid)} type={type(lid)}")
print(f"Keys in full_map: {list(full_map.keys())}, types: {[type(k) for k in full_map.keys()]}")
print(f"lid in full_map: {lid in full_map}")
frappe.destroy()