Replace demo data with 2026 R&D planning, fix zoom and dimension-aware creation

Seeder: Replace 12 demo projects with 6 real 2026 projects from Planning PPTX:
- BRIDGE (Pilot Klundert), CRISP (Compressor Aanbesteding), WISE (Monsternamekast),
  Gemaal 3.0, Afvlakkingsregeling, Structuur & Borging
- 4 strategic themes: Architectuur, Productiewaardig, Lab, Governance
- Real team members, commitments, documents, and dependencies

MetroCanvas: Fix zoom-out scaling
- Wider transition range (0.6→0.25 instead of 0.5→0.1) for smoother feel
- Animated zoom reset on dimension commit (400ms ease) instead of jarring snap
- Guard against re-entry during transitions with isCommitting flag
- Expose dimension metadata (parentEntityType/Id/Name) for parent components

FloatingActions: Dimension-aware creation
- Shows "Nieuw commitment/document" when inside a project dimension
- Shows "Nieuw project/thema" at root level
- Receives depth and parentEntityType props from MetroMap

MetroMap: Wire dimension tracking
- Tracks canvasDepth/canvasDimension from MetroCanvas dimension-change events
- Updates breadcrumb for both page-level and canvas-level navigation
- Passes dimension context to FloatingActions and CommitmentForm

MapDataService: Add parent metadata to buildProjectChildren output

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
znetsixe
2026-04-08 08:50:51 +02:00
parent 926872a082
commit 6711cd01a3
6 changed files with 531 additions and 415 deletions

View File

@@ -25,6 +25,9 @@ class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* Planning 2026 R&D Lab Waterschap Brabantse Delta
* Source: Planning 2026.pptx
*/
public function run(): void
{
@@ -56,483 +59,442 @@ class DatabaseSeeder extends Seeder
]);
// ──────────────────────────────────────────────────────────────
// 2. Users
// 2. Users (R&D team)
// ──────────────────────────────────────────────────────────────
$adminUser = User::create([
'name' => 'Admin Gebruiker',
$admin = User::create([
'name' => 'Admin',
'email' => 'admin@innovatieplatform.nl',
'password' => Hash::make('password'),
'functie' => 'Platform Beheerder',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$adminUser->roles()->attach($roleAdmin);
$admin->roles()->attach($roleAdmin);
$testUser = User::create([
$rene = User::create([
'name' => 'Rene de Ren',
'email' => 'rene@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'R&D Engineer',
'functie' => 'R&D Engineer / Teamlead',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$testUser->roles()->attach($roleProjectOwner);
$rene->roles()->attach($roleProjectOwner);
$analyst = User::create([
'name' => 'Lisanne Bakker',
'email' => 'l.bakker@wbd-rd.nl',
$pim = User::create([
'name' => 'Pim Moerman',
'email' => 'p.moerman@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'Data Analist',
'afdeling' => 'Watermanagement',
'functie' => 'Technisch Adviseur OT/IT',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$analyst->roles()->attach($roleTeamMember);
$pim->roles()->attach($roleTeamMember);
$engineer = User::create([
'name' => 'Joris van Dam',
'email' => 'j.vandam@wbd-rd.nl',
$sjoerd = User::create([
'name' => 'Sjoerd Fijnje',
'email' => 's.fijnje@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'Senior Technisch Adviseur',
'afdeling' => 'Infrastructuur',
'functie' => 'Werktuigbouwkundige / Elektro',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$engineer->roles()->attach($roleTeamMember);
$sjoerd->roles()->attach($roleTeamMember);
// ──────────────────────────────────────────────────────────────
// 3. Themas (4 strategic themes)
// 3. Themas 2026 strategic themes
//
// Kaders: geen nieuwe ML-modellen, geen nieuwe digital twins,
// focus op werkend krijgen, architectuur aantonen, overdragen.
// ──────────────────────────────────────────────────────────────
$themaWater = Thema::create([
'naam' => 'Waterkwaliteit',
'beschrijving' => 'Verbetering van de kwaliteit van oppervlaktewater en grondwater door innovatieve monitoring- en zuiveringstechnieken.',
$themaArchitectuur = Thema::create([
'naam' => 'Architectuur & Veiligheid',
'beschrijving' => 'Aantonen dat de EDGE-laag architectuur veilig, betrouwbaar en schaalbaar is. OT/IT-scheiding, Siemens-koppeling, CI/CD implementatie.',
'prioriteit' => Prioriteit::Hoog,
'periode_start' => '2025-01-01',
'periode_eind' => '2028-12-31',
'periode_start' => '2026-01-01',
'periode_eind' => '2026-12-31',
]);
$themaInfra = Thema::create([
'naam' => 'Slimme Infrastructuur',
'beschrijving' => 'Digitalisering en automatisering van waterkeringen, gemalen en sluizen voor efficiënter beheer en snellere responstijden.',
$themaProductie = Thema::create([
'naam' => 'Productiewaardig Maken',
'beschrijving' => 'Bestaande innovaties werkend, overdraagbaar en schaalbaar maken. Begeleiding van aanbestedingen en overdracht naar Bouwen/Beheer.',
'prioriteit' => Prioriteit::Hoog,
'periode_start' => '2025-01-01',
'periode_eind' => '2028-12-31',
'periode_start' => '2026-01-01',
'periode_eind' => '2026-12-31',
]);
$themaData = Thema::create([
'naam' => 'Data-gedreven Beheer',
'beschrijving' => 'Inzet van data-analyse, AI en digitale tweelingen voor betere besluitvorming in waterbeheer.',
$themaLab = Thema::create([
'naam' => 'Lab & Prototyping',
'beschrijving' => 'Fysieke opstellingen valideren, uitbreiden en koppelen tot een realistische testomgeving voor afvlakkingsregelingen.',
'prioriteit' => Prioriteit::Midden,
'periode_start' => '2025-06-01',
'periode_eind' => '2029-06-30',
'periode_start' => '2026-01-01',
'periode_eind' => '2026-12-31',
]);
$themaDuurzaam = Thema::create([
'naam' => 'Duurzaamheid & Klimaatadaptatie',
'beschrijving' => 'Innovaties gericht op energieneutraliteit, circulaire waterketens en klimaatrobuuste inrichting van het beheergebied.',
$themaGovernance = Thema::create([
'naam' => 'Governance & Teamborging',
'beschrijving' => 'R&D minder persoonsafhankelijk maken. Projectstructuur, documentatie, besluitvorming en rolafbakening vastleggen.',
'prioriteit' => Prioriteit::Midden,
'periode_start' => '2025-01-01',
'periode_eind' => '2030-12-31',
'periode_start' => '2026-01-01',
'periode_eind' => '2026-12-31',
]);
// ──────────────────────────────────────────────────────────────
// 4. Speerpunten (2 per thema)
// ──────────────────────────────────────────────────────────────
// Waterkwaliteit
$spWaterMonitoring = Speerpunt::create([
'thema_id' => $themaWater->id,
'naam' => 'Real-time Watermonitoring',
'beschrijving' => 'Continue meting van waterkwaliteitsparameters via IoT-sensoren in het beheergebied.',
'eigenaar_id' => $testUser->id,
// Architectuur & Veiligheid
$spEdge = Speerpunt::create([
'thema_id' => $themaArchitectuur->id,
'naam' => 'EDGE-laag & OT/IT-scheiding',
'beschrijving' => 'Implementatie en validatie van de EDGE-architectuur met beveiligde OT/IT-scheiding op pilotlocatie.',
'eigenaar_id' => $rene->id,
'status' => SpeerpuntStatus::Actief,
]);
$spMicropollution = Speerpunt::create([
'thema_id' => $themaWater->id,
'naam' => 'Microverontreinigingen',
'beschrijving' => 'Detectie en verwijdering van opkomende stoffen zoals medicijnresten en PFAS.',
'eigenaar_id' => $engineer->id,
$spCicd = Speerpunt::create([
'thema_id' => $themaArchitectuur->id,
'naam' => 'CI/CD & DevOps R&D-stack',
'beschrijving' => 'Continuous Integration en Deployment implementeren in de R&D-stack voor maximale efficiëntie en herhaalbaarheid.',
'eigenaar_id' => $rene->id,
'status' => SpeerpuntStatus::Concept,
]);
// Slimme Infrastructuur
$spDigitaalBeheer = Speerpunt::create([
'thema_id' => $themaInfra->id,
'naam' => 'Digitaal Kunstwerkenregister',
'beschrijving' => 'Volledig digitaal beheer van kunstwerken met BIM-koppeling en conditiebewaking.',
'eigenaar_id' => $engineer->id,
// Productiewaardig Maken
$spOverdracht = Speerpunt::create([
'thema_id' => $themaProductie->id,
'naam' => 'Overdracht naar Bouwen/Beheer',
'beschrijving' => 'Innovaties begeleiden van R&D naar productie: documentatie, oplevering, kennisoverdracht.',
'eigenaar_id' => $rene->id,
'status' => SpeerpuntStatus::Actief,
]);
$spSmartGemaal = Speerpunt::create([
'thema_id' => $themaInfra->id,
'naam' => 'Slimme Gemaalbesturing',
'beschrijving' => 'Predictieve sturing van gemalen op basis van weersvoorspelling en waterstanden.',
'eigenaar_id' => $testUser->id,
$spAanbesteding = Speerpunt::create([
'thema_id' => $themaProductie->id,
'naam' => 'Aanbesteding & TCO-toetsing',
'beschrijving' => 'Technische toetsing van aanbestedingen op prestatie-eisen, energie-efficiëntie en inpasbaarheid.',
'eigenaar_id' => $pim->id,
'status' => SpeerpuntStatus::Actief,
]);
// Data-gedreven Beheer
$spDigitaalTwin = Speerpunt::create([
'thema_id' => $themaData->id,
'naam' => 'Digitale Tweeling Watersysteem',
'beschrijving' => 'Virtueel model van het watersysteem voor scenario-analyse en operationele ondersteuning.',
'eigenaar_id' => $analyst->id,
// Lab & Prototyping
$spDtValidatie = Speerpunt::create([
'thema_id' => $themaLab->id,
'naam' => 'Digital Twin Validatie',
'beschrijving' => 'Valideren van 2025-ontwikkelingen (Measurement, Rotating Machine, Aeration Tank, MGC, Diffuser) op het fysieke prototype.',
'eigenaar_id' => $rene->id,
'status' => SpeerpuntStatus::Actief,
]);
$spGemalenketen = Speerpunt::create([
'thema_id' => $themaLab->id,
'naam' => 'Gemalenketen Testomgeving',
'beschrijving' => 'Realiseren van een volledige gemalenketen in het lab voor experimentele afvlakkingsregelingen.',
'eigenaar_id' => $sjoerd->id,
'status' => SpeerpuntStatus::Concept,
]);
$spAIVoorspelling = Speerpunt::create([
'thema_id' => $themaData->id,
'naam' => 'AI-gestuurde Waterstandsvoorspelling',
'beschrijving' => 'Machine learning modellen voor nauwkeurige korte- en middellangetermijnwaterstanden.',
'eigenaar_id' => $analyst->id,
// Governance & Teamborging
$spProjectstructuur = Speerpunt::create([
'thema_id' => $themaGovernance->id,
'naam' => 'Projectstructuur & Documentatie',
'beschrijving' => 'Afspraken vastleggen over projectstructuur, documentatie, besluitvorming en beleid.',
'eigenaar_id' => $rene->id,
'status' => SpeerpuntStatus::Actief,
]);
// Duurzaamheid
$spEnergieneutraal = Speerpunt::create([
'thema_id' => $themaDuurzaam->id,
'naam' => 'Energieneutrale Zuivering',
'beschrijving' => 'Zelfvoorzienende rwzi\'s door terugwinning van energie uit afvalwater.',
'eigenaar_id' => $engineer->id,
'status' => SpeerpuntStatus::Actief,
]);
$spCirculaireWater = Speerpunt::create([
'thema_id' => $themaDuurzaam->id,
'naam' => 'Circulaire Waterketen',
'beschrijving' => 'Terugwinning van grondstoffen (fosfaat, cellulose, warmte) uit afvalwater.',
'eigenaar_id' => $testUser->id,
$spRolafbakening = Speerpunt::create([
'thema_id' => $themaGovernance->id,
'naam' => 'Rolafbakening R&D ↔ Organisatie',
'beschrijving' => 'Verduidelijken wat R&D wel en niet doet. Afbakening richting Beheer, Bouwen, ICT en Datalab.',
'eigenaar_id' => $rene->id,
'status' => SpeerpuntStatus::Concept,
]);
// ──────────────────────────────────────────────────────────────
// 5. Projects (1012 spread across themes and lifecycle phases)
// 5. Projects 2026 planning (6 projects from the presentation)
// ──────────────────────────────────────────────────────────────
$projects = [];
// --- Waterkwaliteit projects ---
$p1 = $this->createProject([
'speerpunt_id' => $spWaterMonitoring->id,
'naam' => 'LoRaWAN Sensornetwerk Biesbosch',
'beschrijving' => 'Uitrol van een draadloos sensornetwerk in het Biesbosch-gebied voor real-time meting van waterkwaliteitsparameters (pH, DO, troebelheid, geleidbaarheid).',
'eigenaar_id' => $testUser->id,
// --- B.R.I.D.G.E (Bidirectional Real-time Interface for Data & Grid Exchange) ---
$bridge = $this->createProject([
'speerpunt_id' => $spEdge->id,
'naam' => 'B.R.I.D.G.E Pilot Klundert',
'beschrijving' => 'Aantonen dat de nieuwe EDGE-laag veilig en betrouwbaar assets kan uitlezen en aansturen, en correct kan koppelen met Siemens-omgevingen. Implementatie Ubuntu LTS, Node-RED orkestratie, OPC UA communicatie met Siemens PLC (T-serie).',
'eigenaar_id' => $rene->id,
'status' => ProjectStatus::Pilot,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-03-01',
'streef_einddatum' => '2025-12-31',
'startdatum' => '2026-01-15',
'streef_einddatum' => '2026-09-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot]);
$p2 = $this->createProject([
'speerpunt_id' => $spWaterMonitoring->id,
'naam' => 'Drone-inspectie Waterbodem',
'beschrijving' => 'Onderzoek naar de inzet van autonome onderwaterdrones voor sedimentkartering en vervuilingdetectie in kanalen en sloten.',
'eigenaar_id' => $engineer->id,
'status' => ProjectStatus::Experiment,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2025-06-01',
'streef_einddatum' => '2026-06-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment]);
$p3 = $this->createProject([
'speerpunt_id' => $spMicropollution->id,
'naam' => 'PFAS Detectiemethode Ontwikkeling',
'beschrijving' => 'Ontwikkeling van een snelle en goedkope veldmethode voor PFAS-detectie in oppervlaktewater, als alternatief voor kostbare laboratoriumanalyse.',
'eigenaar_id' => $analyst->id,
// --- C.R.I.S.P (Compressor Replacement for Immediate System Performance) ---
$crisp = $this->createProject([
'speerpunt_id' => $spAanbesteding->id,
'naam' => 'C.R.I.S.P Compressor Aanbesteding',
'beschrijving' => 'Technische toetsing van aanbestedingsmethodiek voor compressorvervanging Nieuwveer. Prestatie-eisen, energie-efficiëntie, inpasbaarheid in procesautomatisering. R&D als inhoudelijke sparringpartner voor Bouwen.',
'eigenaar_id' => $pim->id,
'status' => ProjectStatus::Verkenning,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-09-01',
'streef_einddatum' => '2026-09-30',
'startdatum' => '2026-02-01',
'streef_einddatum' => '2026-08-31',
], [FaseType::Signaal, FaseType::Verkenning]);
// --- Slimme Infrastructuur projects ---
$p4 = $this->createProject([
'speerpunt_id' => $spDigitaalBeheer->id,
'naam' => 'BIM-model Gemaal De Donge',
'beschrijving' => 'Digitale driedimensionale representatie van gemaal De Donge inclusief alle technische installaties, leidingen en elektrotechnische componenten.',
'eigenaar_id' => $engineer->id,
// --- W.I.S.E (Weather and Influent Sampling Engine) ---
$wise = $this->createProject([
'speerpunt_id' => $spOverdracht->id,
'naam' => 'W.I.S.E Monsternamekast Overdracht',
'beschrijving' => 'Overdracht monsternamekast naar Bouwen. Opleveren Node-RED flows, documentatie, afbakening R&D vs beheer. Samenwerking met Datalab (data & integratie voorspellend model) en Beheer/Operatie.',
'eigenaar_id' => $rene->id,
'status' => ProjectStatus::OverdrachtBouwen,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2024-09-01',
'streef_einddatum' => '2025-06-30',
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-06-01',
'streef_einddatum' => '2026-06-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot, FaseType::Besluitvorming, FaseType::OverdrachtBouwen]);
$p5 = $this->createProject([
'speerpunt_id' => $spSmartGemaal->id,
'naam' => 'Predictieve Gemaalbesturing Mark-Vliet',
'beschrijving' => 'Implementatie van een ML-algoritme dat op basis van KNMI-weerdata en historische afvoerpatronen de optimale pompsturing berekent voor het Mark-Vliet systeem.',
'eigenaar_id' => $testUser->id,
'status' => ProjectStatus::Besluitvorming,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-01-01',
'streef_einddatum' => '2025-12-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot, FaseType::Besluitvorming]);
// --- Gemaal 3.0 Prototype Validatie ---
$gemaal = $this->createProject([
'speerpunt_id' => $spDtValidatie->id,
'naam' => 'Gemaal 3.0 Prototype Validatie',
'beschrijving' => 'Valideren dat het recent gebouwde prototype functioneel correct is. Testen van alle elektrische aansluitingen, I/O-functionaliteit en randapparatuur. Go/no-go voor verdere uitrol naar 2 kopieën.',
'eigenaar_id' => $sjoerd->id,
'status' => ProjectStatus::Experiment,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2026-03-01',
'streef_einddatum' => '2026-07-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment]);
$p6 = $this->createProject([
'speerpunt_id' => $spSmartGemaal->id,
'naam' => 'Remote Monitoring Waterkeringen',
'beschrijving' => 'Continuemonitoring van primaire waterkeringen met IoT-sensoren voor zakking, piping-detectie en grondwaterstand.',
'eigenaar_id' => $engineer->id,
'status' => ProjectStatus::Signaal,
'prioriteit' => Prioriteit::Laag,
'startdatum' => '2026-01-01',
'streef_einddatum' => null,
], [FaseType::Signaal]);
// --- Data-gedreven Beheer projects ---
$p7 = $this->createProject([
'speerpunt_id' => $spDigitaalTwin->id,
'naam' => 'Digitale Tweeling Pilot Roosendaalse Vliet',
'beschrijving' => 'Eerste proof-of-concept van een digitale tweeling voor het deelgebied Roosendaalse Vliet, gekoppeld aan het SOBEK-hydraulisch model.',
'eigenaar_id' => $analyst->id,
// --- Afvlakkingsregeling Lab Gemalenketen ---
$afvlak = $this->createProject([
'speerpunt_id' => $spGemalenketen->id,
'naam' => 'Afvlakkingsregeling Lab Keten',
'beschrijving' => 'Nabootsen van een volledige gemalenketen in het lab, klaarstomen voor afvlakkingsregeling. Realiseren 2 extra opstellingen, koppelen tot keten, basissoftware testen op ketengedrag.',
'eigenaar_id' => $sjoerd->id,
'status' => ProjectStatus::Concept,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-07-01',
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2026-06-01',
'streef_einddatum' => '2026-12-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept]);
$p8 = $this->createProject([
'speerpunt_id' => $spAIVoorspelling->id,
'naam' => 'AI Waterstandsmodel Hollandsch Diep',
'beschrijving' => 'Training en validatie van een LSTM-neuraal netwerk voor 48-uurs waterstandsvoorspellingen op het Hollandsch Diep, ter vervanging van het huidige regressiemodel.',
'eigenaar_id' => $analyst->id,
'status' => ProjectStatus::Experiment,
'prioriteit' => Prioriteit::Hoog,
'startdatum' => '2025-04-01',
'streef_einddatum' => '2026-03-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment]);
$p9 = $this->createProject([
'speerpunt_id' => $spAIVoorspelling->id,
'naam' => 'Open Data Platform Waterschap',
'beschrijving' => 'Ontwikkeling van een publiekstoegankelijk data-portaal voor het ontsluiten van historische en actuele meetdata van het waterschap.',
'eigenaar_id' => $testUser->id,
'status' => ProjectStatus::Geparkeerd,
'prioriteit' => Prioriteit::Laag,
'startdatum' => '2024-06-01',
'streef_einddatum' => '2025-12-31',
], [FaseType::Signaal, FaseType::Verkenning]);
// --- Duurzaamheid projects ---
$p10 = $this->createProject([
'speerpunt_id' => $spEnergieneutraal->id,
'naam' => 'Biogasopwaardering RWZI Bath',
'beschrijving' => 'Opwaardering van slibvergistingsgas naar groengas-kwaliteit voor invoeding op het gasnet en verkoop aan een energiemaatschappij.',
'eigenaar_id' => $engineer->id,
'status' => ProjectStatus::Evaluatie,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2024-01-01',
'streef_einddatum' => '2025-06-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot, FaseType::Besluitvorming, FaseType::OverdrachtBouwen, FaseType::OverdrachtBeheer, FaseType::Evaluatie]);
$p11 = $this->createProject([
'speerpunt_id' => $spCirculaireWater->id,
'naam' => 'Fosfaatterugwinning Struviet',
'beschrijving' => 'Implementatie van struvietkristallisatie-technologie op RWZI Nieuw-Vossemeer voor de terugwinning van fosfaat als meststof.',
'eigenaar_id' => $testUser->id,
'status' => ProjectStatus::Pilot,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2025-02-01',
'streef_einddatum' => '2026-02-28',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot]);
$p12 = $this->createProject([
'speerpunt_id' => $spEnergieneutraal->id,
'naam' => 'Warmteterugwinning Afvalwater Centrum',
'beschrijving' => 'Pilotinstallatie voor warmtewisselaars op het rioolstelsel in Breda-centrum om warmte terug te winnen voor stadsverwarming.',
'eigenaar_id' => $engineer->id,
// --- Structuur & Borging R&D-team ---
$governance = $this->createProject([
'speerpunt_id' => $spProjectstructuur->id,
'naam' => 'Structuur & Borging R&D',
'beschrijving' => 'R&D minder persoonsafhankelijk en beter voorspelbaar maken. Afspraken over projectstructuur, documentatie, besluitvorming, beleid. Inrichten ICT in Bouvigne voor R&D en Datanetwerkteam.',
'eigenaar_id' => $rene->id,
'status' => ProjectStatus::Verkenning,
'prioriteit' => Prioriteit::Midden,
'startdatum' => '2025-10-01',
'streef_einddatum' => '2027-03-31',
'startdatum' => '2026-01-01',
'streef_einddatum' => '2026-12-31',
], [FaseType::Signaal, FaseType::Verkenning]);
$projects = [$p1, $p2, $p3, $p4, $p5, $p6, $p7, $p8, $p9, $p10, $p11, $p12];
// ──────────────────────────────────────────────────────────────
// 6. Assign team members
// ──────────────────────────────────────────────────────────────
$p1->teamleden()->attach($analyst->id, ['rol' => ProjectRol::Lid->value]);
$p2->teamleden()->attach($testUser->id, ['rol' => ProjectRol::Reviewer->value]);
$p5->teamleden()->attach($analyst->id, ['rol' => ProjectRol::Lid->value]);
$p5->teamleden()->attach($engineer->id, ['rol' => ProjectRol::Reviewer->value]);
$p8->teamleden()->attach($engineer->id, ['rol' => ProjectRol::Lid->value]);
$bridge->teamleden()->attach($pim->id, ['rol' => ProjectRol::Lid->value]);
$bridge->teamleden()->attach($sjoerd->id, ['rol' => ProjectRol::Lid->value]);
$crisp->teamleden()->attach($rene->id, ['rol' => ProjectRol::Reviewer->value]);
$wise->teamleden()->attach($pim->id, ['rol' => ProjectRol::Lid->value]);
$gemaal->teamleden()->attach($rene->id, ['rol' => ProjectRol::Reviewer->value]);
$afvlak->teamleden()->attach($rene->id, ['rol' => ProjectRol::Reviewer->value]);
$governance->teamleden()->attach($pim->id, ['rol' => ProjectRol::Lid->value]);
$governance->teamleden()->attach($sjoerd->id, ['rol' => ProjectRol::Lid->value]);
// ──────────────────────────────────────────────────────────────
// 7. Commitments
// ──────────────────────────────────────────────────────────────
// BRIDGE
Commitment::create([
'project_id' => $p1->id,
'beschrijving' => 'Installatie van 20 sensorknooppunten in het veld vóór einde Q3 2025',
'eigenaar_id' => $testUser->id,
'deadline' => '2025-09-30',
'project_id' => $bridge->id,
'beschrijving' => 'Architectuur validatiedocument opleveren conform stackKlundertPilot.pdf',
'eigenaar_id' => $rene->id,
'deadline' => '2026-04-30',
'status' => CommitmentStatus::InUitvoering,
'bron' => 'Stuurgroep Waterkwaliteit — 12 maart 2025',
'bron' => 'Planning 2026 slide 3',
]);
Commitment::create([
'project_id' => $p1->id,
'beschrijving' => 'Validatierapport sensornauwkeurigheid opleveren aan dataplatformteam',
'eigenaar_id' => $analyst->id,
'deadline' => '2025-11-30',
'project_id' => $bridge->id,
'beschrijving' => 'OT/IT beveiligingsassessment en scheidingsrapport',
'eigenaar_id' => $pim->id,
'deadline' => '2026-06-30',
'status' => CommitmentStatus::Open,
'bron' => 'Stuurgroep Waterkwaliteit — 12 maart 2025',
'bron' => 'Planning 2026 slide 3',
]);
Commitment::create([
'project_id' => $p5->id,
'beschrijving' => 'Afstemming met Rijkswaterstaat over databeschikbaarheid afvoermetingen',
'eigenaar_id' => $engineer->id,
'deadline' => '2025-07-31',
'status' => CommitmentStatus::Afgerond,
'bron' => 'Projectstartup 15 januari 2025',
]);
Commitment::create([
'project_id' => $p5->id,
'beschrijving' => 'Businesscase energiebesparing opstellen voor directie',
'eigenaar_id' => $testUser->id,
'deadline' => '2025-10-15',
'project_id' => $bridge->id,
'beschrijving' => 'Beslisdocument voor opschaling EDGE-laag naar andere locaties',
'eigenaar_id' => $rene->id,
'deadline' => '2026-09-30',
'status' => CommitmentStatus::Open,
'bron' => 'Besluitvormingsrapport fase 5',
'bron' => 'Planning 2026 slide 3',
]);
// CRISP
Commitment::create([
'project_id' => $crisp->id,
'beschrijving' => 'TCO-onderbouwde aanbestedingsdocumenten technisch getoetst vóór marktgang',
'eigenaar_id' => $pim->id,
'deadline' => '2026-05-31',
'status' => CommitmentStatus::Open,
'bron' => 'Planning 2026 slide 4',
]);
// WISE
Commitment::create([
'project_id' => $wise->id,
'beschrijving' => 'Node-RED flows opleveren aan Bouwen / uitvoerende partij',
'eigenaar_id' => $rene->id,
'deadline' => '2026-03-31',
'status' => CommitmentStatus::InUitvoering,
'bron' => 'Planning 2026 slide 5',
]);
Commitment::create([
'project_id' => $p8->id,
'beschrijving' => 'Trainingsdata leveren: minimaal 5 jaar uurlijkse waterstandsmetingen',
'eigenaar_id' => $analyst->id,
'deadline' => '2025-08-01',
'status' => CommitmentStatus::Afgerond,
'bron' => 'Projectplan AI Waterstandsmodel v1.0',
'project_id' => $wise->id,
'beschrijving' => 'Overdracht- en documentatiepakket compleet (afbakening R&D vs beheer)',
'eigenaar_id' => $rene->id,
'deadline' => '2026-06-30',
'status' => CommitmentStatus::Open,
'bron' => 'Planning 2026 slide 5',
]);
// Gemaal 3.0
Commitment::create([
'project_id' => $gemaal->id,
'beschrijving' => 'Go/no-go besluit voor uitrol naar 2 kopieën op basis van testresultaten',
'eigenaar_id' => $sjoerd->id,
'deadline' => '2026-06-30',
'status' => CommitmentStatus::Open,
'bron' => 'Planning 2026 slide 6',
]);
Commitment::create([
'project_id' => $p10->id,
'beschrijving' => 'Eindrapportage energieopbrengst en milieuprestatie biogasinstallatie',
'eigenaar_id' => $engineer->id,
'deadline' => '2025-05-31',
'status' => CommitmentStatus::Afgerond,
'bron' => 'Evaluatieprogramma RWZI Bath',
'project_id' => $gemaal->id,
'beschrijving' => 'Overzicht software/hardware functionaliteiten en validatie digital twins',
'eigenaar_id' => $rene->id,
'deadline' => '2026-07-31',
'status' => CommitmentStatus::Open,
'bron' => 'Planning 2026 slide 6',
]);
// Afvlakkingsregeling
Commitment::create([
'project_id' => $afvlak->id,
'beschrijving' => '2 extra opstellingen gerealiseerd en gekoppeld tot keten',
'eigenaar_id' => $sjoerd->id,
'deadline' => '2026-10-31',
'status' => CommitmentStatus::Open,
'bron' => 'Planning 2026 slide 7',
]);
// Governance
Commitment::create([
'project_id' => $governance->id,
'beschrijving' => 'Projectstructuur- en documentatieafspraken vastgelegd',
'eigenaar_id' => $rene->id,
'deadline' => '2026-03-31',
'status' => CommitmentStatus::InUitvoering,
'bron' => 'Planning 2026 slide 8',
]);
Commitment::create([
'project_id' => $p11->id,
'beschrijving' => 'Technische specificaties struvietreactor aanleveren aan leverancier',
'eigenaar_id' => $testUser->id,
'deadline' => '2025-05-01',
'status' => CommitmentStatus::Afgerond,
'bron' => 'Pilotopzet Fosfaatterugwinning',
'project_id' => $governance->id,
'beschrijving' => 'Rolafbakening R&D ↔ Beheer ↔ Bouwen vastgelegd en gecommuniceerd',
'eigenaar_id' => $rene->id,
'deadline' => '2026-06-30',
'status' => CommitmentStatus::Open,
'bron' => 'Planning 2026 slide 8',
]);
// ──────────────────────────────────────────────────────────────
// 8. Documents
// ──────────────────────────────────────────────────────────────
Document::create([
'project_id' => $p1->id,
'titel' => 'Technisch Ontwerp LoRaWAN Netwerk',
'project_id' => $bridge->id,
'titel' => 'Stack Architectuur Klundert Pilot',
'type' => 'technisch_ontwerp',
'inhoud' => 'Systeemarchitectuur, gatewaylocaties, frequentieplan en databeheerprotocol voor het LoRaWAN sensornetwerk in het Biesboschgebied.',
'versie' => 2,
'auteur_id' => $engineer->id,
]);
Document::create([
'project_id' => $p1->id,
'titel' => 'Projectplan Fase Pilot',
'type' => 'projectplan',
'inhoud' => 'Doelstellingen, activiteiten, planning en risico\'s voor de pilotfase van het LoRaWAN sensornetwerk.',
'inhoud' => 'Systeemarchitectuur EDGE-laag: Ubuntu LTS, Node-RED orkestratie, OPC UA communicatie met Siemens PLC T-serie, InfluxDB/Grafana datastromen.',
'versie' => 1,
'auteur_id' => $testUser->id,
'auteur_id' => $rene->id,
]);
Document::create([
'project_id' => $p5->id,
'titel' => 'Businesscase Predictieve Gemaalbesturing',
'type' => 'businesscase',
'inhoud' => 'Kosten-batenanalyse voor de implementatie van ML-gestuurde pompsturing, inclusief energiebesparingspotentieel en investeringskosten.',
'versie' => 3,
'auteur_id' => $testUser->id,
]);
Document::create([
'project_id' => $p8->id,
'titel' => 'Modelarchitectuur LSTM Waterstandsvoorspelling',
'type' => 'technisch_rapport',
'inhoud' => 'Gedetailleerde beschrijving van de LSTM-netwerkarchitectuur, feature engineering, trainingsopzet en validatiemethodiek.',
'versie' => 1,
'auteur_id' => $analyst->id,
]);
Document::create([
'project_id' => $p10->id,
'titel' => 'Evaluatierapport Biogasopwaardering RWZI Bath',
'type' => 'evaluatierapport',
'inhoud' => 'Eindresultaten van de biogasopwaarderingsinstallatie: energieproductie, CH4-gehalte, opbrengst en geleerde lessen.',
'versie' => 1,
'auteur_id' => $engineer->id,
]);
Document::create([
'project_id' => $p4->id,
'titel' => 'BIM-protocol Kunstwerken v2.0',
'project_id' => $wise->id,
'titel' => 'Overdrachtsprotocol Monsternamekast',
'type' => 'protocol',
'inhoud' => 'Afspraken voor objectcodering, LOD-niveaus, attribuutvelden en uitwisselformaten (IFC) voor het BIM-model van kunstwerken.',
'versie' => 2,
'auteur_id' => $engineer->id,
'inhoud' => 'Opleverdocument voor de overdracht van de monsternamekast naar Bouwen. Bevat: Node-RED flow specificaties, integratie voorspellend model, afbakening verantwoordelijkheden.',
'versie' => 1,
'auteur_id' => $rene->id,
]);
Document::create([
'project_id' => $crisp->id,
'titel' => 'Technische Toetsing Aanbesteding Compressoren',
'type' => 'technisch_rapport',
'inhoud' => 'Q&A en technische beoordeling van aanbestedingsdocumenten voor compressorvervanging Nieuwveer. TCO-analyse, prestatie-eisen, energie-efficiëntie.',
'versie' => 1,
'auteur_id' => $pim->id,
]);
Document::create([
'project_id' => $gemaal->id,
'titel' => 'Testrapport Prototype Gemaal 3.0',
'type' => 'technisch_rapport',
'inhoud' => 'Bevindingen en verbeterpunten uit validatie van het prototype: elektrische aansluitingen, I/O-functionaliteit, randapparatuur, digital twin koppelingen.',
'versie' => 1,
'auteur_id' => $sjoerd->id,
]);
Document::create([
'project_id' => $governance->id,
'titel' => 'R&D Projectstructuur & Beleidskader',
'type' => 'projectplan',
'inhoud' => 'Afspraken over projectstructuur, documentatiestandaarden, besluitvormingsproces en beleid voor het R&D-lab.',
'versie' => 1,
'auteur_id' => $rene->id,
]);
// ──────────────────────────────────────────────────────────────
// 9. Dependencies between projects
// ──────────────────────────────────────────────────────────────
// AI Waterstandsmodel is afhankelijk van LoRaWAN Sensornetwerk (databron)
// Afvlakkingsregeling hangt af van Gemaal 3.0 (prototype moet gevalideerd zijn)
Afhankelijkheid::create([
'project_id' => $p8->id,
'afhankelijk_van_project_id' => $p1->id,
'type' => 'data',
'beschrijving' => 'Het AI-model heeft real-time sensordata nodig uit het LoRaWAN netwerk als input feature.',
'status' => 'open',
]);
// Digitale Tweeling is afhankelijk van AI Waterstandsmodel
Afhankelijkheid::create([
'project_id' => $p7->id,
'afhankelijk_van_project_id' => $p8->id,
'project_id' => $afvlak->id,
'afhankelijk_van_project_id' => $gemaal->id,
'type' => 'technisch',
'beschrijving' => 'De digitale tweeling integreert de voorspellingsmodule van het AI waterstandsmodel.',
'beschrijving' => 'De afvlakkingsregeling vereist gevalideerde prototypes van Gemaal 3.0 (× 2 kopieën) als basis voor de ketenopstelling.',
'status' => 'open',
]);
// Predictieve Gemaalbesturing is afhankelijk van AI Waterstandsmodel
// WISE overdracht profiteert van BRIDGE architectuur (gedeelde EDGE-infrastructuur)
Afhankelijkheid::create([
'project_id' => $p5->id,
'afhankelijk_van_project_id' => $p8->id,
'type' => 'technisch',
'beschrijving' => 'De predictieve besturing gebruikt de 48-uurs waterstandsvoorspellingen als stuurinput.',
'status' => 'open',
]);
// Remote Monitoring Waterkeringen is afhankelijk van LoRaWAN Sensornetwerk
Afhankelijkheid::create([
'project_id' => $p6->id,
'afhankelijk_van_project_id' => $p1->id,
'project_id' => $wise->id,
'afhankelijk_van_project_id' => $bridge->id,
'type' => 'infrastructuur',
'beschrijving' => 'Het monitoring-project maakt gebruik van de LoRaWAN-infrastructuur voor datatransport.',
'beschrijving' => 'De monsternamekast draait op dezelfde EDGE-architectuur die BRIDGE valideert.',
'status' => 'open',
]);
// Gemaal 3.0 validatie van digital twins hangt samen met BRIDGE architectuur
Afhankelijkheid::create([
'project_id' => $gemaal->id,
'afhankelijk_van_project_id' => $bridge->id,
'type' => 'technisch',
'beschrijving' => 'Digital twin validatie in Gemaal 3.0 gebruikt dezelfde EDGE-laag als bewezen in BRIDGE.',
'status' => 'open',
]);
}
/**
* Helper: create a project with its completed and active phases.
*
* @param array<string, mixed> $attributes
* @param FaseType[] $faseTypes All phase types in chronological order; the last one is the active phase.
*/
private function createProject(array $attributes, array $faseTypes): Project
{
$project = Project::create($attributes);
// Attach the project owner as eigenaar in the pivot table
$project->teamleden()->attach($attributes['eigenaar_id'], ['rol' => ProjectRol::Eigenaar->value]);
foreach ($faseTypes as $index => $faseType) {

Binary file not shown.