0 Samenvatting
4 fases om alle bestaande Bossuyt apps samen te brengen in één serviceplatform.
Doel
De huidige apps — bossuyt_service_next (techniekers), vanventory-app (stockbeheer) en ocr-demo (werkbon scanning) — worden verbonden via een centrale Core API met gedeelde database en Keycloak authenticatie. Dynamics NAV blijft de master voor klant- en materiaaldata.
1 Architectuur
Gekozen aanpak: Progressive Integration / Hub & Spoke — bestaande apps blijven intact, Core API laag wordt er bovenop gebouwd.
Klanten, materiaal, orders
Node.js / PostgreSQL
auth.fixassistant.com
Techniekers / mobiel
Stockbeheer
Werkbon scanning
Centrale beheer interface
✅ Waarom Hub & Spoke
- Bestaande apps blijven werken tijdens de migratie
- Elke app kan onafhankelijk worden aangepast
- Core API groeit incrementeel mee
- Minder risico dan een volledige rewrite
⚠️ Aandachtspunten
- NAV heeft geen REST API → CSV export workflow nodig
- Keycloak al geconfigureerd → reuse, niet herbouwen
- Data consistentie tussen apps via shared DB
- Offline-first voor techniekers blijft prioriteit
2 Tijdlijn — 40 Weken (1 dag/week)
Visueel overzicht van alle fases. Elke week = 1 werkdag. Aanpassingen zijn ingecalculeerd.
Faseplanning — 40 weken
1 dag/week · totaal ~40 werkdagen
3 Fase Details
Klik op een fase om de taken uit te klappen.
Foundation & Infrastructure
Setup van de centrale laag waarop alle andere fases bouwen. De bestaande apps blijven onaangeroerd.
api.bossuyt.fixassistant.comtechnicians, customers, equipment, work_orders, sync_log. Separate schema's per app als naamruimte.admin, technician, dispatcher.GET /health, GET /api/v1/technicians, GET /api/v1/customers — readonly, hardcoded testdataDynamics NAV Data Bridge
NAV heeft geen REST API. Aanpak: periodieke CSV export uit NAV → import service in Core API → shared DB. Synchronisatie kan manueel starten of via cron job.
Unified Admin Portal
React/Vite frontend als centraal beheerpaneel. Inloggen via Keycloak. Beheer van techniekers, sync status en gebruikersrechten.
/dashboard, /technicians, /sync, /settings.admin.bossuyt.fixassistant.com. Technicien beheer + sync monitoring werkt.
App Modularisatie
Elke bestaande app wordt aangepast om data van de Core API te gebruiken i.p.v. eigen hardcoded data. Apps blijven zelfstandig werken als fallback.
bossuyt_service_next als PWA. Bij dagstart 10 werkbonnen gecached in IndexedDB — opgesplitst in planning (vaste jobs met "uit te voeren voor" datum) en open (pool van kleine jobs die technieker zelf inplant). Klant/toesteldata ad-hoc geladen. Wagenstock (~1000 lijnen) enkel bij verbinding. Service Worker voor offline fallback. Keycloak login via PKCE./api/v1/route met provider-agnostische abstractie (routingService.getETA(from, to)). Fase 1: OpenRouteService (gratis, account.heigit.org). Fase 2: swap naar TomTom traffic-aware zonder app te wijzigen. UI toont ~35 min met disclaimer "zonder file-rekening". Rijtijden worden gecached bij dagstart. Bij drag & drop automatisch herberekend.
work_order records. LLM-geparsde velden direct in DB. Koppelen aan klant via NAV klantnummer.Server Migratie — Hetzner → Bossuyt
Wanneer het platform stabiel draait op Hetzner, verhuist alles naar een Bossuyt-eigen server. Dit is een kritisch moment — fouten hier betekenen downtime. Grondige voorbereiding en een rollback-plan zijn essentieel.
docker images), volumes in kaart brengen (docker volume ls), environment variables verzamelen (.env bestanden), Traefik config kopiëren, SSL certificaten inventariseren.pg_dump -Fc bossuyt > bossuyt.dump. Testen van restore op nieuwe server vóór migratie. Keycloak realm export (JSON). Aanpak: maintenance mode aan → dump → overbrengen → restore → testen → DNS switch.docker network create traefik).4 Tech Stack
Wat blijft, wat is nieuw, wat is al aanwezig.
✅ Behouden
🆕 Nieuw toe te voegen
🏗️ Infrastructure domeinen (voorstel)
api.bossuyt.fixassistant.com
admin.bossuyt.fixassistant.com
service.bossuyt.fixassistant.com
auth.fixassistant.com (bestaand)
5 Risico's & Mitigatie
Gekende risico's geïdentificeerd vanuit de brainstorm.
🔴 NAV heeft geen REST API
CSV export is manueel of vereist rapport customisatie in NAV. Mitigatie: vroeg afstemmen met Bossuyt welk formaat haalbaar is, ook ODBC/OData als alternatief verkennen.
🔴 Offline-first voor techniekers
Service app moet werken zonder internet (op klantlocatie). Mitigatie: lokale opslag + sync bij reconnect. Fase 4 prioriteit.
🟡 Keycloak rol-migratie
Bestaande gebruikers moeten de juiste rollen krijgen. Mitigatie: admin approval flow al gebouwd in family-ai-hub — hergebruiken.
🟡 Data duplicatie tussen apps
Klantdata staat nu verspreid. Mitigatie: Core API als enige bron van waarheid, apps lezen altijd uit Core API.
🟢 OCR fouten op moeilijke werkbonnen
LLM post-processing is al geïmplementeerd en getest (41/41 tests). Risico is laag.
6 Plan Analyse — Sterktes & Risico's
Kritische beoordeling van het plan door Claude + OMC.
✅ Wat goed is
⚠️ Aandachtspunten & Suggesties
Stuur Bossuyt een e-mail deze week en vraag een testexport uit NAV: klanten + apparatuur als CSV. Dat valideer je in een paar uur. Als het lukt → Fase 2 wordt een stuk eenvoudiger. Als het niet lukt → weet je vroeg genoeg dat je een andere strategie nodig hebt (ODBC, OData, of manueel).
7 Waar starten — zonder NAV data
Je hebt de NAV CSV nog niet. Toch kan je al heel veel bouwen. Alles werkt op mock data die de echte NAV structuur spiegelt — bij de echte CSV wissel je enkel de bron.
✅ Nu bouwen (mock data)
⏳ Wacht op NAV CSV
Definieer je data model nu op basis van een echte werkbon van Bossuyt. Mock alles op basis van die structuur. Als de CSV aankomt wissel je enkel de bron — de app verandert niet.
🎯 Eerste werkdag — concrete taak
Bekijk een echte Bossuyt werkbon (papier of PDF) en definieer de TypeScript types in types/index.ts:
type WorkOrder = {
id: string
navOrderNr: string // NAV werkopdrachtnummer
customer: Customer
equipment: Equipment
interventionType: string // ketel onderhoud / airco / warmtepomp...
plannedDate: string // ISO date
technicianId: string
status: 'open' | 'in_progress' | 'completed'
syncedAt?: string // laatste sync met Core API
}
type Customer = {
id: string
navId: string // NAV klantnummer
name: string
address: string
contact?: string
phone?: string
}
type Equipment = {
id: string
navId: string
brand: string
model: string
serialNumber: string
location: string // waar staat het toestel in het gebouw
lastServiceDate?: string
}
Pas aan op basis van wat je op een echte Bossuyt werkbon ziet. Dat is je fundament voor alles.