gigafibre-fsm/scripts/migration/fix_gl_entries.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

72 lines
2.3 KiB
Python

"""Fix GL entries to match updated invoice item income_accounts."""
import frappe, os, sys, time
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()
print("Connected:", frappe.local.site)
DEFAULT_INCOME = "Autres produits d'exploitation - T"
print("=== Update GL Entries ===")
t0 = time.time()
# Get dominant income account per invoice (highest total amount)
print(" Getting dominant account per invoice...")
dom = frappe.db.sql("""
SELECT parent, income_account, SUM(ABS(base_net_amount)) as total
FROM "tabSales Invoice Item"
WHERE income_account != %s
GROUP BY parent, income_account
""", (DEFAULT_INCOME,))
inv_best = {}
for inv_name, acct, total in dom:
total = float(total or 0)
if inv_name not in inv_best or total > inv_best[inv_name][1]:
inv_best[inv_name] = (acct, total)
print(f" {len(inv_best)} invoices with mapped accounts")
# Batch update GL entries
by_acct = {}
for inv_name, (acct, _) in inv_best.items():
by_acct.setdefault(acct, []).append(inv_name)
gl_updated = 0
for acct_name, inv_names in by_acct.items():
for i in range(0, len(inv_names), 1000):
batch = inv_names[i:i+1000]
placeholders = ','.join(['%s'] * len(batch))
frappe.db.sql(
f"""UPDATE "tabGL Entry" SET account = %s
WHERE voucher_type = 'Sales Invoice'
AND voucher_no IN ({placeholders})
AND account = %s""",
[acct_name] + batch + [DEFAULT_INCOME]
)
frappe.db.commit()
gl_updated += len(inv_names)
print(f" {acct_name}: {len(inv_names)} invoices")
print(f" Total: {gl_updated} invoices [{time.time()-t0:.0f}s]")
# Verify
print("\n=== Verify ===")
r = frappe.db.sql("""
SELECT account, COUNT(*) as cnt, ROUND(SUM(credit)::numeric, 2) as total_credit
FROM "tabGL Entry"
WHERE voucher_type = 'Sales Invoice' AND credit > 0
GROUP BY account ORDER BY total_credit DESC LIMIT 25
""")
print(" GL credit entries by account (Sales Invoice):")
for row in r:
print(f" {row[1]:>10} ${row[2]:>14} {row[0]}")
# Drop temp table if exists
frappe.db.sql("DROP TABLE IF EXISTS _tmp_sku_income_map")
frappe.db.commit()
frappe.destroy()
print("\nDone!")