Files
innovatieplatform/database/seeders/DatabaseSeeder.php
znetsixe 6fdeb1b5e2 Add vertical branch handles and seed architecture documents from diagrams
Branch handles: Added all 6 directions (→ ← ↑ ↓ ↘ ↗) so an entire
metro map can grow from a single starting node. Cardinal directions
(0/90/180/270°) extend the same line, diagonals (45/315°) fork to
new tracks.

Documents seeded from 6 architecture diagrams:
- EVOLV Digital Twin Hierarchy (ISA-88 tracks) → Gemaal 3.0
- Pumping Station dependency chain → Gemaal 3.0
- PLC/EDGE VLAN network architecture → BRIDGE
- R&D Stack topology (Cloud/EDGE/OT) → BRIDGE
- CoreSync network setup → BRIDGE
- R&D Timeline gitflow tracks → Governance

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:01:30 +02:00

628 lines
31 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace Database\Seeders;
use App\Enums\CommitmentStatus;
use App\Enums\FaseStatus;
use App\Enums\FaseType;
use App\Enums\Prioriteit;
use App\Enums\ProjectRol;
use App\Enums\ProjectStatus;
use App\Enums\SpeerpuntStatus;
use App\Models\Afhankelijkheid;
use App\Models\Commitment;
use App\Models\Document;
use App\Models\Fase;
use App\Models\Project;
use App\Models\Role;
use App\Models\Speerpunt;
use App\Models\Thema;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
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
{
// ──────────────────────────────────────────────────────────────
// 1. System roles
// ──────────────────────────────────────────────────────────────
$roleAdmin = Role::create([
'naam' => 'admin',
'beschrijving' => 'Volledige toegang tot het platform',
'permissies' => ['*'],
]);
$roleProjectOwner = Role::create([
'naam' => 'project_owner',
'beschrijving' => 'Kan projecten beheren en bewerken',
'permissies' => ['projects.manage', 'commitments.manage', 'documents.manage'],
]);
$roleTeamMember = Role::create([
'naam' => 'team_member',
'beschrijving' => 'Kan bijdragen aan toegewezen projecten',
'permissies' => ['projects.view', 'commitments.edit', 'documents.upload'],
]);
Role::create([
'naam' => 'viewer',
'beschrijving' => 'Alleen-lezen toegang',
'permissies' => ['projects.view', 'documents.view'],
]);
// ──────────────────────────────────────────────────────────────
// 2. Users (R&D team)
// ──────────────────────────────────────────────────────────────
$admin = User::create([
'name' => 'Admin',
'email' => 'admin@innovatieplatform.nl',
'password' => Hash::make('password'),
'functie' => 'Platform Beheerder',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$admin->roles()->attach($roleAdmin);
$rene = User::create([
'name' => 'Rene de Ren',
'email' => 'rene@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'R&D Engineer / Teamlead',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$rene->roles()->attach($roleProjectOwner);
$pim = User::create([
'name' => 'Pim Moerman',
'email' => 'p.moerman@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'Technisch Adviseur OT/IT',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$pim->roles()->attach($roleTeamMember);
$sjoerd = User::create([
'name' => 'Sjoerd Fijnje',
'email' => 's.fijnje@wbd-rd.nl',
'password' => Hash::make('password'),
'functie' => 'Werktuigbouwkundige / Elektro',
'afdeling' => 'R&D Lab',
'email_verified_at' => now(),
]);
$sjoerd->roles()->attach($roleTeamMember);
// ──────────────────────────────────────────────────────────────
// 3. Themas 2026 strategic themes
//
// Kaders: geen nieuwe ML-modellen, geen nieuwe digital twins,
// focus op werkend krijgen, architectuur aantonen, overdragen.
// ──────────────────────────────────────────────────────────────
$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' => '2026-01-01',
'periode_eind' => '2026-12-31',
]);
$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' => '2026-01-01',
'periode_eind' => '2026-12-31',
]);
$themaLab = Thema::create([
'naam' => 'Lab & Prototyping',
'beschrijving' => 'Fysieke opstellingen valideren, uitbreiden en koppelen tot een realistische testomgeving voor afvlakkingsregelingen.',
'prioriteit' => Prioriteit::Midden,
'periode_start' => '2026-01-01',
'periode_eind' => '2026-12-31',
]);
$themaGovernance = Thema::create([
'naam' => 'Governance & Teamborging',
'beschrijving' => 'R&D minder persoonsafhankelijk maken. Projectstructuur, documentatie, besluitvorming en rolafbakening vastleggen.',
'prioriteit' => Prioriteit::Midden,
'periode_start' => '2026-01-01',
'periode_eind' => '2026-12-31',
]);
// ──────────────────────────────────────────────────────────────
// 4. Speerpunten (2 per thema)
// ──────────────────────────────────────────────────────────────
// 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,
]);
$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,
]);
// 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,
]);
$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,
]);
// 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,
]);
// 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,
]);
$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 2026 planning (6 projects from the presentation)
// ──────────────────────────────────────────────────────────────
// --- 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' => '2026-01-15',
'streef_einddatum' => '2026-09-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot]);
// --- 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' => '2026-02-01',
'streef_einddatum' => '2026-08-31',
], [FaseType::Signaal, FaseType::Verkenning]);
// --- 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::Hoog,
'startdatum' => '2025-06-01',
'streef_einddatum' => '2026-06-30',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept, FaseType::Experiment, FaseType::Pilot, FaseType::Besluitvorming, FaseType::OverdrachtBouwen]);
// --- 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]);
// --- 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::Midden,
'startdatum' => '2026-06-01',
'streef_einddatum' => '2026-12-31',
], [FaseType::Signaal, FaseType::Verkenning, FaseType::Concept]);
// --- 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' => '2026-01-01',
'streef_einddatum' => '2026-12-31',
], [FaseType::Signaal, FaseType::Verkenning]);
// ──────────────────────────────────────────────────────────────
// 6. Assign team members
// ──────────────────────────────────────────────────────────────
$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' => $bridge->id,
'beschrijving' => 'Architectuur validatiedocument opleveren conform stackKlundertPilot.pdf',
'eigenaar_id' => $rene->id,
'deadline' => '2026-04-30',
'status' => CommitmentStatus::InUitvoering,
'bron' => 'Planning 2026 slide 3',
]);
Commitment::create([
'project_id' => $bridge->id,
'beschrijving' => 'OT/IT beveiligingsassessment en scheidingsrapport',
'eigenaar_id' => $pim->id,
'deadline' => '2026-06-30',
'status' => CommitmentStatus::Open,
'bron' => 'Planning 2026 slide 3',
]);
Commitment::create([
'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' => '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' => $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' => $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' => $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' => $bridge->id,
'titel' => 'Stack Architectuur Klundert Pilot',
'type' => 'technisch_ontwerp',
'inhoud' => 'Systeemarchitectuur EDGE-laag: Ubuntu LTS, Node-RED orkestratie, OPC UA communicatie met Siemens PLC T-serie, InfluxDB/Grafana datastromen.',
'versie' => 1,
'auteur_id' => $rene->id,
]);
Document::create([
'project_id' => $wise->id,
'titel' => 'Overdrachtsprotocol Monsternamekast',
'type' => 'protocol',
'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,
]);
// --- Documents extracted from architecture diagrams (raw/*.drawio.png) ---
// EVOLV-Tracks-Maintracks: full ISA-88 node hierarchy
Document::create([
'project_id' => $gemaal->id,
'titel' => 'EVOLV Digital Twin Hiërarchie (ISA-88 Tracks)',
'type' => 'technisch_ontwerp',
'inhoud' => "EVOLV node-hiërarchie conform ISA-88 (S88) batch control standaard.\n\n"
. "**Control Module**: measurement, diffuser, healthCompact, filterController\n"
. "**Equipment**: Rotating Machine, sump (gepland)\n"
. "**Unit**: machineGroupControl, valve, hydraulic network (gepland)\n"
. "**Process Cell**: Pumping Station\n"
. "**Area**: Sewage Pumping Group Control\n"
. "**Complex models**: Influent Prediction\n"
. "**Utilities**: generalFunctions, coreSync, convert, dashboardAPI\n"
. "**Data manipulation**: onderste laag\n\n"
. "Verticale tracks per asset-keten. Horizontale vertakkingen per ISA-88 niveau. "
. "Stippellijncirkels = geplande maar nog niet gebouwde nodes. "
. "Bron: EVOLV-Tracks-Maintracks.drawio.png",
'versie' => 1,
'auteur_id' => $rene->id,
]);
// EVOLV-Tracks-PumpingStation: vertical dependency chain
Document::create([
'project_id' => $gemaal->id,
'titel' => 'Pumping Station Afhankelijkheidsketen',
'type' => 'technisch_ontwerp',
'inhoud' => "Verticale afhankelijkheidsketen voor de Pumping Station track:\n\n"
. "measurement (Control Module) → Rotating Machine (Equipment) → "
. "machineGroupControl (Unit) → Sewage Pumping Station (Process Cell) → "
. "Sewage Pumping Group Control (Area) → Influent Prediction (Complex) → "
. "generalFunctions + coreSync + convert + dashboardAPI (Utilities)\n\n"
. "Elke laag is afhankelijk van de laag erboven. Equipment-nodes die als stippellijn staan "
. "(sump) zijn gepland maar nog niet ontwikkeld.\n"
. "Bron: EVOLV-Tracks-PumpingStation.drawio.png",
'versie' => 1,
'auteur_id' => $rene->id,
]);
// PLCEdge: network architecture VLAN separation
Document::create([
'project_id' => $bridge->id,
'titel' => 'PLC/EDGE Netwerk Architectuur (VLAN-scheiding)',
'type' => 'technisch_ontwerp',
'inhoud' => "Netwerkarchitectuur voor de BRIDGE pilot met VLAN-scheiding:\n\n"
. "**Extern Serverpark** (Internet): Digital Twin + Integratielaag op Edem expert system\n"
. "**Bouvigne Serverpark** (VLAN 1): Linux Server met Digital Twin + Integratielaag\n"
. "**On-site Gemaal/RWZI** (VLAN 2 + 3):\n"
. " - VLAN 3: Linux EDGE met Digital Twin + Integratielaag\n"
. " - VLAN 2: Siemens 1500 PLC (Typical) + Remote IO modules → Pomp\n\n"
. "Communicatie: HTTPS tussen extern en Bouvigne, tunnel naar EDGE, OPC UA naar PLC.\n"
. "Bron: PLCEdge-Page-1.drawio.png",
'versie' => 2,
'auteur_id' => $pim->id,
]);
// Stack: full R&D software stack
Document::create([
'project_id' => $bridge->id,
'titel' => 'R&D Stack Topologie (Cloud / EDGE / OT)',
'type' => 'technisch_ontwerp',
'inhoud' => "Drielaagse R&D stack architectuur:\n\n"
. "**Cloud/Central Layer**: nginx-proxy, Nodered, Portainer, SSL CertResolver, "
. "jenkins, influx-db, Grafana, Mosquitto, MQTT Broker, Fluffle (MQTT OUT ONLY broker), "
. "ESL dit (single port only)\n\n"
. "**EDGE Layer**: Mosquitto/VPN bridge, Nodered, Portainer, influx-db, "
. "Grafana, CoreSync, Mosquitto, MQTT SX\n\n"
. "**OT Layer**: OPCua Server → PLC\n\n"
. "Tunnel-verbinding tussen Cloud en EDGE. OPC UA van EDGE naar OT.\n"
. "Bron: Stack.drawio (2).png",
'versie' => 1,
'auteur_id' => $rene->id,
]);
// CoreSync: local/central sync topology
Document::create([
'project_id' => $bridge->id,
'titel' => 'CoreSync Netwerk Setup (Single Level)',
'type' => 'technisch_ontwerp',
'inhoud' => "CoreSync single-level configuratie:\n\n"
. "**R&D lokaal ZRG (LVL 1)**: Apparaat 1 + Apparaat 2 met measurement nodes, "
. "verbonden via Apparaat 3 (Node-Red container) met GR Bridge flows\n\n"
. "**R&D Centraal (LVL 1)**: Apparaat 4 (Node-Red container) met GR Bridge flows, "
. "verbonden via HTTPS naar lokaal\n\n"
. "Notitie: Elk netwerk dat UR, DR en 1RG bijv de edges zijn dit simpel. "
. "Ga through AZURE. Per net tekent voor edge = 1 à 1 b/u to net. "
. "PI flow at Bouvigne.\n"
. "Bron: CoreSync-Single level.drawio.png",
'versie' => 1,
'auteur_id' => $pim->id,
]);
// Complex gitflow: R&D timeline with branching tracks
Document::create([
'project_id' => $governance->id,
'titel' => 'R&D Tijdlijn & Releasebeleid (Gitflow)',
'type' => 'projectplan',
'inhoud' => "R&D release-tijdlijn als metro-tracks (gitflow model):\n\n"
. "**Tracks**: Bestuurlijk, Hotfix, Release, Release Fixes, Studenten, Yellowchess, Budget\n\n"
. "**Tijdlijn**:\n"
. "- 7/'21: R&D start PRO\n"
. "- 8/'21: Introductie met minor avans\n"
. "- 9/'21: Start minor PA avans, Opbouw partytent\n"
. "- 8/'21: Budget 40k\n"
. "- Pilot v0.1 → Verhuizing loods hardenberg → Pilot v0.2\n"
. "- Release 2.0 → 2.1\n\n"
. "Vertakkingen tonen hoe R&D-werk splitst en samenkomt.\n"
. "Bron: EVOLV-Tracks-complex gitflow.drawio.png",
'versie' => 1,
'auteur_id' => $rene->id,
]);
// ──────────────────────────────────────────────────────────────
// 9. Dependencies between projects
// ──────────────────────────────────────────────────────────────
// Afvlakkingsregeling hangt af van Gemaal 3.0 (prototype moet gevalideerd zijn)
Afhankelijkheid::create([
'project_id' => $afvlak->id,
'afhankelijk_van_project_id' => $gemaal->id,
'type' => 'technisch',
'beschrijving' => 'De afvlakkingsregeling vereist gevalideerde prototypes van Gemaal 3.0 (× 2 kopieën) als basis voor de ketenopstelling.',
'status' => 'open',
]);
// WISE overdracht profiteert van BRIDGE architectuur (gedeelde EDGE-infrastructuur)
Afhankelijkheid::create([
'project_id' => $wise->id,
'afhankelijk_van_project_id' => $bridge->id,
'type' => 'infrastructuur',
'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.
*/
private function createProject(array $attributes, array $faseTypes): Project
{
$project = Project::create($attributes);
$project->teamleden()->attach($attributes['eigenaar_id'], ['rol' => ProjectRol::Eigenaar->value]);
foreach ($faseTypes as $index => $faseType) {
$isLast = $index === count($faseTypes) - 1;
Fase::create([
'project_id' => $project->id,
'type' => $faseType,
'status' => $isLast ? FaseStatus::Actief : FaseStatus::Afgerond,
'startdatum' => now()->subMonths(count($faseTypes) - 1 - $index),
'einddatum' => $isLast ? null : now()->subMonths(count($faseTypes) - 2 - $index),
]);
}
return $project;
}
}