gigafibre-fsm/scripts/migration/import_technicians.py
louispaulb 101faa21f1 feat: inline editing, search, notifications + full repo cleanup
- InlineField component + useInlineEdit composable for Odoo-style dblclick editing
- Client search by name, account ID, and legacy_customer_id (or_filters)
- SMS/Email notification panel on ContactCard via n8n webhooks
- Ticket reply thread via Communication docs
- All migration scripts (51 files) now tracked
- Client portal and field tech app added to monorepo
- README rewritten with full feature list, migration summary, architecture
- CHANGELOG updated with all recent work
- ROADMAP updated with current completion status
- Removed hardcoded tokens from docs (use $ERP_SERVICE_TOKEN)
- .gitignore updated (docker/, .claude/, exports/, .quasar/)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 07:34:41 -04:00

146 lines
5.6 KiB
Python

"""
Link Employee → Dispatch Technician and populate technicians from active staff.
Run inside erpnext-backend-1:
/home/frappe/frappe-bench/env/bin/python /home/frappe/frappe-bench/import_technicians.py
"""
import frappe
import os
import time
from datetime import datetime
os.chdir("/home/frappe/frappe-bench/sites")
frappe.init(site="erp.gigafibre.ca", sites_path=".")
frappe.connect()
frappe.local.flags.ignore_permissions = True
print("Connected:", frappe.local.site)
now_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
# ═══════════════════════════════════════════════════════════════
# PHASE 1: Add 'employee' Link field to Dispatch Technician
# ═══════════════════════════════════════════════════════════════
print("\n" + "="*60)
print("PHASE 1: ADD EMPLOYEE LINK FIELD")
print("="*60)
existing = frappe.db.sql("""
SELECT fieldname FROM "tabDocField"
WHERE parent = 'Dispatch Technician' AND fieldname = 'employee'
""")
if not existing:
# Get max idx
max_idx = frappe.db.sql("""
SELECT COALESCE(MAX(idx), 0) FROM "tabDocField"
WHERE parent = 'Dispatch Technician'
""")[0][0]
frappe.db.sql("""
INSERT INTO "tabDocField" (
name, creation, modified, modified_by, owner, docstatus, idx,
parent, parentfield, parenttype,
fieldname, label, fieldtype, options, reqd, read_only, hidden
) VALUES (
%(name)s, %(now)s, %(now)s, 'Administrator', 'Administrator', 0, %(idx)s,
'Dispatch Technician', 'fields', 'DocType',
'employee', 'Employee', 'Link', 'Employee', 0, 0, 0
)
""", {
"name": "dt-employee-link-{}".format(int(time.time())),
"now": now_str,
"idx": max_idx + 1,
})
# Add the column to the actual table
try:
frappe.db.sql("""
ALTER TABLE "tabDispatch Technician" ADD COLUMN employee varchar(140)
""")
except Exception as e:
if "already exists" in str(e).lower() or "duplicate" in str(e).lower():
print("Column 'employee' already exists")
else:
raise
frappe.db.commit()
print("Added 'employee' Link field to Dispatch Technician")
else:
print("'employee' field already exists on Dispatch Technician")
# ═══════════════════════════════════════════════════════════════
# PHASE 2: Clear test technicians and populate from employees
# ═══════════════════════════════════════════════════════════════
print("\n" + "="*60)
print("PHASE 2: POPULATE TECHNICIANS FROM EMPLOYEES")
print("="*60)
# Delete existing test technicians
existing_techs = frappe.db.sql('SELECT COUNT(*) FROM "tabDispatch Technician"')[0][0]
if existing_techs > 0:
frappe.db.sql('DELETE FROM "tabDispatch Technician"')
frappe.db.commit()
print("Deleted {} test technicians".format(existing_techs))
# Get active employees in tech/support/sysadmin roles (Operations + Customer Service departments)
# These are the staff who do field work or dispatch-related tasks
employees = frappe.db.sql("""
SELECT name, employee_name, employee_number, cell_number, company_email,
department, designation, status
FROM "tabEmployee"
WHERE status = 'Active'
AND department IN ('Operations - T', 'Customer Service - T', 'Management - T')
ORDER BY name
""", as_dict=True)
print("Active dispatch-eligible employees: {}".format(len(employees)))
counter = 0
for emp in employees:
counter += 1
tech_id = "TECH-{}".format(emp["employee_number"])
tech_name = tech_id # document name
frappe.db.sql("""
INSERT INTO "tabDispatch Technician" (
name, creation, modified, modified_by, owner, docstatus, idx,
technician_id, full_name, phone, email, status, employee
) VALUES (
%(name)s, %(now)s, %(now)s, 'Administrator', 'Administrator', 0, 0,
%(tech_id)s, %(full_name)s, %(phone)s, %(email)s, 'Disponible', %(employee)s
)
""", {
"name": tech_name,
"now": now_str,
"tech_id": tech_id,
"full_name": emp["employee_name"],
"phone": emp["cell_number"],
"email": emp["company_email"],
"employee": emp["name"],
})
frappe.db.commit()
print("Created {} Dispatch Technicians".format(counter))
# ═══════════════════════════════════════════════════════════════
# PHASE 3: VERIFY
# ═══════════════════════════════════════════════════════════════
print("\n" + "="*60)
print("PHASE 3: VERIFY")
print("="*60)
techs = frappe.db.sql("""
SELECT name, technician_id, full_name, phone, email, employee
FROM "tabDispatch Technician"
ORDER BY name
""", as_dict=True)
print("Total Dispatch Technicians: {}".format(len(techs)))
for t in techs:
print(" {}{} phone={} email={} emp={}".format(
t["technician_id"], t["full_name"],
t["phone"] or "-", t["email"] or "-", t["employee"]))
# Clear cache
frappe.clear_cache()
print("\nCache cleared — Dispatch Technician doctype updated")