摘要:在上一篇文章中,我们完成了私教健身管理系统的业务边界划分与领域模型推演。但“架构图”如何平滑过渡到“工程代码”?在进入具体的数据库建表(无论是使用原生 SQL 还是 Prisma 等现代 ORM 工具)之前,我们必须先交付系统设计真正落地的三张核心图纸:ER 实体关系模型、核心状态机、以及基于数据边界的 RBAC 权限矩阵

引言:设计与工程的分水岭

很多开发者在拿到需求后,习惯性地凭借直觉去建表,这往往会导致后期业务扩展时牵一发而动全身。

一个高健壮性的 B 端交易与调度系统,其底层基建必须由三个维度共同支撑:

  • ER 模型:决定了系统世界里“有什么”。
  • 状态机设计:决定了系统世界“怎么动”。
  • 权限模型:决定了“谁能推动这个世界”。

接下来,我们将把抽象的业务概念,直接展开为研发级、可直接用于数据库建模与低代码配置的结构。


一、分层 ER 模型(系统的数据骨架)

不要一上来就罗列几十张表,优秀的数据库设计必须是分层的。以下是经过业务提纯后的核心数据结构。

1. 第一层:用户与角色层(Actor)

核心思想:统一身份,分离职责。所有人员统一在 User 表中,通过 role 字段分化行为,避免多表关联带来的灾难。

  • User(统一用户表)
  • id / role (STUDENT | TRAINER | ADMIN) / name / phone / email / status

2. 第二层:交易与资产层(核心商业闭环)

这一层负责记录“钱的流动”与“服务权利的确权”。商品是静态的,订单是一次性的,而课时资产(CourseCard)才是伴随用户整个生命周期的核心。

  • Course(课程商品 SKU)

  • id / title / type (如 1v1 / 1v2 等) / price / sessions_total (包含课时数) / status

  • Order(交易流水单)

  • id / order_no / user_id / course_id / final_price / status / pay_time

  • CourseCard(课时资产本)

  • id / student_id / course_id / order_id / total_sessions (总额度) / used_sessions (已用) / remaining_sessions (余额) / status

3. 第三层:履约调度层(系统的真正枢纽)

这是整个系统最复杂、并发最高的区域。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(已支付成功)
  • PENDINGCANCELLED(超时未支付/主动取消)
  • PAIDREFUNDED(发起退款)
  • 强约束:只有当状态切为 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 ✔ 查看本人扣除流水 ✔ 查看所授课程流水 ✔ 全局审计与追溯

💡 权限设计三大铁律:

  1. 学员的隔离性:绝对的“孤岛”,只能看到与自己 ID 绑定的所有业务数据。
  2. 教练的局部域:基于关联关系(如 trainer_id)构建数据视图,能看自己的排班和上课学员,但绝不能看到同事的数据或门店的财务数据。
  3. 管理员的全局观:掌握绝对控制权,用于处理极端异常(如退费回滚、异常排课冲突处理)。

四、一句话收束

回到我们开篇的论调:

  • ER 模型 决定了“系统世界有什么”;
  • 状态机 决定了“世界里的元素怎么合理地互动”;
  • 权限模型 决定了“谁有资格去推动这个世界”。

下一步预告:
当这三套模型在图纸上彻底咬合后,我们距离真正的工程落地就只剩下一层薄纱了。在下一篇文章中,我们将直接进入代码层,演示如何将这些精心设计的架构,优雅地翻译成现代 ORM(如 Prisma)的 Schema 定义,并在此基础上构建全栈 Serverless API 接口。敬请期待!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐