# 月卡生效、购买与续卡规则 ## 当前规则(2026-10-30) - 仅新购月卡(DURATION)及后台新开月卡采用首次课程核销生效。历史卡保留原起止时间,不批量修改历史余额、订单、预约或已签合同。 - 每次购买生成独立会员卡,不累加到旧月卡。新卡保存购买时的 `activationDurationDays`,`startDate`、`expireDate` 均为 `null`,状态为 `SCHEDULED`(待首次核销)。等待期间不会自动生效或过期。 - 用户预约、教练确认预约、取消预约、标记未出席及课时补录都不会启动计时。原有教练确认预约时扣次的规则保留;取消退回原卡。 - 只有已确认预约核销为 `COMPLETED`,才在同一事务中首次设置月卡日期。起点取**核销当天中国时区 00:00**,该自然日计为第 1 天,截止时间为起点加购买时的有效天数,采用左闭右开区间。例如 10 月 31 日首次核销的 30 天卡,可用至 11 月 29 日结束,数据库截止时间为 11 月 30 日 00:00(中国时区)。 - 后续课程核销、重复请求不重新计算或延长有效期。购卡、预约、确认和核销使用同一会员行锁,避免并发重复激活。 - 待首次核销月卡可以预约,仍须签署要求签署的合同并有可用课时。为了保证提前预约的课程落在首次生效后的有效期内,可预约课程不超过「今天中国时区零点 + 已购天数」。生效后按实际周期验证课程起止时间。 - 每张月卡的额度、预约、退款和到期独立,月卡余次不跨期结转。次卡、体验卡原有生效和续卡规则保留。 ## 页面与合同 - 月卡详情展示「第一次上课核销,才开始计时」,明确自然日、预约不计时和查询位置。使用说明中可直接查看《会员卡服务合同》范本。 - 「我的会员卡」对新卡显示「首次预约课程核销当天生效」及已购天数,可直接预约,不提供手动提前启用。 - 预约选卡、馆主代约、会员详情和编辑页均支持日期待定,避免显示虚假日期或将待核销卡误判过期。 - 新月卡合同模板 `2026-10-v3` 的会员卡信息与第二条说明首次核销起算,未激活时保留日期待定,不用支付或合同创建时间代替。合同购买天数采用会员卡快照。 - 原有有确定日期的月卡周期、自动到期/生效和提前启用规则继续兼容。已签合同内容与签名摘要保留。 ## 在线支付前端入口 - 会员卡详情底部改为「联系馆主」,使用微信原生 `button open-type="contact"` 打开小程序客服会话,可附带所咨询会员卡的页面卡片。接待方沿用小程序后台已有客服配置。 - 支付确认弹窗和下单操作由 `packages/app/src/config/features.ts` 的 `ONLINE_PAYMENT_ENABLED = false` 屏蔽,保留原前端支付流程以供恢复。 - 后端下单、支付回调、退款、订单、发卡与合同能力均保留;未来恢复支付时,新月卡仍遵循首次核销生效。 ## 发布步骤 1. 备份数据库,应用 `20261030090000_monthly_first_check_in` 迁移(日期允许为空,新增有效天数快照字段;不更新历史记录)。 2. 生成 Prisma Client,构建并配套发布 shared/server 及新版小程序;旧版小程序不支持日期待定,不应单独发布服务端。 3. 在微信小程序真机中验收「联系馆主」客服会话,并验证新月卡购买/后台开卡、预约、确认、取消、核销后的日期与新合同范本。 无新增环境变量。当前改动只完成本地实现与验证,未应用生产迁移、部署服务端或发布小程序。 ## 本地验证 - 服务端完整回归:39 个套件、627 项测试通过;包含首次核销、中国时区跨日、预约确认与取消不激活、重复核销、历史卡兼容及合同条款/有效天数快照。 - shared/server 构建、小程序类型检查、微信小程序生产构建通过;首页 10 项测试通过。 - 390px 宽度下使用真实 Vue 页面及隔离模拟数据检查详情说明、联系馆主按钮和待首次核销月卡列表。截图见 [页面预览](screenshots/monthly-first-check-in-preview.png)。微信原生客服会话需真机验收。 - `pnpm lint` 因环境未安装脚本引用的 `eslint` 而无法运行,未为此修改依赖或锁文件。