Scrum4Me/prisma/seed.ts
Scrum4Me Agent 93b9c03419 docs(taxonomy): move design/api/qa/backlog/assets into folders
- docs/scrum4me-styling.md        → docs/design/styling.md
- docs/MD3_Color_Scheme_Documentation.md → docs/design/md3-color-scheme.md
- docs/API.md                     → docs/api/rest-contract.md
- docs/scrum4me-test-plan.md      → docs/qa/api-test-plan.md
- docs/scrum4me-backlog.md        → docs/backlog/index.md
- docs/scrum4me-product-backlog.md → docs/backlog/product-historical.md
- docs/erd.svg                    → docs/assets/erd.svg
- docs/icons.html                 → docs/assets/icons.html

Internal links updated across CLAUDE.md, README.md, docs/, prisma/,
and scripts/. prisma/schema.prisma erd output path also updated.
2026-05-03 12:30:58 +02:00

204 lines
6.4 KiB
TypeScript

// Seed bron: docs/backlog/index.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, '..')
dotenv.config({ path: path.join(root, '.env.local'), override: true })
dotenv.config({ path: path.join(root, '.env') })
let prisma: PrismaClient
async function main() {
const url = process.env.DATABASE_URL
if (!url) throw new Error('DATABASE_URL is not set. Check .env.local')
const { Pool } = await import('pg')
const { PrismaPg } = await import('@prisma/adapter-pg')
const pool = new Pool({ connectionString: url })
const adapter = new PrismaPg(pool)
prisma = new PrismaClient({ adapter })
console.log('Seeding database...')
// Create main demo user
const demoHash = await bcrypt.hash('demo1234', 12)
const demo = await prisma.user.upsert({
where: { username: 'demo' },
update: {},
create: {
username: 'demo',
password_hash: demoHash,
is_demo: true,
roles: {
create: [
{ role: 'PRODUCT_OWNER' },
{ role: 'DEVELOPER' },
],
},
},
})
console.log(`Demo user: ${demo.username} (id: ${demo.id})`)
// Create seed user for the product
const userHash = await bcrypt.hash('scrum4me123', 12)
const user = await prisma.user.upsert({
where: { username: 'lars' },
update: {},
create: {
username: 'lars',
password_hash: userHash,
is_demo: false,
roles: {
create: [
{ role: 'PRODUCT_OWNER' },
{ role: 'SCRUM_MASTER' },
{ role: 'DEVELOPER' },
],
},
},
})
console.log(`Main user: ${user.username} (id: ${user.id})`)
// Create tester user for cross-user isolation tests (no products)
const testerHash = await bcrypt.hash('tester123', 12)
const tester = await prisma.user.upsert({
where: { username: 'tester' },
update: {},
create: {
username: 'tester',
password_hash: testerHash,
is_demo: false,
roles: {
create: [
{ role: 'PRODUCT_OWNER' },
{ role: 'DEVELOPER' },
],
},
},
})
console.log(`Tester user: ${tester.username} (id: ${tester.id})`)
// Reset demo product data — delete in dependency order to avoid FK violations
const existingProducts = await prisma.product.findMany({ where: { user_id: demo.id }, select: { id: true } })
for (const p of existingProducts) {
// Stories reference product_id directly (no cascade), so delete PBIs first (cascades to stories via pbi_id)
const existingPbis = await prisma.pbi.findMany({ where: { product_id: p.id }, select: { id: true } })
for (const pbi of existingPbis) {
await prisma.story.deleteMany({ where: { pbi_id: pbi.id } })
}
await prisma.pbi.deleteMany({ where: { product_id: p.id } })
await prisma.sprint.deleteMany({ where: { product_id: p.id } })
}
await prisma.product.deleteMany({ where: { user_id: demo.id } })
const product = await prisma.product.create({
data: {
user_id: demo.id,
name: 'Scrum4Me',
code: '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)`)
await prisma.productMember.create({
data: { product_id: product.id, user_id: user.id },
})
console.log(` Added ${user.username} as member of ${product.name}`)
const milestones = await loadBacklog(root)
console.log(`Loaded backlog: ${milestones.length} milestones, ${milestones.reduce((acc, m) => acc + m.stories.length, 0)} stories`)
for (const ms of milestones) {
const pbi = await prisma.pbi.create({
data: {
product_id: product.id,
code: ms.key,
title: ms.title,
description: ms.goal,
priority: ms.priority,
sort_order: ms.sort_order,
},
})
const sprint = await prisma.sprint.create({
data: {
product_id: product.id,
sprint_goal: `${ms.key}${ms.goal}`,
status: ms.sprint_status,
},
})
console.log(
` PBI ${pbi.title} (priority ${pbi.priority}) + sprint ${ms.sprint_status}`,
)
// M3.5 = de huidige sprint die nog moet beginnen — alle stories en taken
// worden geforceerd op niet-uitgevoerd, ongeacht de checkbox in de backlog.
const forceOpen = ms.key === 'M3.5'
for (const s of ms.stories) {
const isActive = ms.sprint_status === 'ACTIVE'
const effectivelyDone = !forceOpen && s.status === 'DONE'
const inSprint = isActive || effectivelyDone
const storyStatus = effectivelyDone ? 'DONE' : isActive ? 'IN_SPRINT' : 'OPEN'
const storySummary = s.tasks.map((t) => t.title).join('; ')
const story = await prisma.story.create({
data: {
pbi_id: pbi.id,
product_id: product.id,
sprint_id: inSprint ? sprint.id : null,
code: s.ref,
title: s.title,
description: storySummary,
acceptance_criteria: s.acceptance_criteria,
priority: ms.priority,
sort_order: s.sort_order,
status: storyStatus,
},
})
for (const t of s.tasks) {
await prisma.task.create({
data: {
story_id: story.id,
sprint_id: inSprint ? sprint.id : null,
title: t.title,
description: t.description,
priority: ms.priority,
sort_order: t.sort_order,
status: effectivelyDone ? 'DONE' : 'TO_DO',
},
})
}
}
}
console.log('\nSeeding complete!')
console.log('Demo user: username=demo password=demo1234')
console.log('Main user: username=lars password=scrum4me123')
}
main()
.catch((e) => {
console.error(e)
process.exit(1)
})
.finally(async () => {
await prisma?.$disconnect()
})