【架构实战】从业务逻辑到工程落地:私教预约系统的三大核心模型解析
目录引言设计与工程的分水岭一、分层 ER 模型系统的数据骨架1. 第一层用户与角色层Actor2. 第二层交易与资产层核心商业闭环3. 第三层履约调度层系统的真正枢纽二、状态机设计系统的行为约束1. Booking预约单状态机2. Order交易单状态机3. CourseCard课时卡状态机三、基于数据边界的权限矩阵RBAC权限矩阵一览 权限设计三大铁律四、一句话收束摘要在上一篇文章中我们完成了私教健身管理系统的业务边界划分与领域模型推演。但“架构图”如何平滑过渡到“工程代码”在进入具体的数据库建表无论是使用原生 SQL 还是 Prisma 等现代 ORM 工具之前我们必须先交付系统设计真正落地的三张核心图纸ER 实体关系模型、核心状态机、以及基于数据边界的 RBAC 权限矩阵。引言设计与工程的分水岭很多开发者在拿到需求后习惯性地凭借直觉去建表这往往会导致后期业务扩展时牵一发而动全身。一个高健壮性的 B 端交易与调度系统其底层基建必须由三个维度共同支撑ER 模型决定了系统世界里“有什么”。状态机设计决定了系统世界“怎么动”。权限模型决定了“谁能推动这个世界”。接下来我们将把抽象的业务概念直接展开为研发级、可直接用于数据库建模与低代码配置的结构。一、分层 ER 模型系统的数据骨架不要一上来就罗列几十张表优秀的数据库设计必须是分层的。以下是经过业务提纯后的核心数据结构。1. 第一层用户与角色层Actor核心思想统一身份分离职责。所有人员统一在User表中通过role字段分化行为避免多表关联带来的灾难。User统一用户表id/role(STUDENT | TRAINER | ADMIN) /name/phone/email/status2. 第二层交易与资产层核心商业闭环这一层负责记录“钱的流动”与“服务权利的确权”。商品是静态的订单是一次性的而课时资产CourseCard才是伴随用户整个生命周期的核心。Course课程商品 SKUid/title/type(如 1v1 / 1v2 等) /price/sessions_total(包含课时数) /statusOrder交易流水单id/order_no/user_id/course_id/final_price/status/pay_timeCourseCard课时资产本id/student_id/course_id/order_id/total_sessions(总额度) /used_sessions(已用) /remaining_sessions(余额) /status3. 第三层履约调度层系统的真正枢纽这是整个系统最复杂、并发最高的区域。Booking表是毫无争议的核心枢纽所有的状态流转都必须经过它。TrainerSchedule供给侧资源池id/trainer_id/date/start_time/end_time/capacity_total/capacity_booked/status设计意图将教练的时间切割为标准化的“库存资源”。Booking预约履约单id/booking_no/student_id/course_card_id/schedule_id/status/check_in_time/is_deducted(是否已扣课标记)设计意图绑定人Student、资产CourseCard与资源Schedule。SessionRecord课时流水账id/student_id/course_card_id/booking_id/type(RECHARGE | CONSUME) /sessions/remark设计意图防篡改设计。任何课时余额的变化必须在这里有确切的流水留痕。二、状态机设计系统的行为约束业务表绝不能随意UPDATE核心业务实体的生命周期必须由严格的单向状态机驱动。这能从根源上杜绝“脏数据”与“非法操作”。1. Booking预约单状态机⚠️关键认知Booking 不仅仅是一条记录它是“状态驱动的引擎”。流转路径UPCOMING已预约未上课 → 学员签到/教练上课 →COMPLETED正常完成UPCOMING→ 提前主动取消 / 系统冲突强取 →CANCELLED取消并释放资源UPCOMING→ 约定时间未签到 →NO_SHOW爽约/未到课2. Order交易单状态机流转路径PENDING待支付 →PAID已支付成功PENDING→CANCELLED超时未支付/主动取消PAID→REFUNDED发起退款强约束只有当状态切为PAID时系统才能下发CourseCard课时资产。3. CourseCard课时卡状态机流转路径VALID正常可用 → 余额扣减为 0 →EXHAUSTED课时用尽VALID→ 超过绝对有效期 →EXPIRED过期作废VALID/EXHAUSTED→ 发生退费 →REFUNDED已冻结/退款完成三、基于数据边界的权限矩阵RBAC在 B 端系统中权限设计最容易踩坑的地方在于混淆了“功能权限”与“数据权限”。一个教练和一个老板都可以拥有“查看预约View Booking”的功能权限但他们看到的数据范围Scope绝对是天壤之别。核心公式权限 Role (角色) Resource (资源) Action (操作) Scope (数据边界)权限矩阵一览模块STUDENT (学员)TRAINER (教练)ADMIN (管理员)Course (课程库)✔ 仅查看上架商品✔ 仅查看上架商品✔ 增删改查全权限Booking (预约单)✔ 创建/取消本人预约✔ 查看本人记录❌ 不可创建✔ 查看/处理关联自己的预约✔ 代客预约✔ 全局查看与强制改单CourseCard (资产)✔ 查看本人余额与流水❌ 无权访问✔ 全局管理与手动调账Schedule (排班)✔ 查看公开可用时间✔ 创建/修改本人排期✔ 全局调度与统筹排班SessionRecord✔ 查看本人扣除流水✔ 查看所授课程流水✔ 全局审计与追溯 权限设计三大铁律学员的隔离性绝对的“孤岛”只能看到与自己 ID 绑定的所有业务数据。教练的局部域基于关联关系如trainer_id构建数据视图能看自己的排班和上课学员但绝不能看到同事的数据或门店的财务数据。管理员的全局观掌握绝对控制权用于处理极端异常如退费回滚、异常排课冲突处理。四、一句话收束回到我们开篇的论调ER 模型决定了“系统世界有什么”状态机决定了“世界里的元素怎么合理地互动”权限模型决定了“谁有资格去推动这个世界”。下一步预告当这三套模型在图纸上彻底咬合后我们距离真正的工程落地就只剩下一层薄纱了。在下一篇文章中我们将直接进入代码层演示如何将这些精心设计的架构优雅地翻译成现代 ORM如 Prisma的 Schema 定义并在此基础上构建全栈 Serverless API 接口。敬请期待