交付出件箱

← 返回出件箱

Phase 87 · 品牌码扫码席位「真到期」技术方案

阶段 3 architecture · 2026-09-29 · 基线 origin/test 83ca4937
编号 verify:Phase 87|phase87 在 docs/ 0 处(仅 dev2 memory 2 处为本议题预占)· 对照 Phase 83 3 处命中
核心 9 个文件与第一轮 verify 基线 7f6d6a1f 对比 git diff --stat 空,行号沿用有效
verify 报告:~/reports/brand-code-hard-expiry-verify-20260929.md(13 维 + D1-D5 第二轮)

0. 长官拍板(不再讨论)

# 口径 来源
R1 品牌码新扫码建的家长号,从扫码当天起 365 天硬到期 9-18
R2 到期后所有入口都挡住 9-18
R3 续期 = 机构在品牌码页点「延期」(已有功能,只改 users.seat_expires_at) 9-18 / 9-21
R4 老号不动(到期字段 NULL 照旧永久);生产品牌码 0 个,无存量 9-18
D1 所有到期号统一提示「服务已到期,请联系机构续期」(平台号的「席位已到期」一起换) 9-29 按建议
D2 品牌码页到期日/状态/统计跟着延期走(= 家长号真实到期日) 9-29 按建议
D2′ 收费不管:导出表「到期日 / 状态 / 是否计费 / 合计」维持开通记录 365 天,不动 9-29 长官「不用管收费 你就给延期就行」
D3 同一微信在本机构有停用的家长号(不论来源),再扫码拦下「账号已停用,请联系机构」 9-29 长官「就先不放进来了」
D4 已登录家长遇到期,被踢出的登录窗显示「服务已到期,请联系机构续期」 9-29 按建议
D5 到期提醒脚本自动包含品牌码号,不改代码 9-29 按建议

1. 现状(物理取证)

2. 改动(不改表 · 不迁移)

2.1 建号写到期日(R1)

_provision_family_seat 第二次提交处:同一个 now 写 seat_bound_at 和 seat_expires_at = now + timedelta(days=ACTIVATION_VALID_DAYS)(常量 :39 已存在)。
不改 generate_seats 签名(结算按位置参数调用);seat_valid_days 保持 NULL。同步改 docstring :94-96 那段「留 None(永久)」的旧说明。

2.2 扫码入口拦到期(R2)

activate_brand_code 在 seat, is_new = await _find_or_provision_family_seat(...)(:261)之后、刷新昵称/记开通/签 token 之前:
assert_seat_org_usable(None, seat)(函数内 import,同 middleware:289 写法)。到期 → 403,不刷新昵称、不记开通、不发 token。

2.3 停用号再扫码拦下(D3)

_find_existing_family_seat 加关键字参数 active: bool = True,条件改为 User.is_active.is_(active)(默认值保持原行为)。
_find_or_provision_family_seat 在「找不到可用号」后、新建前:用 active=False 再查一次,命中 → HTTPException(403, "账号已停用,请联系机构")(在锁内抛,finally 照常释放锁)。

2.4 每次请求拦到期(R2)

require_org_seat 在 if seat is None or not seat.is_active 之后(:389 后)加 assert_seat_org_usable(None, seat)。
影响:门店号(约 23 个接口)到期也会被挡;生产实测门店号 136 个中已到期 23 个、到期后登录过 0 个,实际影响≈0(长官已知晓)。

2.5 文案统一(D1)

seat_expiry.py 与 seat_auth.py:563 两处 "席位已到期" → "服务已到期,请联系机构续期"(全角逗号)。
前端无按旧字符串做判断的代码(login-diagnosis.ts:69 自行按时间生成标签,不读后端文字)。

2.6 品牌码页跟延期走(D2 / D2′)

2.7 已登录家长被踢显示原因(D4)

2.8 不改

3. 测试(禁 mock · 真 PG)

见 test-coverage-analysis.md「Phase 87」节。旧文案断言 4 处同步改:tests/api/test_seat_extend.py:373、tests/integration/test_seat_expiry_e2e.py:177/474、tests/integration/test_login_alert_org_nickname_e2e.py:107。

4. 发版

改登录相关 → 先发 test,长官真机验(扫码新号 / 手工把 test 号到期日改到过去看提示 / 停用后重扫 / 延期后页面日期)再发生产。