Files
mp-pilates/docs/membership-periods.md
2026-10-18 15:52:23 +08:00

4.2 KiB
Raw Blame History

月卡周期与续费规则

已确认规则

  • 月卡(DURATION)每次购买生成独立会员卡周期,不向旧周期累加课时,不覆盖旧卡、订单和预约关联。
  • 旧周期尚未到期时,新周期从同款卡已购周期的最晚到期时间开始。连续购买按支付确认顺序排期,每期额度独立。
  • 旧周期已结束时,新周期从支付确认时间开始。旧月卡即使账面还有 6 次,也不可继续使用,不会与新购 10 次合成 16 次。
  • 次卡(TIMES)保留现有规则:有效期内续费累加次数、延长有效期;过期余次不结转。体验卡仍为独立新卡。
  • 原有月卡沿用已经约定的有效期,不按开卡日倒推缩短,不批量改写历史余额。

状态与展示

新增 SCHEDULED(待生效)状态,数据库迁移只在原枚举末尾追加值,不改写现有记录。

读取会员权益时,依据服务端时间实时判断生效、到期和可用次数,不依赖凌晨任务。到期的限次月卡返回 0 次可用权益;原始账面余额留在旧记录中用于历史核对。待生效额度不会计入当前余额。

会员页分为「正在使用」「下期待生效」「历史记录」。续费页显示本期剩余与下期起止时间/独立额度,提前续费提示「支付后排期待生效」。页面打开期间在生效和到期边界刷新展示。

提前启用

接口:POST /membership/:id/activate,要求登录及 { "confirmed": true },仅操作登录用户自己的周期。

只能启用同款卡最早的待生效周期。本期必须已经用完次数;不限次月卡或仍有余次的周期不允许提前结束。

启用前先检查本期未完成预约;如仍有未来待确认/已确认课程,需上完或取消后再启用。新周期从启用时刻开始,保留完整已购时长,后续待生效周期连续重新衔接。已经预约到新周期或后续周期的课程必须仍在调整后的范围内,否则拒绝操作并提示调整预约,不自动取消课程。

购卡排期、提前启用及预约写入使用同一会员的数据库行锁串行处理。启用事务只修改周期日期与状态,不改变订单和预约所关联的周期 ID。

预约与扣次

月卡可提前预约已付款周期内的课程,但课程起止时间必须完全落在所选周期内。上课时间按场馆中国时区计算。学员预约、馆主代约及确认预约均验证周期,不能借用另一期额度。

仍由教练确认预约时扣次;未来周期被确认预约后保留待生效状态。取消后退回原周期,不转入其他新卡;已过期月卡的退回次数不会变为可用权益。

发布与兼容

  1. 备份生产数据库和当前 server/shared 构建及 Prisma Client。
  2. 应用 20261018090000_scheduled_membership_periods,生成对应 Prisma Client,再发布 shared/server。
  3. 发布小程序新版本,才能显示独立周期、正确续卡预览及提前启用入口。旧版内置的续卡计算不会随服务端更新,应配套发布小程序。

没有新增环境变量,不需要清空或重建已有会员数据。新周期与历史记录共用原有 memberships、orders、bookings 关系,既有购买不会重新发卡。

验证包括月卡 6 + 新购 10 分期保存、过期与临界时刻、连续购买排期、提前启用确认与归属、已有预约保护、课程周期边界、支付确认发放新周期、次卡原逻辑,以及共享/服务端/小程序构建。

本次验证(2026-10-18)

  • 当前工作区完整服务端测试通过:34 个套件、545 项测试。
  • shared/server 构建、小程序类型检查和微信小程序生产构建通过。
  • pnpm lint 无法执行:现有环境未安装脚本引用的 eslint;未为此调整依赖或锁文件。
  • 使用真实 Vue 页面与模拟数据检查了 390px 宽度下的未过期续卡、已过期续卡、待生效周期列表、提前启用确认及成功后的日期/额度更新;未发起真实支付或修改真实会员权益。
  • 本次月卡迁移及服务端改动已与器械课后评价一并部署生产;新版小程序尚未上传或发布。详见 联合发布记录。