2026-09-29 · 基线 origin/test(7f6d6a1f);核心文件与 origin/main 无差异 · 只读核查,未改代码
需求(长官 9-18 拍板):品牌码新扫码的家长号从扫码当天起算 365 天硬到期;到期挡住并提示「服务已到期,请联系机构续期」;机构在品牌码页点「延期」续期;老号不动;天数固定 365。
| 核查 | 命令要点 | 结果 |
|---|---|---|
| require_org_seat 无到期检查 | git show origin/test:app/auth/middleware.py \| sed -n 335,410p |
is_active 命中 3(对照有效)· seat_expires_at/assert_seat_org_usable 命中 0 |
| 到期检查现有位置 | 同文件 grep assert_seat_org_usable | 仅 :289-290(require_h5_user 分支) |
| 品牌码建号从不写到期 | brand_code_service.py grep seat_expires_at/valid_days |
只有 :94 注释、:289 读;签 token 在 :274 前无检查 |
| 用 require_org_seat 的接口 | git grep -c "Depends(require_org_seat)" |
brand_code_claim / parent_ocr / parent_patients / middleware(require_store_seat) |
| 生产现有品牌码号 | seatops 只读 SQL | 生产 brand_codes=0 · activations=0 · 品牌码席位 0(对照 org_seat 177) |
| test 现有品牌码号 | 同上 | 3 个,到期字段全 NULL |
→ 「老号不动」在生产上没有存量要兼容;test 3 个号保持 NULL 即永久。
_provision_family_seat(brand_code_service.py:81-113)调 generate_seats 不传 valid_days → seat_valid_days / seat_expires_at 都是 NULL。改造:建号时显式写 seat_expires_at = 绑定时刻 + 365 天(不能只传天数,否则起算点会变成「首次密码登录」)。assert_seat_org_usable(seat_expiry.py:22-42)被 refresh(:944)、require_h5_user(middleware:289)、verify_api_key(h5_chat:127)调用。require_org_seat(middleware.py:335-408)只查 is_active 和设备号,不查到期 → 孩子档案 / OCR / 认领 / 门店接口都漏。PATCH /api/admin/parent-seats/{id}/extend → extend_seat(seat_service.py:663-719),只改 users.seat_expires_at,已过期从当前时刻起算;两字段都 NULL 的号返回 400「永久席位无需续期」。_provision_family_seat,和开通记录用同一个时间点activate_brand_code 对命中的旧号检查到期,到期返回 403「服务已到期,请联系机构续期」require_org_seat 加到期检查(复用 assert_seat_org_usable),一处覆盖孩子档案/OCR/认领/门店接口预估改动:brand_code_service.py、middleware.py、seat_expiry.py(文案)、admin_brand_code.py(视 D2)、前端两处(视 D4)、测试若干。不需要迁移。