From 854c50bad3b7818989d65a879c1e3afd9fa18fd4 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Sun, 26 Apr 2026 16:09:14 +0200 Subject: [PATCH] feat(ST-004): replace DevPlanner seed with Scrum4Me backlog Co-Authored-By: Claude Opus 4.7 (1M context) --- prisma/seed.ts | 212 +++++++++++++------------------------------------ 1 file changed, 53 insertions(+), 159 deletions(-) diff --git a/prisma/seed.ts b/prisma/seed.ts index e15033f..1351646 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,7 +1,10 @@ +// Seed bron: docs/scrum4me-backlog.md → prisma/seed-data/parse-backlog.ts. +// Pas alléén de backlog-markdown aan als je seed-data wilt wijzigen, niet deze file. import { PrismaClient } from '@prisma/client' import * as dotenv from 'dotenv' import * as path from 'path' import * as bcrypt from 'bcryptjs' +import { loadBacklog } from './seed-data/parse-backlog' // Load env from project root const root = path.resolve(__dirname, '..') @@ -99,187 +102,78 @@ async function main() { const product = await prisma.product.create({ data: { user_id: demo.id, - name: 'DevPlanner', - description: 'Een lichtgewicht Scrum-gebaseerde projectplanner voor solo developers en kleine Scrum Teams.', - repo_url: 'https://github.com/devplanner/devplanner', - definition_of_done: 'Feature is geïmplementeerd, getest (unit + integratie), gedocumenteerd in code, en gedeployed naar de staging-omgeving zonder regressies.', + name: 'Scrum4Me', + description: + 'Een desktop-first fullstack webapplicatie voor solo developers en kleine Scrum Teams die meerdere softwareprojecten parallel beheren.', + repo_url: 'https://github.com/madhura68/Scrum4Me', + definition_of_done: + 'Code is geïmplementeerd, type-checked, getest, gedocumenteerd in code en docs, en gedeployed naar Vercel zonder regressies.', archived: false, }, }) console.log(`Product created: ${product.name} (id: ${product.id}, owner: demo)`) - // PBI data from the product backlog document - const pbis = [ - { - title: 'Authenticatie & gebruikersbeheer', - description: 'Het Scrum Team kan een account aanmaken en inloggen met gebruikersnaam en wachtwoord. Een demo-gebruiker heeft alleen leesrechten. Gebruikers kunnen één of meerdere Scrum-rollen aannemen.', - priority: 1, - stories: [ - { title: 'Account aanmaken', description: 'Als bezoeker wil ik een account aanmaken met gebruikersnaam en wachtwoord, zodat ik toegang krijg tot de app.', acceptance_criteria: '- Gebruikersnaam en wachtwoord zijn verplicht\n- Gebruikersnaam is uniek; dubbele aanmelding geeft foutmelding\n- Wachtwoord heeft minimaal 8 tekens\n- Na aanmaken wordt de gebruiker direct ingelogd\n- Geen e-mailverificatie vereist in v1', priority: 1 }, - { title: 'Inloggen', description: 'Als geregistreerde gebruiker wil ik inloggen met gebruikersnaam en wachtwoord, zodat ik mijn projecten kan beheren.', acceptance_criteria: '- Incorrecte combinatie geeft generieke foutmelding\n- Na inloggen wordt de gebruiker doorgestuurd naar het dashboard\n- Sessie blijft actief totdat de gebruiker uitlogt', priority: 1 }, - { title: 'Uitloggen', description: 'Als ingelogde gebruiker wil ik kunnen uitloggen, zodat mijn sessie veilig afgesloten wordt.', acceptance_criteria: '- Uitlogknop altijd zichtbaar in de navigatie\n- Na uitloggen wordt de gebruiker naar de loginpagina gestuurd\n- Sessiedata wordt gewist', priority: 1 }, - { title: 'Demo-gebruiker (read-only)', description: 'Als bezoeker wil ik kunnen inloggen als demo-gebruiker, zodat ik de app kan verkennen zonder een account aan te maken.', acceptance_criteria: '- Vaste inloggegevens voor de demo-gebruiker zijn beschikbaar op de loginpagina\n- Demo-gebruiker ziet alle data maar kan niets aanmaken, aanpassen of verwijderen\n- Alle actieknoppen zijn zichtbaar maar uitgeschakeld', priority: 2 }, - { title: 'Roltoewijzing', description: 'Als gebruiker wil ik één of meerdere Scrum-rollen kunnen aannemen (Product Owner, Scrum Master, Developer).', acceptance_criteria: '- Gebruiker kan bij registratie of in instellingen rollen selecteren\n- Minimaal één rol is verplicht\n- Alle drie de rollen tegelijk zijn toegestaan', priority: 3 }, - ], - }, - { - title: 'Productbeheer', - description: 'Het Scrum Team kan producten aanmaken, bekijken, bewerken en archiveren.', - priority: 1, - stories: [ - { title: 'Product aanmaken', description: 'Als Product Owner wil ik een nieuw product aanmaken met naam, beschrijving en git-repo URL.', acceptance_criteria: '- Naam is verplicht en uniek per gebruiker\n- Beschrijving is optioneel\n- Git-repo URL is optioneel maar wordt gevalideerd als geldige URL', priority: 1 }, - { title: 'Product bewerken', description: 'Als Product Owner wil ik de naam, beschrijving en git-repo URL van een product kunnen aanpassen.', acceptance_criteria: '- Alle velden zijn bewerkbaar\n- Wijzigingen worden opgeslagen zonder de pagina te verlaten', priority: 2 }, - { title: 'Product archiveren', description: 'Als Product Owner wil ik een product kunnen archiveren.', acceptance_criteria: '- Gearchiveerde producten verschijnen niet in de standaardlijst\n- Archiveren is omkeerbaar', priority: 2 }, - { title: 'Productenlijst bekijken', description: 'Als gebruiker wil ik een overzicht zien van alle actieve producten.', acceptance_criteria: '- Lijst toont naam, beschrijving (ingekort) en git-repo link\n- Klikken op een product opent de Product Backlog', priority: 1 }, - ], - }, - { - title: 'Product Backlog', - description: 'Het Scrum Team kan de Product Backlog beheren via een gesplitst scherm: links de PBIs, rechts de bijbehorende stories.', - priority: 1, - stories: [ - { title: 'PBI aanmaken', description: 'Als Product Owner wil ik een PBI aanmaken in de Product Backlog.', acceptance_criteria: '- PBI heeft een titel (verplicht) en omschrijving (optioneel)\n- PBI krijgt een prioriteit (1 t/m 4)\n- Nieuw PBI verschijnt onderaan de lijst', priority: 1 }, - { title: 'PBI bewerken', description: 'Als Product Owner wil ik de titel, omschrijving en prioriteit van een PBI kunnen aanpassen.', acceptance_criteria: '- Dubbelklikken of via contextmenu opent bewerkingsmodus\n- Alle velden zijn inline bewerkbaar', priority: 2 }, - { title: 'PBI verwijderen', description: 'Als Product Owner wil ik een PBI kunnen verwijderen.', acceptance_criteria: '- Verwijderen vereist bevestiging\n- Cascade verwijdering van bijbehorende stories', priority: 2 }, - { title: 'PBI prioriteit instellen', description: 'Als Product Owner wil ik per PBI een prioriteit kunnen instellen (1 t/m 4).', acceptance_criteria: '- Prioriteit is instelbaar via dropdown of inline label\n- PBIs worden gegroepeerd per prioriteit', priority: 1 }, - { title: 'PBI volgorde aanpassen via drag-and-drop', description: 'Als Product Owner wil ik de volgorde van PBIs binnen dezelfde prioriteit kunnen aanpassen via drag-and-drop.', acceptance_criteria: '- Drag-and-drop werkt vloeiend via dnd-kit\n- Volgorde wordt direct opgeslagen na loslaten', priority: 2 }, - { title: 'PBI filteren', description: 'Als gebruiker wil ik PBIs kunnen filteren op prioriteit.', acceptance_criteria: '- Filteropties beschikbaar in de navigatiebar\n- Filter werkt realtime', priority: 3 }, - { title: 'Gesplitst scherm Product Backlog', description: 'Als gebruiker wil ik de Product Backlog bekijken als gesplitst scherm.', acceptance_criteria: '- Scherm is standaard 50/50 verdeeld\n- Splitter is horizontaal versleepbaar', priority: 1 }, - ], - }, - { - title: 'Story-beheer', - description: 'Stories kunnen worden aangemaakt, bewerkt, geprioriteerd en gerangschikt binnen een PBI.', - priority: 1, - stories: [ - { title: 'Story aanmaken', description: 'Als Product Owner wil ik een story aanmaken binnen een PBI.', acceptance_criteria: '- Story heeft een titel (verplicht), omschrijving (optioneel) en prioriteit\n- Nieuwe story verschijnt als blok rechts', priority: 1 }, - { title: 'Story weergave als blokken', description: 'Als gebruiker wil ik stories zien als compacte blokken (~10% schermbreedte).', acceptance_criteria: '- Elk blok toont: storytitel, prioriteit, status\n- Blokken zijn gerangschikt op prioriteit', priority: 1 }, - { title: 'Story prioriteit instellen', description: 'Als Product Owner wil ik per story een prioriteit instellen.', acceptance_criteria: '- Prioriteit instelbaar via het storyblok\n- Prioriteitswijziging herplaatst het blok in de juiste groep', priority: 2 }, - { title: 'Story volgorde aanpassen via drag-and-drop', description: 'Als Product Owner wil ik de volgorde van stories aanpassen via drag-and-drop.', acceptance_criteria: '- Drag-and-drop werkt via dnd-kit\n- Volgorde wordt direct opgeslagen', priority: 2 }, - { title: 'Story bewerken', description: 'Als Product Owner wil ik de titel, omschrijving en prioriteit van een story kunnen aanpassen.', acceptance_criteria: '- Bewerkbaar via klikken op het storyblok\n- Wijzigingen opgeslagen zonder paginaverversing', priority: 2 }, - { title: 'Story verwijderen', description: 'Als Product Owner wil ik een story kunnen verwijderen.', acceptance_criteria: '- Verwijderen vereist bevestiging\n- Cascade verwijdering van gekoppelde taken', priority: 2 }, - ], - }, - { - title: 'Todo-lijst', - description: 'Gebruikers kunnen een snelle todo-lijst bijhouden voor ongeplande of kortstondige taken.', - priority: 2, - stories: [ - { title: 'Todo-item aanmaken', description: 'Als gebruiker wil ik snel een todo-item aanmaken zonder het aan een product te koppelen.', acceptance_criteria: '- Todo heeft alleen een titel (verplicht)\n- Aanmaken via een snel-invoerveld (Enter om op te slaan)', priority: 1 }, - { title: 'Todo-item afvinken', description: 'Als gebruiker wil ik een todo-item kunnen afvinken.', acceptance_criteria: '- Afgevinkte items zijn visueel doorgestreept\n- Afgevinkte items kunnen worden gearchiveerd', priority: 1 }, - { title: 'Todo promoveren naar PBI', description: 'Als Product Owner wil ik een todo-item promoveren naar een PBI.', acceptance_criteria: '- Promoten opent een dialoog om product en prioriteit te kiezen\n- Todo wordt omgezet naar een PBI', priority: 2 }, - { title: 'Todo promoveren naar story', description: 'Als Product Owner wil ik een todo-item promoveren naar een story.', acceptance_criteria: '- Promoten opent een dialoog om product, PBI en prioriteit te kiezen\n- Todo wordt omgezet naar een story', priority: 2 }, - ], - }, - { - title: 'Sprint Backlog & Sprint Planning', - description: 'Het Scrum Team kan een Sprint aanmaken met een Sprint Goal, stories slepen en de volgorde bepalen.', - priority: 2, - stories: [ - { title: 'Sprint aanmaken', description: 'Als Scrum Master wil ik een nieuwe Sprint aanmaken met een Sprint Goal.', acceptance_criteria: '- Sprint heeft een Sprint Goal (verplicht)\n- Sprint is gekoppeld aan een product\n- Er kan maar één actieve Sprint per product zijn', priority: 1 }, - { title: 'Sprint Backlog scherm (gesplitst)', description: 'Als gebruiker wil ik de Sprint Backlog kunnen beheren via een gesplitst scherm.', acceptance_criteria: '- Links: Sprint Backlog met geselecteerde stories\n- Rechts: stories uit de Product Backlog', priority: 1 }, - { title: 'Story naar Sprint slepen', description: 'Als Developer wil ik een story vanuit de Product Backlog naar de Sprint Backlog kunnen slepen.', acceptance_criteria: '- Drag-and-drop werkt via dnd-kit\n- Story verschijnt in de Sprint Backlog op de gesleepte positie', priority: 1 }, - { title: 'Volgorde stories in Sprint bepalen', description: 'Als Developer wil ik de volgorde van stories in de Sprint Backlog kunnen aanpassen.', acceptance_criteria: '- Drag-and-drop werkt binnen de Sprint Backlog\n- Volgorde wordt direct opgeslagen', priority: 2 }, - { title: 'Story uit Sprint verwijderen', description: 'Als Developer wil ik een story uit de Sprint Backlog kunnen verwijderen.', acceptance_criteria: '- Story verdwijnt uit de Sprint Backlog\n- Story is weer beschikbaar in de Product Backlog', priority: 2 }, - ], - }, - { - title: 'Sprint Planning (taken per story)', - description: 'Tijdens Sprint Planning worden stories opgedeeld in taken via een gesplitst scherm.', - priority: 2, - stories: [ - { title: 'Sprint Planning scherm', description: 'Als Developer wil ik een Sprint Planning scherm zien met stories links en taken rechts.', acceptance_criteria: '- Links: stories in de Sprint Backlog\n- Rechts: taken van de geselecteerde story', priority: 1 }, - { title: 'Taak aanmaken', description: 'Als Developer wil ik een taak aanmaken onder een story.', acceptance_criteria: '- Taak heeft een titel (verplicht), omschrijving (optioneel) en prioriteit\n- Nieuwe taak verschijnt onderaan de takenlijst', priority: 1 }, - { title: 'Taak prioriteit instellen', description: 'Als Developer wil ik per taak een prioriteit instellen.', acceptance_criteria: '- Prioriteit instelbaar via taakregel\n- Taken gegroepeerd op prioriteit', priority: 2 }, - { title: 'Taak volgorde aanpassen via drag-and-drop', description: 'Als Developer wil ik de volgorde van taken kunnen aanpassen via drag-and-drop.', acceptance_criteria: '- Drag-and-drop via dnd-kit binnen de takenlijst\n- Volgorde direct opgeslagen na loslaten', priority: 2 }, - { title: 'Taakstatus bijhouden', description: 'Als Developer wil ik de status van een taak kunnen bijhouden (To Do, In Progress, Done).', acceptance_criteria: '- Status is instelbaar via de UI\n- Story toont een voortgangsindicator op basis van taakstatussen', priority: 1 }, - ], - }, - { - title: 'Claude Code integratie', - description: 'Claude Code kan via een REST API stories en taken ophalen, implementatieplannen vastleggen en commits registreren.', - priority: 2, - stories: [ - { title: 'REST API — story ophalen', description: 'Als Developer (via Claude Code) wil ik de hoogst geprioriteerde open story ophalen via een API-endpoint.', acceptance_criteria: '- Endpoint: GET /api/products/:id/next-story\n- Authentiseerd via API-token\n- Geeft 404 als er geen open stories zijn', priority: 1 }, - { title: 'REST API — eerste 10 taken ophalen', description: 'Als Developer (via Claude Code) wil ik de eerste 10 taken van de Sprint Backlog kunnen ophalen.', acceptance_criteria: '- Endpoint: GET /api/sprints/:id/tasks?limit=10\n- Retourneert taken in huidige volgorde', priority: 1 }, - { title: 'REST API — taakvolgorde aanpassen', description: 'Als Developer (via Claude Code) wil ik de volgorde van taken kunnen aanpassen via de API.', acceptance_criteria: '- Endpoint: PATCH /api/stories/:id/tasks/reorder\n- Accepteert een geordende lijst van taak-ids', priority: 2 }, - { title: 'Implementatieplan vastleggen', description: 'Als Developer (via Claude Code) wil ik een implementatieplan kunnen schrijven naar een story.', acceptance_criteria: '- Endpoint: POST /api/stories/:id/log\n- type: "IMPLEMENTATION_PLAN"', priority: 1 }, - { title: 'Teststatus vastleggen', description: 'Als Developer (via Claude Code) wil ik de uitkomst van testruns kunnen vastleggen in een story.', acceptance_criteria: '- Endpoint: POST /api/stories/:id/log\n- type: "TEST_RESULT", status: "PASSED" | "FAILED"', priority: 1 }, - { title: 'Commit-hash vastleggen', description: 'Als Developer (via Claude Code) wil ik de commit-hash na een succesvolle commit kunnen vastleggen.', acceptance_criteria: '- Endpoint: POST /api/stories/:id/log\n- type: "COMMIT", commit_hash, commit_message', priority: 1 }, - { title: 'Story activiteitenlog in UI', description: 'Als gebruiker wil ik per story een activiteitenlog zien met alle vastgelegde plannen, testresultaten en commits.', acceptance_criteria: '- Log toont alle entries in chronologische volgorde\n- Elk type entry heeft een eigen visuele stijl', priority: 2 }, - ], - }, - { - title: 'Infrastructuur & deployment', - description: 'De app is deployable op Vercel + Neon en volledig lokaal draaibaar zonder externe afhankelijkheden.', - priority: 1, - stories: [ - { title: 'Cloud deployment (Vercel + Neon)', description: 'Als Developer wil ik de app deployen op Vercel met een Neon PostgreSQL-database.', acceptance_criteria: '- next build slaagt zonder fouten\n- Database-migraties worden uitgevoerd via Prisma', priority: 1 }, - { title: 'Lokale modus', description: 'Als Developer wil ik de app lokaal kunnen draaien met een Neon PostgreSQL-database.', acceptance_criteria: '- npm run dev start de app lokaal\n- DATABASE_URL verwijst naar Neon connection string', priority: 1 }, - { title: 'API-token authenticatie', description: 'Als Developer wil ik een API-token kunnen genereren in de app.', acceptance_criteria: '- Gebruiker kan een API-token aanmaken\n- Token wordt eenmalig getoond\n- Alle API-endpoints vereisen een geldig token', priority: 1 }, - ], - }, - ] + const milestones = await loadBacklog(root) + console.log(`Loaded backlog: ${milestones.length} milestones, ${milestones.reduce((acc, m) => acc + m.stories.length, 0)} stories`) - // Create all PBIs and their stories - for (let pbiIdx = 0; pbiIdx < pbis.length; pbiIdx++) { - const pbiData = pbis[pbiIdx] + for (const ms of milestones) { const pbi = await prisma.pbi.create({ data: { product_id: product.id, - title: pbiData.title, - description: pbiData.description, - priority: pbiData.priority, - sort_order: (pbiIdx + 1) * 1.0, + title: `${ms.key}: ${ms.title}`, + description: ms.goal, + priority: ms.priority, + sort_order: ms.sort_order, }, }) - console.log(` PBI: ${pbi.title} (priority ${pbi.priority})`) + const sprint = await prisma.sprint.create({ + data: { + product_id: product.id, + sprint_goal: `${ms.key} — ${ms.goal}`, + status: ms.sprint_status, + }, + }) - for (let storyIdx = 0; storyIdx < pbiData.stories.length; storyIdx++) { - const storyData = pbiData.stories[storyIdx] - await prisma.story.create({ + console.log( + ` PBI ${pbi.title} (priority ${pbi.priority}) + sprint ${ms.sprint_status}`, + ) + + for (const s of ms.stories) { + const isActive = ms.sprint_status === 'ACTIVE' + const inSprint = isActive || s.status === 'DONE' + const storyStatus = + s.status === 'DONE' ? 'DONE' : isActive ? 'IN_SPRINT' : 'OPEN' + + const story = await prisma.story.create({ data: { pbi_id: pbi.id, product_id: product.id, - title: storyData.title, - description: storyData.description, - acceptance_criteria: storyData.acceptance_criteria, - priority: storyData.priority, - sort_order: (storyIdx + 1) * 1.0, - status: 'OPEN', + sprint_id: inSprint ? sprint.id : null, + title: s.title, + description: s.description, + acceptance_criteria: s.acceptance_criteria, + priority: ms.priority, + sort_order: s.sort_order, + status: storyStatus, + }, + }) + + await prisma.task.create({ + data: { + story_id: story.id, + sprint_id: inSprint ? sprint.id : null, + title: 'Implementatie', + description: s.description, + priority: ms.priority, + sort_order: 1.0, + status: s.status === 'DONE' ? 'DONE' : 'TO_DO', }, }) } } - // Create active sprint for the demo product - const sprint = await prisma.sprint.create({ - data: { - product_id: product.id, - sprint_goal: 'Gebruikers kunnen inloggen, een product aanmaken en de Product Backlog beheren.', - status: 'ACTIVE', - }, - }) - - console.log(`Sprint created: ${sprint.sprint_goal}`) - - // Add the first story of each of the first 3 PBIs to the sprint - const sprintStoryTitles = [ - 'Account aanmaken', - 'Product aanmaken', - 'PBI aanmaken', - ] - - for (const title of sprintStoryTitles) { - await prisma.story.updateMany({ - where: { product_id: product.id, title }, - data: { sprint_id: sprint.id, status: 'IN_SPRINT' }, - }) - } - - console.log(`Added ${sprintStoryTitles.length} stories to the sprint`) console.log('\nSeeding complete!') console.log('Demo user: username=demo password=demo1234')