ERP Masterplan v1.0

Bossuyt Service Ecosysteem

Unified platform plan — Service App + Vanventory + OCR Demo → één geïntegreerd systeem

OpgesteldApril 2026
Looptijd40 weken (~10 maanden, 1 dag/week)
ArchitectuurHub & Spoke (Progressief)
ServerHetzner + Docker + Traefik

0 Samenvatting

4 fases om alle bestaande Bossuyt apps samen te brengen in één serviceplatform.

4
Fases
22
Weken totaal
3
Apps te integreren
1
Unified platform

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.

📚
Core API Cursus →
Stap-voor-stap: hoe bouw je de Core API? 7 lessen met echte code, Docker, Drizzle, Keycloak & NAV sync.

1 Architectuur

Gekozen aanpak: Progressive Integration / Hub & Spoke — bestaande apps blijven intact, Core API laag wordt er bovenop gebouwd.

Dynamics NAV
Klanten, materiaal, orders
🧠 Core API
Node.js / PostgreSQL
🔑 Keycloak
auth.fixassistant.com
📱 Service App
Techniekers / mobiel
📦 Vanventory
Stockbeheer
📄 OCR Demo
Werkbon scanning
🖥️ Admin Portal
Centrale beheer interface
Dynamics NAV · Klanten, materiaal
🧠 Core API · Node.js / PostgreSQL
🔑 Keycloak · auth.fixassistant.com
📱 Service
📦 Vanventory
📄 OCR
🖥️ Admin Portal

✅ 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.

Maand 1
Maand 2
Maand 3
Maand 4-5
W1
W2
W3
W4
W5
W6
W7
W8
W9
W10
W11
W12
W13
W14
W15
W16
W17
W18
W19
W20
W21
W22
📦 Fase 1: Foundation
Core API setup
Shared DB schema
Keycloak integratie
🔗 Fase 2: NAV Bridge
CSV export workflow
Import service + sync jobs
🖥️ Fase 3: Admin Portal
Technicien beheer
Sync logs + dashboard
🔌 Fase 4: App Koppeling
Service App → Core API
Vanventory → Core API
OCR → Core API

Faseplanning — 40 weken

Fase 1 · Foundation & Core API W1–W8 (8w)
Fase 2 · NAV Bridge W9–W14 (6w)
Fase 3 · Admin Portal W15–W22 (8w)
Fase 4 · App Modularisatie W23–W40 (18w)

1 dag/week · totaal ~40 werkdagen

3 Fase Details

Klik op een fase om de taken uit te klappen.

1

Foundation & Infrastructure

Weken 1–8 · Core API + Shared DB + Keycloak
Weken 1–8

Setup van de centrale laag waarop alle andere fases bouwen. De bestaande apps blijven onaangeroerd.

🐳
Core API project opzetten
Node.js + TypeScript + Express/Fastify, Docker container, Traefik routing op api.bossuyt.fixassistant.com
W1–W2
🗄️
Shared PostgreSQL schema
Tabellen: technicians, customers, equipment, work_orders, sync_log. Separate schema's per app als naamruimte.
W2–W3
🔑
Keycloak JWT middleware
Core API valideert tokens van bestaand Keycloak op auth.fixassistant.com. Rollen: admin, technician, dispatcher.
W3–W5
Health check + basis endpoints
GET /health, GET /api/v1/technicians, GET /api/v1/customers — readonly, hardcoded testdata
W4–W5
🚀
CI/CD pipeline
GitHub Actions of lokale deploy script: build → test → docker push → traefik reload
W5
Deliverable: Core API draait op server, Keycloak auth werkt, DB schema aangemaakt, basis endpoints beschikbaar.
2

Dynamics NAV Data Bridge

Weken 9–14 · Master data vanuit NAV importeren
Weken 9–14

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.

📤
NAV CSV export formaat definiëren
Met Bossuyt afstemmen welke velden geëxporteerd worden: klanten, apparatuur, open orders. NAV rapport of manuele export.
W6
⚙️
Import service bouwen
Node.js script: CSV inlezen → validatie → upsert in shared DB. Idempotent (meerdere runs = zelfde resultaat).
W6–W7
🔄
Sync scheduler
Cron job (bijv. dagelijks 06:00) of webhook trigger. Sync log bijhouden in DB met timestamp, #records, errors.
W7–W8
Data validatie + conflict handling
Wat als klant in NAV verwijderd wordt? Soft delete strategie. Duplicate detectie op klantnummer.
W8–W9
Deliverable: NAV data (klanten, apparatuur) beschikbaar via Core API endpoints. Sync log zichtbaar.
3

Unified Admin Portal

Weken 15–22 · Centraal beheerpaneel
Weken 15–22

React/Vite frontend als centraal beheerpaneel. Inloggen via Keycloak. Beheer van techniekers, sync status en gebruikersrechten.

⚛️
Admin Portal scaffolding
React + Vite + TypeScript. Auth via Keycloak PKCE flow. Routing: /dashboard, /technicians, /sync, /settings.
W10–W11
👤
Technicien beheer module
Overzicht alle techniekers, Keycloak rol toewijzing, actief/inactief zetten. Koppeling met NAV technician data.
W11–W12
📊
Sync dashboard
Overzicht laatste NAV syncs: datum, #records, errors. Manuele sync knop. Alert bij sync failure.
W12–W13
🔒
Rechten & audit log
Wie heeft wat gedaan? Audit trail voor admin acties. Role-based zichtbaarheid van menu items.
W13–W14
Deliverable: Admin portal live op admin.bossuyt.fixassistant.com. Technicien beheer + sync monitoring werkt.
4

App Modularisatie

Weken 23–40 · Service App + Vanventory + OCR koppelen
Weken 23–40

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.

📱
Service App → Core API (PWA)
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.
W23–W27
📋
Intelligent planningssysteem
Planning vs Open: dispatcher wijst planning-items toe (met deadline), open-pool is optioneel voor techniekers. Technieker kan item uit planning halen mét reden: lukt niet meer / materiaal ontbreekt / onmogelijke timing voor klant / andere. Drag & drop om open-items in de dag te schuiven. Collega-view: dispatcher kan aan/uit zetten of technieker planning van collega's ziet.
W26–W29
🗺️
Routing service — rijtijden (Fase 1: ORS)
Backend endpoint /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.
W28–W30
📦
Vanventory → Core API
Stockbewegingen synchroniseren naar shared DB. Materiaal op werkbon koppelen aan Vanventory stock items.
W17–W19
📄
OCR Demo → Core API
Gescande werkbonnen opslaan in Core API als work_order records. LLM-geparsde velden direct in DB. Koppelen aan klant via NAV klantnummer.
W19–W22
End-to-end test + acceptatie
Technician scant werkbon → OCR → Core API → zichtbaar in Admin Portal. Vanventory stock bijgewerkt. NAV sync werkt na update.
W21–W22
Deliverable: Alle 3 apps praten met Core API. Volledig end-to-end werkbon workflow operationeel.
5

Server Migratie — Hetzner → Bossuyt

Na Week 40 · Volledige infrastructuur verhuizen naar Bossuyt-eigen server
Post W40

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.

📦
Inventarisatie & voorbereiding
Alle Docker images documenteren (docker images), volumes in kaart brengen (docker volume ls), environment variables verzamelen (.env bestanden), Traefik config kopiëren, SSL certificaten inventariseren.
🗄️
Database backup & restore plan
PostgreSQL dump van alle databases: 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.
🐳
Nieuwe server opbouwen
Docker + Docker Compose installeren. Traefik opzetten met Let's Encrypt. Alle docker-compose.yml bestanden overbrengen. Images bouwen of ophalen van registry. Netwerken aanmaken (docker network create traefik).
DNS switch & validatie
DNS records wijzigen van Hetzner IP naar Bossuyt server IP. TTL vooraf verlagen naar 5 min. Na switch: alle subdomains testen, SSL certificaten controleren, Keycloak auth end-to-end testen, NAV sync draaien.
🔄
Rollback plan
Hetzner server 2 weken online houden na migratie. Als er problemen zijn: DNS terugdraaien (max 5 min downtime door lage TTL). Monitoring instellen voor alle services.
Deliverable: Volledig platform draait op Bossuyt-eigen server. Hetzner server kan worden afgesloten. Alle data intact, geen downtime voor eindgebruikers.

4 Tech Stack

Wat blijft, wat is nieuw, wat is al aanwezig.

✅ Behouden

React + Vite (apps) Keycloak Docker + Traefik PostgreSQL Python/Flask (OCR) Google Vision API Claude Haiku (LLM)

🆕 Nieuw toe te voegen

Node.js/TypeScript (Core API) Fastify of Express Drizzle ORM CSV import service Cron scheduler Audit log middleware IndexedDB + Service Worker (PWA) OpenRouteService (ORS) — rijtijden fase 1 TomTom Traffic API — fase 2 swap React Admin Portal

🏗️ 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

Progressive integration is de juiste keuze
Alles tegelijk herschrijven zou eindeloos duren en wat nu werkt kapotmaken. Hub & Spoke geeft je de tijd om stap voor stap te migreren zonder downtime.
Keycloak hergebruiken is slim
Al geconfigureerd op auth.fixassistant.com en battle-tested. Nieuwe auth laag bouwen zou weken kosten voor nul meerwaarde.
OCR is al klaar — gratis quick win in Fase 4
41/41 tests groen, LLM post-processing geïmplementeerd. Koppelen aan Core API is het enige dat rest.
22 weken is realistisch (voor één deeltijdse developer)
Fases zijn goed gedimensioneerd. Niet te ambitieus, niet te conservatief.

⚠️ Aandachtspunten & Suggesties

🔴
NAV is de grootste onbekende — valideer dit EERST
Heel Fase 2 staat of valt met wat Bossuyt effectief kan exporteren. Als NAV oud of zwaar gecustomiseerd is, kan een bruikbare CSV export weken kosten. Aanbeveling: vraag nu al een echte CSV export op en valideer of je die kunt parsen — vóór je ook maar één regel code schrijft.
🟢
Offline-first: opgelost via slimme PWA strategie
Technician laadt bij start van de dag enkel zijn ~5 opdrachten voor die dag. Klantdetails en toestelinfo worden ad-hoc geladen en gecached (IndexedDB). Wagenstock (~1000 lijnen) wordt geladen wanneer verbinding beschikbaar is — dit kan je van de technieker verwachten. Toestelwijzigingen ook enkel online. Dit is een standaard PWA + Service Worker implementatie — geen complexe sync engine nodig.
🟢
Solo project (jij + Claude) — onderhoud is duidelijk
Geen onduidelijkheid over wie het systeem beheert. Wel rekening houden met: goede Docker setup zodat alles herstart bij serverfout, duidelijke env vars, en basis monitoring. Timeline aangepast naar 30 weken voor realistisch solo dev tempo.
🟡
Fase 4 heeft 3 parallelle integraties — te riskant
Service App + Vanventory + OCR lopen deels gelijktijdig. Als één blokkeert, slip je de hele fase. Beter strikt sequentieel: Service App volledig af → dan Vanventory → dan OCR.
💡 Concrete eerste stap:

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)

📱
PWA setup
Service worker, manifest, install prompt, offline fallback pagina
🔑
Keycloak login
PKCE flow, token opslag, protected routes
💾
IndexedDB offline layer
Cache schema voor opdrachten, klanten, toestellen + sync status
📋
Day view
Overzicht opdrachten van vandaag (mock data, max 5)
📝
Werkbon form
Al gestart — afwerken + validatie + opslaan offline
✍️
Handtekening + PDF
Al gebouwd — integreren in werkbon flow
🔔
Push notificaties
Al gestart — afwerken voor nieuwe opdracht alerts
🧱
Core API scaffold
Node.js + TypeScript, auth middleware, DB schema, basis endpoints

⏳ Wacht op NAV CSV

👥
Echte klanten
Naam, adres, contactpersoon — komt uit NAV
🔧
Echte toestellen
Merk, type, serienummer, locatie — komt uit NAV
📅
Echte opdrachten
Werkordernummer, type interventie, geplande datum
🔄
NAV sync service
CSV import, upsert logica, conflict handling, cron job
Slimme aanpak:

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.

Bossuyt ERP Masterplan · Gebaseerd op Gemini brainstorm sessie · Claude + OMC  ·  v1.5