# Targo/Gigafibre FSM — Context for Claude Cowork > Last updated: 2026-03-30 ## Project Overview Targo Internet is a fiber ISP in Quebec. Gigafibre is the consumer brand. We're migrating from a legacy PHP/MariaDB system to ERPNext v16 + custom Vue.js (Quasar) apps. ## Architecture ``` Server: 96.125.196.67 (Proxmox VM) Traefik v2.11 (80/443) → Docker containers: erp.gigafibre.ca → ERPNext v16.10.1 (PostgreSQL, 9 containers) erp.gigafibre.ca/ops/ → Ops PWA (Quasar/Vue3, Authentik SSO via forwardAuth) dispatch.gigafibre.ca → Legacy dispatch app (being replaced by ops /dispatch) auth.targo.ca → Authentik SSO oss.gigafibre.ca → Oktopus CE (TR-069) git.targo.ca → Gitea n8n.gigafibre.ca → n8n workflows ``` ## Codebase Layout ``` gigafibre-fsm/ ├── apps/ │ ├── ops/ ← Main ops PWA (Quasar v2 + Vite) │ │ ├── src/ │ │ │ ├── api/ │ │ │ │ ├── auth.js # authFetch with token: b273a666c86d2d0:06120709db5e414 │ │ │ │ ├── dispatch.js # CRUD for Dispatch Job, Tech, Tag + rename/delete │ │ │ │ ├── service-request.js # ServiceRequest, ServiceBid, EquipmentInstall │ │ │ │ └── traccar.js # GPS tracking (Traccar API) │ │ │ ├── components/ │ │ │ │ ├── shared/ │ │ │ │ │ ├── TagEditor.vue # Universal inline tag editor (autocomplete, color, level, required) │ │ │ │ │ └── TagInput.vue # Old tag input (deprecated, replaced by TagEditor) │ │ │ │ └── customer/ # CustomerHeader, CustomerInfoCard, etc. │ │ │ ├── composables/ # useHelpers, useScheduler, useMap, useDragDrop, etc. │ │ │ ├── config/ │ │ │ │ └── erpnext.js # BASE_URL='', MAPBOX_TOKEN, TECH_COLORS │ │ │ ├── modules/ │ │ │ │ └── dispatch/ │ │ │ │ └── components/ # TimelineRow, BottomPanel, JobEditModal, RightPanel, etc. │ │ │ ├── pages/ │ │ │ │ ├── DispatchPage.vue # Full-screen dispatch V2 (1600+ lines) │ │ │ │ ├── ClientDetailPage.vue │ │ │ │ ├── ClientsPage.vue │ │ │ │ ├── TicketsPage.vue │ │ │ │ └── ... │ │ │ ├── stores/ │ │ │ │ ├── dispatch.js # Pinia store: technicians, jobs, allTags │ │ │ │ └── auth.js │ │ │ └── router/index.js # / = MainLayout, /dispatch = standalone │ │ └── deploy.sh # Build + deploy to erp.gigafibre.ca │ └── dispatch/ # Legacy standalone dispatch app (deprecated) ├── scripts/migration/ # Python migration scripts (tickets, customers, etc.) └── CONTEXT.md # This file ``` ## Key ERPNext Custom Doctypes ### Dispatch Job - `ticket_id`, `subject`, `customer` (Link→Customer), `service_location` (Link→Service Location) - `job_type` (Select: Installation/Réparation/Maintenance/Retrait/Dépannage/Autre) - `source_issue` (Link→Issue), `address`, `longitude`, `latitude` - `priority` (low/medium/high), `duration_h`, `status` (open/assigned/in_progress/done) - `assigned_tech` (Link→Dispatch Technician), `assigned_user` (Link→User) - `scheduled_date`, `start_time`, `end_date` - `tags` (Table→Dispatch Tag Link), `assistants` (Table→Dispatch Job Assistant) - `equipment_items`, `materials_used`, `checklist`, `photos`, `customer_signature` - `actual_start`, `actual_end`, `travel_time_min`, `completion_notes` ### Dispatch Technician - `technician_id`, `full_name`, `user` (Link→User), `phone`, `email` - `status` (Disponible/En route/En pause/Hors ligne), `color_hex` - `longitude`, `latitude`, `traccar_device_id`, `employee` (Link→Employee) - `tags` (Table→Dispatch Tag Link) ### Dispatch Tag - `label`, `color` (hex), `category` (Skill/Service/Region/Equipment/Custom) - Current tags: Fibre (#3b82f6), Téléphonie (#f59e0b), TV (#06b6d4), Installation (#06b6d4), Fusionneur (#f59e0b), Monteur (#8b5cf6), Câblage (#10b981), Caméra IP (#a855f7), Garage (#78716c), Urgence (#ef4444), Rive-Sud (#14b8a6), Montréal (#06b6d4) ### Dispatch Tag Link (child table) - `tag` (Link→Dispatch Tag), `level` (Int, default 0), `required` (Check, default 0) - On **techs**: level = skill proficiency (1=base, 5=expert) - On **jobs**: level = minimum required proficiency, required = mandatory for dispatch matching ### Issue (ERPNext standard + custom fields) - `legacy_ticket_id`, `assigned_staff` (group name e.g. "Tech Targo"), `opened_by_staff` - `issue_type`: "Reparation Fibre", "Installation Fibre", "Install/Reparation Télé", "Téléphonie", "Télévision", "Monteur", "Fusionneur", "Installation", "Support", "ToDo", "Projet", "Conception" - `is_incident`, `impact_zone`, `affected_clients`, `parent_incident`, `is_important` - `service_location` (Link→Service Location) ## Auth Pattern All API calls use token auth via `authFetch()`: ```js Authorization: token $ERP_SERVICE_TOKEN // see server .env ``` Authentik SSO protects the ops app at Traefik level (forwardAuth). The token is injected server-side by the nginx proxy (or via `VITE_ERP_TOKEN` in dev). ## Tag/Skill System — Auto-Dispatch Logic (designed, not yet wired) The dispatch system uses a cost-optimization model inspired by AI agent routing: 1. Each **job** has tags with `required` flag and `level` (minimum skill needed) 2. Each **tech** has tags with `level` (skill proficiency 1-5) 3. Auto-dispatch: find techs where `tech.level >= job.requiredLevel` for all **required** tags 4. Among matches, pick the **lowest adequate** tech (closest skill to required level) 5. This preserves experts for complex jobs — don't send the level-5 splicer to a basic install Example: - Job: Fibre (required, level 3) → needs someone competent - Tech A: Fibre level 5 (expert) — can do it but overkill - Tech B: Fibre level 3 (adequate) — send this one, keep A free ## 20 Test Dispatch Jobs (2026-03-31) Created from Tech Targo Issues. Tagged by issue_type: - 6 jobs: Fibre only (Reparation Fibre) - 4 jobs: Fibre + Installation (Installation/Installation Fibre) - 10 jobs: TV + Téléphonie (Install/Reparation Télé) ## 46 Dispatch Technicians All imported from legacy system. **Not yet tagged with skills** — need team breakdown. ## Deploy ```bash cd apps/ops && bash deploy.sh # builds Quasar PWA + deploys to erp.gigafibre.ca ``` ## Pending Work 1. **Tag technicians with skills** — assign Fibre/Télé/etc. tags + levels to 46 techs 2. **Wire auto-dispatch logic** — implement the matching algorithm in useAutoDispatch.js 3. **Ticket-to-dispatch UI** — button in ticket detail modal to create Dispatch Job from Issue 4. **Customer portal** — store.targo.ca/clients replacement with Stripe payments 5. **Field tech mobile app** — barcode scanner, equipment install, job completion 6. **Code optimization** — extract components from ClientDetailPage.vue (1500+ lines) ## ERPNext PostgreSQL Gotchas - GROUP BY requires all selected columns (not just aggregates) - HAVING clause needs explicit column references - Double-quoted identifiers are case-sensitive - Transaction abort cascades (one error blocks subsequent queries until rollback) - Patches applied in `scripts/migration/` for bulk operations