gigafibre-fsm/scripts/server_bulk_submit.py
louispaulb 4693bcf60c feat: telephony UI, performance indexes, Twilio softphone, lazy-load invoices
- Add PostgreSQL performance indexes migration script (1000x faster queries)
  Sales Invoice: 1,248ms → 28ms, Payment Entry: 443ms → 31ms
  Indexes on customer/party columns for all major tables
- Disable 3CX poller (PBX_ENABLED flag, using Twilio instead)
- Add TelephonyPage: full CRUD UI for Routr/Fonoster resources
  (trunks, agents, credentials, numbers, domains, peers)
- Add PhoneModal + usePhone composable (Twilio WebRTC softphone)
- Lazy-load invoices/payments (initial 5, expand on demand)
- Parallelize all API calls in ClientDetailPage (no waterfall)
- Add targo-hub service (SSE relay, SMS, voice, telephony API)
- Customer portal: invoice detail, ticket detail, messages pages
- Remove dead Ollama nginx upstream

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 13:59:59 -04:00

127 lines
4.0 KiB
Python

#!/usr/bin/env python3
"""
Server-side bulk submit script for ERPNext migration data.
Run this INSIDE the erpnext-backend container via bench console.
Usage:
1. SSH into server: ssh root@96.125.196.67
2. Enter container: docker exec -it erpnext-backend-1 bash
3. Go to bench: cd /home/frappe/frappe-bench
4. Run: bench --site all execute scripts.server_bulk_submit.run
OR copy this file and run with bench console:
bench --site erp.gigafibre.ca console
Then paste the code below.
BEFORE RUNNING: Fix the PostgreSQL GROUP BY bug first! (see fix_ple_postgres.sh)
"""
# === Paste this into bench console ===
import frappe
def run():
"""Main entry point for bench execute"""
site = frappe.local.site
print(f"Running on site: {site}")
# Mute all emails and notifications
frappe.flags.mute_emails = True
frappe.flags.mute_notifications = True
frappe.flags.in_import = True
# Step 1: Enable disabled items
print("\n═══ Step 1: Enable disabled Items ═══")
disabled_items = frappe.get_all("Item", filters={"disabled": 1}, pluck="name")
print(f" Found {len(disabled_items)} disabled items")
for item_name in disabled_items:
frappe.db.set_value("Item", item_name, "disabled", 0, update_modified=False)
frappe.db.commit()
print(f" Enabled all {len(disabled_items)} items")
# Step 2: Submit Sales Invoices
print("\n═══ Step 2: Submit Sales Invoices ═══")
draft_invoices = frappe.get_all(
"Sales Invoice",
filters={"docstatus": 0},
pluck="name",
order_by="posting_date asc",
limit_page_length=0
)
total_inv = len(draft_invoices)
print(f" Total draft invoices: {total_inv}")
ok, fail = 0, 0
errors = []
for i, inv_name in enumerate(draft_invoices):
try:
inv = frappe.get_doc("Sales Invoice", inv_name)
inv.set_posting_time = 1 # keep original posting_date
inv.flags.ignore_permissions = True
inv.flags.mute_emails = True
inv.flags.ignore_notifications = True
inv.submit()
ok += 1
if ok % 100 == 0:
frappe.db.commit()
print(f" Progress: {ok + fail}/{total_inv} (ok={ok}, fail={fail})")
except Exception as e:
fail += 1
frappe.db.rollback()
if len(errors) < 30:
errors.append(f"{inv_name}: {str(e)[:150]}")
frappe.db.commit()
print(f" Done: submitted={ok}, failed={fail}")
if errors:
print(f" Errors (first {len(errors)}):")
for e in errors:
print(f" {e}")
# Step 3: Submit Payment Entries
print("\n═══ Step 3: Submit Payment Entries ═══")
draft_payments = frappe.get_all(
"Payment Entry",
filters={"docstatus": 0},
pluck="name",
order_by="posting_date asc",
limit_page_length=0
)
total_pe = len(draft_payments)
print(f" Total draft payments: {total_pe}")
ok, fail = 0, 0
errors = []
for i, pe_name in enumerate(draft_payments):
try:
pe = frappe.get_doc("Payment Entry", pe_name)
pe.flags.ignore_permissions = True
pe.flags.mute_emails = True
pe.flags.ignore_notifications = True
pe.submit()
ok += 1
if ok % 100 == 0:
frappe.db.commit()
print(f" Progress: {ok + fail}/{total_pe} (ok={ok}, fail={fail})")
except Exception as e:
fail += 1
frappe.db.rollback()
if len(errors) < 30:
errors.append(f"{pe_name}: {str(e)[:150]}")
frappe.db.commit()
print(f" Done: submitted={ok}, failed={fail}")
if errors:
print(f" Errors (first {len(errors)}):")
for e in errors:
print(f" {e}")
# Unmute
frappe.flags.mute_emails = False
frappe.flags.mute_notifications = False
frappe.flags.in_import = False
print("\n✓ All done!")