5.2 KiB
Context
- 现有特殊延期
SubmitSpecial(internal/application/packagesilence/extension_submit.go)输入为items[{package_usage_id, days}],validateSpecialItems只允许expired套餐,任一行不合格整批拒绝;审批字段只带首条资产与item_count。 - 执行
executeBatch→executeExtensionInTx逐条独立事务;校验套餐仍为expired。 - 批次表已有
import_file_key、计数字段;审批附件由ApprovalAttachmentUploader从对象存储 Key 下载后上传企微。 - 已有
excelize(pkg/utils/excel.go)与对象存储服务。 - 管理端批量入口在
SilenceExtendDialog.vue(CSV 填package_usage_id,days),无批次页面。
Goals / Non-Goals
Goals: 按资产号、统一天数的批量特殊延期;预检与部分提交;待实名套餐过期前延期;> 5 个资产的审批 xlsx 附件;批次查询。
Non-Goals: 不改在线付费、线下付费延期;不改单资产特殊延期接口;不改审批回调分发;批量不支持线下付费延期。
Decisions
1. 新接口而非改造旧接口
新增 POST /api/admin/package-silence/batch-extensions/precheck 与 POST /api/admin/package-silence/batch-extensions,入参 {identifiers[], days, extension_type, reason, basis, evidence_refs, amount, 线下收款信息..., import_file_key}。提交内部把可延期明细转换为现有 specialRow 后复用批次创建、审批创建、执行流程。旧 SubmitSpecial 保持兼容(单资产与旧前端)。理由:输入模型(资产号 + 统一天数)与旧接口(套餐 ID + 逐行天数)不同,改旧接口会破坏现有单资产弹窗。
2. 资产展开
复用资产标识解析(asset_identifier_store / ResolveIdentifier):ICCID → 卡,卡有有效设备绑定则换成设备;虚拟号 / IMEI → 设备。以 (asset_type, asset_id) 去重。再查询资产名下 deleted_at IS NULL AND silence_status IN ('expired','waiting') 的套餐。
3. 预检复用资格计算,放开 waiting
把 validateSpecialItems 的逐行判定抽成 checkSpecialUsage(usage, days, free, allowWaiting),批量路径 allowWaiting=true;返回结构化原因而不是累积错误。预检与提交共用同一函数,提交时服务端重跑,保证与预检一致或更严格(期间状态变化以提交时为准)。
4. 过期前延期执行
明细增加来源沉默期状态快照 source_silence_status。executeExtensionInTx 的状态校验从"必须 expired"改为"必须 expired,或明细来源为 waiting 且当前仍为 waiting/expired";新截止日统一 SilenceDeadline(当前截止日期, 延长天数);waiting 套餐延期后状态不变(不调用激活),expired 套餐沿用"改为 waiting 并重新判定"。ended、失效、退款 → 该条失败。
5. 明细 xlsx 生成时机与存储
资产数 > 5 时,在业务事务之前用 excelize 生成 xlsx,上传对象存储(Key 前缀 silence/batch-detail/{batch_no}.xlsx),批次新增 detail_file_key 记录。审批字段新增 ApprovalFieldSilenceDetailKeys = "detail_file_keys"(FileList),在 scene.go 沉默期业务字段中登记(非必须映射)。上传失败直接拒绝提交,不建批次。事务内不调用外部接口,符合现有约束。≤ 5 时 asset_identifier 字段写全部资产号(顿号分隔)。
未映射"延期明细"时附注批次号到原因:由表单构建阶段判断映射是否存在不便,改为提交时总是在原因后附注"(批次 {batch_no},共 N 个资产)"于 > 5 场景,规则简单且无副作用。
6. 跳过明细存储
批次新增 skipped_items jsonb(资产号、资产类型、套餐、原因)与 skipped_count;详情接口返回。
7. 管理端
新增「批量延期」弹窗(入口:沉默期管理 / 延期批次页):填写统一信息 → 选择 xlsx / csv(一列资产号,前端解析,≤1000)→ 调预检展示可 / 不可延期表 → 确认提交。新增「延期批次」列表与详情页,详情可下载明细 xlsx(detail_file_key 签名下载,≤ 5 个资产时由后端即时生成)。旧弹窗中的 CSV 批量入口移除。
Risks / Trade-offs
- [过期前延期改变既有"只能延期已过期"规则] → 仅批量特殊延期路径放开,单资产与付费延期不变;明细记录来源状态便于审计。
- [预检与提交之间状态变化] → 提交时服务端重跑,以提交时结果为准,前端提示差异条数。
- [1000 个资产展开后套餐数更多] → 明细上限按套餐 3000 条控制,超出拒绝并提示拆分。
- [企微附件大小] → 1000 资产 xlsx 约数十 KB,远低于限制。
Migration Plan
- 迁移:批次表加
detail_file_key、skipped_items、skipped_count;明细表加source_silence_status(默认expired)。 - 部署后端;企微模板加"延期明细"附件控件,管理端场景配置补映射(可后补)。
- 部署管理端前端。
- 回滚:回滚镜像;新增字段有默认值,不影响旧逻辑。
Open Questions
- 批量是否需要按代理 / 店铺范围限制可延期资产(目前沿用延期权限的数据范围)。