# Gigafibre FSM Complete operations platform for **Gigafibre** (consumer brand of TARGO Internet), a fiber ISP in Quebec. Replaces a legacy PHP/MariaDB billing system with ERPNext v16 + custom Vue.js (Quasar) apps. ## What This Repo Contains | Directory | Description | |-----------|-------------| | `apps/ops/` | **Targo Ops** — main operations PWA (Vue 3 / Quasar v2) | | `apps/field/` | **Targo Field** — mobile app for technicians (barcode, diagnostics, offline) | | `apps/client/` | **Gigafibre Portal** — customer self-service portal | | `apps/website/` | **www.gigafibre.ca** — marketing site (React / Vite / Tailwind) | | `apps/dispatch/` | Legacy dispatch app (replaced by `apps/ops/` dispatch module) | | `apps/portal/` | Customer portal deploy configs | | `erpnext/` | ERPNext custom doctype setup scripts | | `scripts/migration/` | 51 Python scripts for legacy-to-ERPNext data migration | | `scripts/` | Utility scripts (bulk submit, PostgreSQL fixes) | | `docs/` | Architecture, infrastructure, migration plan, changelog | ## Architecture ``` 96.125.196.67 (Proxmox VM, Ubuntu 24.04) | Traefik v2.11 (TLS via Let's Encrypt) | +-- erp.gigafibre.ca ERPNext v16.10.1 (PostgreSQL, 9 containers) +-- erp.gigafibre.ca/ops/ Ops PWA (Quasar/Vue3, Authentik SSO) +-- id.gigafibre.ca Authentik SSO (customer-facing) +-- auth.targo.ca Authentik SSO (staff, federated to id.gigafibre.ca) +-- n8n.gigafibre.ca n8n workflow automation +-- git.targo.ca Gitea +-- www.gigafibre.ca Marketing site + address API +-- oss.gigafibre.ca Oktopus CE (TR-069 CPE management) +-- tracker.targointernet.com Traccar GPS tracking ``` ## Features ### Ops App (`apps/ops/`) - **Client Management** — customer list with search by name, account ID, legacy ID. Inline editing (double-click any field to edit, saves to ERPNext in background) - **Client Detail** — full customer view with contact, billing KPIs, service locations, subscriptions, equipment, tickets, invoices, payments, notes - **Inline Editing** — Odoo-style double-click-to-edit on all fields (locations, equipment, tickets, invoices). Uses `InlineField` component + `useInlineEdit` composable - **Dispatch Timeline** — drag-drop job scheduling with Mapbox map, GPS tracking (Traccar), technician management, tag/skill system - **Ticket Management** — list with inline status/priority editing, detail modal with reply thread - **Equipment Tracking** — serial/MAC, status lifecycle, OLT info, per-location grouping - **SMS/Email Notifications** — send from contact card via n8n webhooks (Twilio SMS, Mailjet email) - **Invoice OCR** — scan paper bills using Ollama Vision (llama3.2-vision) - **PWA** — installable, offline-capable with Workbox ### Legacy Migration (completed) Migrated from a 15-year-old PHP/MariaDB billing system: | Data | Volume | Status | |------|--------|--------| | Customers | 6,667 (active + terminated) | Migrated | | Contacts + Addresses | ~6,600 each | Migrated | | Service Locations | ~17,000 | Migrated | | Subscriptions | 21,876 (with RADIUS credentials) | Migrated | | Items (products/plans) | 833 | Migrated | | Sales Invoices | 115,000+ | Migrated | | Payments | 99,000+ | Migrated with invoice references | | Tickets (Issues) | 242,000+ (parent/child hierarchy) | Migrated | | Ticket Messages (Communications) | 784,000+ | Migrated | | Customer Memos (Comments) | 29,000+ | Migrated with real dates | | Employees | 45 ERPNext Users from legacy staff | Migrated | ### Bugs Fixed From Legacy System - **Date corruption** — Unix timestamps stored as strings; fixed during import with timezone-aware conversion - **Invoice outstanding amounts** — payment_item references broken in legacy; reconciled during migration - **Customer links** — orphan records (invoices/payments without valid customer); rebuilt relationships - **Subscription details** — missing service_location links, incorrect billing frequencies; corrected via analysis scripts - **Reversal transactions** — credit notes improperly recorded; mapped to ERPNext return invoices - **Annual billing dates** — yearly subscriptions had wrong period boundaries; recalculated - **Duplicate customer IDs** — legacy allowed duplicate customer_id; resolved with rename script - **Staff/ticket ownership** — legacy used numeric IDs for assignment; mapped to ERPNext User emails ### ERPNext Adjustments for Import - **Direct PostgreSQL inserts** — Frappe ORM too slow for 100K+ records; used psycopg2 with proper `tabXxx` schema - **Scheduler paused** — disabled auto-invoicing during import to prevent 21K subscriptions from generating invoices - **Custom fields on Customer** — `legacy_account_id`, `legacy_customer_id`, `ppa_enabled`, `stripe_id`, date fields - **Custom fields on Item** — `legacy_product_id`, download/upload speeds, quotas, OLT profiles - **Custom fields on Subscription** — `radius_user`, `radius_pwd`, `legacy_service_id` - **Custom fields on Issue** — `legacy_ticket_id`, `assigned_staff`, `opened_by_staff`, `issue_type`, `is_important`, `service_location` - **PostgreSQL GROUP BY patch** — ERPNext v16 generates MySQL-style queries; patched `number_card.py` and PLE reports - **Subscription API unlock** — removed `read_only` and `set_only_once` restrictions on Subscription fields for REST API updates - **Portal auth bridge** — server script for legacy MD5 password migration to PBKDF2 ## ERPNext Custom Doctypes ### Field Service Management | Doctype | ID Pattern | Purpose | |---------|-----------|---------| | Service Location | LOC-##### | Customer premises (address, GPS, OLT port, network config) | | Service Equipment | EQP-##### | Deployed hardware (ONT, router, TV box — serial, MAC, IP) | | Service Subscription | SUB-##### | Active service plans (speed, price, billing cycle, RADIUS) | ### Dispatch | Doctype | Purpose | |---------|---------| | Dispatch Job | Work orders with equipment, materials, checklist, photos, signature | | Dispatch Technician | Tech profiles with GPS link (Traccar), skills, color coding | | Dispatch Tag | Categorization with skill levels (Fibre, TV, Telephonie, etc.) | | Dispatch Tag Link | Child table linking tags to jobs/techs with level + required flag | ### Child Tables Equipment Move Log, Job Equipment Item, Job Material Used, Job Checklist Item, Job Photo, Dispatch Job Assistant, Checklist Template + Items ## Quick Start ### Development ```bash # Ops app cd apps/ops npm install npx quasar dev # Website cd apps/website npm install npm run dev ``` ### Deploy Ops to Production ```bash cd apps/ops bash deploy.sh # builds PWA + deploys to server via SSH ``` ### Run Migration Scripts ```bash # Scripts run inside the ERPNext backend container docker cp scripts/migration/migrate_all.py frappe_docker-backend-1:/tmp/ docker exec frappe_docker-backend-1 bench --site erp.gigafibre.ca execute /tmp/migrate_all.main ``` ### Setup FSM Doctypes ```bash docker cp erpnext/setup_fsm_doctypes.py frappe_docker-backend-1:/home/frappe/frappe-bench/apps/frappe/frappe/ docker exec frappe_docker-backend-1 bench --site erp.gigafibre.ca execute frappe.setup_fsm_doctypes.create_all ``` ## Documentation | Document | Content | |----------|---------| | [ARCHITECTURE.md](docs/ARCHITECTURE.md) | Data model, tech stack, authentication flow, doctype reference | | [INFRASTRUCTURE.md](docs/INFRASTRUCTURE.md) | Server, DNS, Traefik, Authentik, Docker, n8n, gotchas | | [MIGRATION-PLAN.md](docs/MIGRATION-PLAN.md) | Legacy system portrait, mapping, phases, risks | | [CHANGELOG.md](docs/CHANGELOG.md) | Detailed migration log with volumes and methods | | [ROADMAP.md](docs/ROADMAP.md) | 5-phase implementation plan | | [MIGRATION_MAP.md](scripts/migration/MIGRATION_MAP.md) | Field-level mapping legacy tables to ERPNext | | [COMPETITIVE-ANALYSIS.md](docs/COMPETITIVE-ANALYSIS.md) | Comparison with Gaiia, Odoo, Zuper, Salesforce, ServiceTitan | ## Infrastructure | Service | URL | Technology | |---------|-----|------------| | ERP | erp.gigafibre.ca | ERPNext v16.10.1 (Frappe, PostgreSQL) | | Ops | erp.gigafibre.ca/ops/ | Quasar v2 PWA | | SSO (staff) | auth.targo.ca | Authentik | | SSO (customers) | id.gigafibre.ca | Authentik (federated from auth.targo.ca) | | Workflows | n8n.gigafibre.ca | n8n | | Git | git.targo.ca | Gitea | | GPS | tracker.targointernet.com | Traccar | | Website | www.gigafibre.ca | React / Vite / Tailwind | | CPE Mgmt | oss.gigafibre.ca | Oktopus CE (TR-069) | | DNS | Cloudflare | gigafibre.ca (DNS-only, Traefik handles TLS) | | Email | Mailjet | noreply@targo.ca | | SMS | Twilio | +1 438 231-3838 | ## Tech Stack | Layer | Technology | |-------|-----------| | Backend | ERPNext v16 / Frappe (Python) on PostgreSQL | | Frontend (ops) | Vue 3, Quasar v2, Pinia, Vite | | Frontend (website) | React, Vite, Tailwind, shadcn/ui | | Maps | Mapbox GL JS + Directions API | | GPS | Traccar (REST + WebSocket) | | Auth | Authentik SSO (forwardAuth via Traefik) | | Proxy | Traefik v2.11 (Let's Encrypt) | | Automation | n8n webhooks | | SMS | Twilio (via n8n) | | Email | Mailjet (via n8n) | | OCR | Ollama (llama3.2-vision) | | Hosting | Proxmox VM, Ubuntu 24.04, Docker |