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:
@@ -60,5 +60,8 @@
|
|||||||
"moduleNameMapper": {
|
"moduleNameMapper": {
|
||||||
"^@mp-pilates/shared(.*)$": "<rootDir>/../../shared/src$1"
|
"^@mp-pilates/shared(.*)$": "<rootDir>/../../shared/src$1"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"prisma": {
|
||||||
|
"seed": "ts-node prisma/seed.ts"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
154
packages/server/prisma/seed.ts
Normal file
154
packages/server/prisma/seed.ts
Normal 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()
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user