Customer IDs are now the raw legacy customer_id (bank payment reference):
LPB4, 114796350603272, DOMIL5149490230
New customers: C + 14 digits sequential (C10000000000001)
No collision with existing 15-digit bank references (gap at 10^13).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch Ops data source from Subscription to Service Subscription (source of truth)
- Reimport 39,630 native Subscriptions from Service Subscription data
- Rename 15,302 customers to CUST-{legacy_customer_id} (eliminates hex UUIDs)
- Rename all doctypes to zero-padded 10-digit numeric format:
SINV-0000001234, PE-0000001234, ISS-0000001234, LOC-0000001234,
EQP-0000001234, SUB-0000001234, ASUB-0000001234
- Fix subscription pricing: LPB4 now correctly shows 0$/month
- Update ASUB- prefix detection in useSubscriptionActions.js
- Add reconciliation, reimport, and rename migration scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
All /api/ and /ollama/ requests now go through the ops base path
(/ops/api/... and /ops/ollama/...) so Traefik routes them to
ops-frontend nginx, which injects the ERPNext token server-side.
Token is never exposed in the browser.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Ollama container running llama3.2-vision:11b on server
- OCR page in ops app: camera/upload → Ollama extracts vendor, date,
amounts, line items → editable form → create Purchase Invoice
- nginx proxies /ollama/ to Ollama API (both ops + field containers)
- Added createDoc to erp.js API layer
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract data loading into loadCustomer() function and watch props.id
for changes. Previously only ran in onMounted — navigating between
clients showed stale data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move ERPNext API token from JS bundle to nginx proxy_set_header
(token only lives on server, never in client code)
- Switch ops + field apps from auth.targo.ca to id.gigafibre.ca SSO
- Fix "Aucun contenu" showing on tickets that have comments but no
description (check comments.length in v-if condition)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ops app (Vue/Quasar PWA) with dispatch V2 integration, tag system,
customer 360, tickets, and dashboard. Served via standalone nginx
container at erp.gigafibre.ca/ops/ with Traefik StripPrefix + Authentik SSO.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 29,178 account_memo → Comment on Customer
- Timestamps converted from unix to datetime
- Author mapped from staff_id → User email
- Visible in Customer page comment section
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- 45 users created with Authentik SSO (no password)
- Roles assigned: System Manager, Support Team, Sales/Accounts
- Service accounts skipped (admin, tech, dev, inventaire, agent)
- Email = Authentik identity link
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Integrates www.gigafibre.ca (React/Vite) into the monorepo.
Full git history accessible via `git log -- apps/website/`.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Integrates the Dispatch PWA (Vue/Quasar) into the gigafibre-fsm monorepo.
Full git history accessible via `git log -- apps/dispatch/`.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Guide de référence et de transfert couvrant toute l'infra Gigafibre:
Traefik, Authentik SSO, ERPNext, Dispatch PWA, n8n, Mailjet, Twilio,
DNS Cloudflare, Docker compose, build/deploy, pièges connus.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Contact form POSTs to /rpc/contact → Mailjet email to support@targo.ca
- Lead capture (availability dialog) POSTs to /rpc/lead → Mailjet email
- API server handles both endpoints with proper HTML formatting
- No Supabase edge functions needed
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Import content from targo.ca/accessibilite/ and /politique-de-confidentialite/
- Styled with site design (Header, Footer, prose layout)
- Routes: /accessibilite, /politique-de-confidentialite
- Footer links now point to real pages instead of placeholders
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Contact form now POSTs to /rpc/contact (www-api → n8n webhook)
- Footer links: Mon compte → store.targo.ca, placeholder # → /support
- .env added to .gitignore (Supabase keys should not be committed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
React/Vite/shadcn-ui site for Gigafibre ISP.
Address qualification via PostgreSQL (5.2M AQ addresses, pg_trgm fuzzy search).
No Supabase dependency for address search.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Full feature matrix comparing 6 FSM platforms with Gigafibre.
Gaiia (YC, $13.2M) is the primary comparable — ISP-specific OSS/BSS.
Key insights:
- Gaiia charges per-subscriber; Gigafibre is self-hosted (free)
- Our dispatch UX already exceeds Gaiia's public features
- Biggest gaps: customer portal, online checkout, mobile tech app
- Quick wins: auto travel time, tech status updates, SMS notifications
Priority roadmap ordered by ROI for a 2-10 tech ISP operation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Data model inspired by Odoo OCA Field Service + Salesforce FS patterns.
Adapted for small ISP/telecom (Gigafibre) running ERPNext.
Doctypes: Service Location, Service Equipment, Service Subscription
+ child tables for equipment history, checklists, photos, materials
+ extended Dispatch Job with customer/location/equipment links
Docs: architecture overview, tech stack, auth flow, industry comparison, roadmap
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Token is no longer hardcoded in source — injected at build time.
Build with: VITE_ERP_TOKEN="key:secret" npx quasar build
Prevents accidental token invalidation and keeps secrets out of git.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Regenerated Admin API token (old one was invalidated by generate_keys)
- Traefik: separate routers for app (with Authentik) and /api/ (no auth)
- Nginx proxy: use container IP (cross-compose DNS doesn't resolve names)
- /outpost.goauthentik.io/ route for Authentik callbacks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- authFetch uses redirect:'manual' to detect 302 from Authentik
- If session expired (302/401/opaqueredirect), reload page to trigger
Traefik forwardAuth → Authentik re-login flow
- Logout redirects to Authentik invalidation flow
- App.vue calls checkSession on mount to populate user identity
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove login form from App.vue (Authentik handles auth at Traefik level)
- Simplify auth store: no more checkSession/generate_keys complexity
- All ERPNext API calls use a service token (reliable, no CORS issues)
- User identity provided by Authentik X-authentik-email header
- Logout redirects to Authentik end-session URL
- Removed: login(), generate_keys, cookie fallback, token localStorage
Infrastructure:
- Created Authentik Proxy Provider for dispatch.gigafibre.ca
- Added to embedded outpost
- Applied authentik@file middleware to dispatch Traefik router
- Also removed unused Gitea (git.gigafibre.ca) containers + volumes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- All elements (SVG ring + avatar + badge) inside a fixed-size
container (45x45px) with absolute positioning
- Avatar centered with calculated offset, ring fills container
- Mapbox marker anchor changed from 'bottom' to 'center'
- No more variable margins causing offset drift on zoom
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace faint linear bars with SVG ring around avatar:
- Outer arc (faded): planned load / 8h capacity, color-coded
green→yellow→orange→red based on load percentage
- Inner arc (solid green): jobs completed / total jobs
- Ring uses stroke-dasharray for clean arcs with round caps
- Tooltip: "Name — 2/5 jobs (3.0h / 7.0h)"
- Crew badge (purple "2") positioned on avatar corner
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Progress bar under each tech avatar showing daily load (0-8h)
Green (<4h) → Yellow (4-6h) → Orange (6-8h) → Red (8h+)
Includes both primary queue and assistant jobs
- Crew badge: purple circle with count (e.g. "2") when tech has
assistants on today's jobs — indicates grouped team
- Tooltip shows "Name — X.Xh / 8h"
- Marker now uses gpsCoords || coords for visibility check
(fixes techs with GPS but no static coords)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Technician GPS positions from Traccar were being fetched and stored
correctly every 30s but drawMapMarkers() was never triggered on
gpsCoords change, so markers stayed at their initial position.
Added a deep watcher on store.technicians[].gpsCoords in useMap.js
that calls drawMapMarkers() whenever any technician's GPS position
is updated by pollGps().
Also includes traccar.js API module and dispatch store GPS polling
(pollGps / startGpsPolling / stopGpsPolling).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
No Docker image rebuild needed. Builds PWA locally with npx quasar
then copies dist/pwa directly into the ERPNext frontend container.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These were accidentally deleted when removing ~576 lines of inline map code.
Caused ReferenceError preventing the app from loading data.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Removed src/components/shared/TagInput.vue (exact duplicate of src/components/TagInput.vue)
- Deleted feature/quasar-migration branch from local and remote
- Verified build + deploy: design intact
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Current state: custom CSS + vanilla Vue components
Architecture: modular with composables, provide/inject pattern
Ready for progressive migration to Quasar native components
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>