【架构实战】工程落地:从领域模型到 Prisma Schema 与事件驱动架构
·
目录
摘要:所有的架构设计最终都要回归代码。在工程实现层,我们的目标只有一个:将 ER 模型、状态机和业务流程,转化为可执行的数据结构、行为入口与解耦的通信机制。本文将从 Prisma Schema 建模、RESTful API 设计以及事件总线清单三个维度,交付一套直接可开工的工程骨架。
一、 Prisma Schema:业务关系的物理映射
在 Prisma 层,我们不只是建表,而是在定义业务约束。通过强类型的 enum 和关联关系,可以在数据库层面拦截 80% 的逻辑错误。
1. 用户与核心资产层(User & CourseCard)
enum Role { STUDENT; TRAINER; ADMIN }
enum CardStatus { VALID; EXHAUSTED; EXPIRED; REFUNDED }
model User {
id String @id @default(uuid())
role Role @default(STUDENT)
name String
phone String @unique
status String @default("ACTIVE")
createdAt DateTime @default(now())
// 关联关系
orders Order[]
bookings Booking[]
cards CourseCard[]
}
model CourseCard {
id String @id @default(uuid())
studentId String
student User @relation(fields: [studentId], references: [id])
courseId String
course Course @relation(fields: [courseId], references: [id])
orderId String
order Order @relation(fields: [orderId], references: [id])
totalSessions Int
usedSessions Int @default(0)
remainingSessions Int
validEnd DateTime // 有效期截止
status CardStatus @default(VALID)
bookings Booking[]
records SessionRecord[]
}
2. 履约枢纽层(Schedule & Booking)
enum BookingStatus { UPCOMING; COMPLETED; CANCELLED; NO_SHOW }
model TrainerSchedule {
id String @id @default(uuid())
trainerId String
trainer User @relation(fields: [trainerId], references: [id])
startTime DateTime
endTime DateTime
capacityTotal Int @default(1)
capacityBooked Int @default(0)
status String @default("OPEN") // OPEN | CLOSED
bookings Booking[]
}
model Booking {
id String @id @default(uuid())
bookingNo String @unique
studentId String
student User @relation(fields: [studentId], references: [id])
scheduleId String
schedule TrainerSchedule @relation(fields: [scheduleId], references: [id])
courseCardId String
courseCard CourseCard @relation(fields: [courseCardId], references: [id])
status BookingStatus @default(UPCOMING)
checkInTime DateTime?
isDeducted Boolean @default(false) // 核心标记:是否已成功扣课
}
二、 API 设计:基于“动作”而非“资源”的契约
优秀的 API 设计不应该只是简单的 CRUD,而应该体现业务动作(Business Actions)。
1. 预约模块(核心交互)
POST /api/bookings:创建预约。输入scheduleId和courseCardId,后端执行事务(校验余额、锁定资源、生成预约单)。POST /api/bookings/:id/check-in:履约签到。触发状态变更及课时扣减逻辑。POST /api/bookings/:id/cancel:取消预约。需符合时间窗口规则,释放资源。
2. 资产与订单模块
GET /api/me/course-cards:我的课时。展示剩余次数、过期时间及使用流水。POST /api/orders/checkout:下单支付。创建待支付订单。POST /api/webhooks/payment:支付回调。处理支付成功后的资产生成逻辑。
三、 事件清单(Event List):系统的“解耦之魂”
如果让 Booking 代码直接去写 CourseCard 的余额,系统很快就会变成一团乱麻。事件驱动(EDA) 是将履约与资产解耦的最佳方式。
1. 核心事件流向
- OrderPaid:支付成功事件 → \rightarrow → 触发
CreateCourseCard(生成资产)。 - BookingCreated:预约成功事件 → \rightarrow → 触发
LockSchedule(锁定排期) &FreezeSession(冻结课时)。 - BookingCheckedIn:签到成功事件 → \rightarrow → 触发
DeductSession(实扣课时) &CalcCommission(计算提成)。 - CourseCardExhausted:课时耗尽事件 → \rightarrow → 触发
PushNotification(续费提醒)。
2. 为什么事件驱动如此重要?
- 高扩展性:未来如果想增加“上课奖励积分”功能,只需订阅
BookingCheckedIn事件,无需修改原有的履约代码。 - 故障隔离:即使“提成计算模块”暂时挂了,也不影响学员正常的签到上课。
四、 工程总结:三层架构的统一视角
- Prisma Schema(结构层):定义了静态的物理世界,确保数据一致性。
- API Layer(交互层):定义了外部世界与系统的沟通方式,封装业务逻辑。
- Event System(通信层):定义了系统内部的“呼吸”与“反馈”,实现组件间的深度解耦。
最终收束
这套系统在工程视角下,本质是一个事件驱动的履约型交易系统。
- Prisma 是地基,定死了规矩;
- API 是门户,执行着指令;
- Event 是神经网络,传递着信息。
至此,从业务问题定义到最终的代码实现架构,我们已经完成了一次完整的闭环。对于开发者而言,接下来的工作就是将这些 Schema 填入项目,按照 API 契约编写 Service 逻辑,并用事件总线将它们串联起来。这就是构建一个专业级 SaaS 系统的标准路径。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)