- 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>
127 lines
4.0 KiB
Python
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!")
|