feat(server): add database seed script

Seeds: studio config, 5 card types (trial, 10x, 20x, monthly, quarterly),
admin user, weekday+Saturday time slot templates
This commit is contained in:
richarjiang
2026-04-02 12:34:53 +08:00
parent 994d1f75d5
commit b9d55c9e9f
2 changed files with 157 additions and 0 deletions

View File

@@ -60,5 +60,8 @@
"moduleNameMapper": {
"^@mp-pilates/shared(.*)$": "<rootDir>/../../shared/src$1"
}
},
"prisma": {
"seed": "ts-node prisma/seed.ts"
}
}

View File

@@ -0,0 +1,154 @@
import { PrismaClient, UserRole, CardTypeCategory } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
console.log('🌱 Seeding database...')
// 1. Studio Config
const existingConfig = await prisma.studioConfig.findFirst()
if (!existingConfig) {
await prisma.studioConfig.create({
data: {
name: '普拉提工作室',
address: '请在管理后台设置地址',
phone: '请在管理后台设置电话',
cancelHoursLimit: 2,
photos: [],
},
})
console.log(' ✅ Studio config created')
} else {
console.log(' ⏭️ Studio config already exists')
}
// 2. Card Types
const existingCards = await prisma.cardType.count()
if (existingCards === 0) {
await prisma.cardType.createMany({
data: [
{
name: '体验课',
type: CardTypeCategory.TRIAL,
totalTimes: 1,
durationDays: 7,
price: 9900,
originalPrice: 29900,
description: '首次体验,感受普拉提的魅力',
isActive: true,
sortOrder: 0,
},
{
name: '私教10次卡',
type: CardTypeCategory.TIMES,
totalTimes: 10,
durationDays: 90,
price: 299900,
originalPrice: 399900,
description: '10节私教课90天有效期',
isActive: true,
sortOrder: 1,
},
{
name: '私教20次卡',
type: CardTypeCategory.TIMES,
totalTimes: 20,
durationDays: 180,
price: 499900,
originalPrice: 699900,
description: '20节私教课180天有效期更优惠',
isActive: true,
sortOrder: 2,
},
{
name: '月卡',
type: CardTypeCategory.DURATION,
totalTimes: null,
durationDays: 30,
price: 99900,
description: '30天不限次数',
isActive: true,
sortOrder: 3,
},
{
name: '季卡',
type: CardTypeCategory.DURATION,
totalTimes: null,
durationDays: 90,
price: 249900,
originalPrice: 299700,
description: '90天不限次数更实惠',
isActive: true,
sortOrder: 4,
},
],
})
console.log(' ✅ Card types created')
} else {
console.log(' ⏭️ Card types already exist')
}
// 3. Admin User
const existingAdmin = await prisma.user.findFirst({
where: { role: UserRole.ADMIN },
})
if (!existingAdmin) {
await prisma.user.create({
data: {
openid: 'admin_test_openid',
nickname: '教练',
role: UserRole.ADMIN,
},
})
console.log(' ✅ Admin user created')
} else {
console.log(' ⏭️ Admin user already exists')
}
// 4. Week Templates (weekdays 9-16, hourly slots)
const existingTemplates = await prisma.weekTemplate.count()
if (existingTemplates === 0) {
const timeSlots = [
{ startTime: '09:00', endTime: '10:00' },
{ startTime: '10:00', endTime: '11:00' },
{ startTime: '14:00', endTime: '15:00' },
{ startTime: '15:00', endTime: '16:00' },
]
const templates = []
// Monday to Friday (1-5)
for (let day = 1; day <= 5; day++) {
for (const slot of timeSlots) {
templates.push({
dayOfWeek: day,
startTime: slot.startTime,
endTime: slot.endTime,
capacity: 1,
isActive: true,
})
}
}
// Saturday (6) — morning only
templates.push(
{ dayOfWeek: 6, startTime: '09:00', endTime: '10:00', capacity: 1, isActive: true },
{ dayOfWeek: 6, startTime: '10:00', endTime: '11:00', capacity: 1, isActive: true },
)
await prisma.weekTemplate.createMany({ data: templates })
console.log(' ✅ Week templates created')
} else {
console.log(' ⏭️ Week templates already exist')
}
console.log('🌱 Seeding complete!')
}
main()
.catch((e) => {
console.error('❌ Seed failed:', e)
process.exit(1)
})
.finally(async () => {
await prisma.$disconnect()
})