Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
- 新增六对成对迁移 000232–000237:H5 弹窗类型、退款结算标识与申请人备注、优先轮询事实字段与两个新终态、通道阈值命中留痕、手机号最近解绑人、提现资格校验留痕 - 退款:原因必填与申请人备注、来源支付与渠道流水冻结、线下处理流水号补录审计、按订单查询可选退款方式、企微审批材料补齐且新增字段缺失映射即明确失败 - 优先轮询:人工关闭、有效期到期独立周期任务、失败与过期人工重触发、事实字段与异常重试查询、资产解析端点只读投影 - 通道阈值:命中事实同事务留痕与命中记录查询;员工账单:列表筛选与详情投影;商户池:列表投影与统计周期语义;H5:弹窗类型与类别排序 - 手机号:有效关联数量与最近解绑人、短信验证码失败次数限制;导出:佣金明细十五列与报表序号列 - 时间筛选:三处新增筛选纳入统一严格解析契约,员工账单产生时间参数改名 - 同步 12 份主 Spec 需求、两端点与异步任务证据链,门禁 context-health 与 OpenSpec 校验通过
113 lines
9.9 KiB
Markdown
113 lines
9.9 KiB
Markdown
# close-august-iteration-gaps 上线与回滚说明
|
||
|
||
对应 tasks.md §14.1 / §14.2 / §14.4。上线顺序与回滚口径依据 design.md「Migration Plan」与 proposal.md「Impact」。
|
||
|
||
## 1. 上线顺序(必须先迁移,再发二进制,再配置企微,最后开放新字段使用)
|
||
|
||
### 第一步:执行六对迁移(按编号顺序,不修改既有迁移)
|
||
|
||
| 顺序 | 迁移编号 | 内容 |
|
||
| --- | --- | --- |
|
||
| 1 | `000232_add_h5_popup_type` | `tb_h5_popup_configuration` 加 `popup_type`(枚举 `promotion`/`announcement`,非空,默认 `announcement`)+ 取值 CHECK;up 以默认值回填既有行 |
|
||
| 2 | `000233_extend_refund_settlement_fields` | 退款主表加 `source_payment_no`(`varchar(64)`)、`original_channel_trade_no`(**`varchar(100)`**,与来源列 `tb_payment.third_party_trade_no` 一致)、`offline_settlement_no`(`varchar(128)`)、`offline_settled_at`、`offline_settled_by`;退款审批尝试表加 `remark`(申请人备注,逐次冻结) |
|
||
| 3 | `000234_extend_polling_priority_item` | 优先轮询事实表加 `asset_type`、`asset_id`、`device_no_snapshot`、`agent_shop_id_snapshot`、`attempt_limit`(默认 3)、`started_at`、`finished_at`、`next_run_at`、`dequeued_at`、`integration_log_id`、`priority_effective_from`;重建状态 CHECK 容纳 `closed` 与 `expired`;活动项部分唯一索引谓词保持 `status IN ('pending','processing')` 不变;为 `next_run_at` 建部分索引;既有活动项 `priority_effective_from` 回填为迁移时刻,资产列按既有设备—卡绑定回填 |
|
||
| 4 | `000235_extend_carrier_threshold_hit` | 阈值锁表加命中累计流量、阈值数值、阈值单位、判定时间、触发来源、解锁时间、复机结果;判定时间回填既有行创建时间(并置默认 `now()`),命中数值与阈值留空;新增按通道、卡与判定时间的查询索引 |
|
||
| 5 | `000236_add_phone_association_invalidator_name` | 手机号—资产关联加 `invalidator_name_snapshot`(非空默认空串) |
|
||
| 6 | `000237_extend_withdrawal_attempt_qualification` | 提现审批尝试表加资料资格版本标识、校验时间、是否通过、未通过稳定原因 |
|
||
|
||
执行方式:维护者按既有迁移脚本(`scripts/migrate.sh`)执行,六对全部落盘后再统一 `up`(本次测试环境即如此,避免先落盘的号被后落盘的低号跳过)。执行后用只读查询核对列/默认值/CHECK/索引(见 `verification.md` 第 2 节)。
|
||
|
||
### 第二步:发布 API / Worker 二进制
|
||
|
||
手工发布,步骤见 `docs/deployment/production-runbook.md`。发布前确认工作树包含本变更全部生产代码改动(`go build ./cmd/api ./cmd/worker` 通过)。
|
||
|
||
### 第三步:维护者配置企业微信控件映射(仅本变更新增字段强制映射)
|
||
|
||
- 退款审批场景:套餐已用量与总量、资产类型、设备类型与型号、原支付渠道交易流水号。
|
||
- 代理注册审批场景:业务员。
|
||
- 以 `GET /api/admin/wecom/scenes` 返回的启用记录与 `control_mapping` 作为验收证据。既有未映射的可选控件保持既有静默跳过行为。
|
||
- 未配置前:退款/注册审批提交时对缺失的新增控件**明确失败并提示缺失控件**(不静默丢弃)。
|
||
|
||
### 第四步:开放新字段使用
|
||
|
||
新端点与新增筛选按第 3 节启用;前端按第 4 节的参数改名同步。
|
||
|
||
### 上线前置清单(两项,待维护者执行)
|
||
|
||
| 项 | 内容 | 验收证据 | 状态 |
|
||
| --- | --- | --- | --- |
|
||
| 1 | 在生产配置企业微信控件映射:退款审批的套餐用量(已用量与总量)、资产类型、设备类型与型号、原渠道流水号;代理注册审批的业务员 | `GET /api/admin/wecom/scenes` 返回的启用记录与 `control_mapping` | **待维护者执行** |
|
||
| 2 | 员工账单时间参数改名的前端同步:`created_from`/`created_to` → `start_time`/`end_time`(旧参数名与旧格式一律拒绝,无兼容别名) | 前端发布后员工账单列表与详情的时间筛选可用 | **待维护者执行** |
|
||
|
||
两项上线前置未完成前:新字段的企微审批材料会在提交时**明确失败并提示缺失控件**(不静默丢弃);员工账单的旧时间参数调用会被**参数非法拒绝**。
|
||
|
||
## 2. 回滚步骤
|
||
|
||
### 2.1 代码回退
|
||
|
||
代码回退到上一版本后,数据库停留在 237 形态,各新增列**可空或带默认值**,旧二进制不写这些列也不会违反约束:
|
||
|
||
| 表 | 列 | 回滚期旧代码不写时的取值 |
|
||
| --- | --- | --- |
|
||
| `tb_h5_popup_configuration` | `popup_type` | 默认 `announcement` |
|
||
| `tb_refund_request` | `source_payment_no`(`varchar(64)`)/ `original_channel_trade_no`(`varchar(100)`,与来源列 `tb_payment.third_party_trade_no` 一致)/ `offline_settlement_no`(`varchar(128)`) | 默认空串 |
|
||
| `tb_refund_request` | `offline_settled_at` | NULL(可空) |
|
||
| `tb_refund_request` | `offline_settled_by` | 默认 `0` |
|
||
| `tb_refund_request_attempt` | `remark` | 默认空串 |
|
||
| `tb_polling_priority_item` | `asset_type` / `device_no_snapshot` / `integration_log_id` | 默认空串 |
|
||
| `tb_polling_priority_item` | `asset_id` / `agent_shop_id_snapshot` / `started_at` / `finished_at` / `next_run_at` / `dequeued_at` / `priority_effective_from` | NULL(可空) |
|
||
| `tb_polling_priority_item` | `attempt_limit` | 默认 `3` |
|
||
| `tb_carrier_traffic_threshold_lock` | `hit_traffic_mb` / `hit_threshold_value` | NULL(可空) |
|
||
| `tb_carrier_traffic_threshold_lock` | `hit_threshold_unit` / `trigger_source` / `resume_result` | 默认空串 |
|
||
| `tb_carrier_traffic_threshold_lock` | `judged_at` | **默认 `now()`** |
|
||
| `tb_carrier_traffic_threshold_lock` | `unlocked_at` | NULL(可空) |
|
||
| `tb_phone_asset_association` | `invalidator_name_snapshot` | 默认空串 |
|
||
| `tb_commission_withdrawal_request_attempt` | `qualification_version_id` / `qualification_passed` | 默认 `0` |
|
||
| `tb_commission_withdrawal_request_attempt` | `qualification_checked_at` | NULL(可空) |
|
||
| `tb_commission_withdrawal_request_attempt` | `qualification_failure_reason` | 默认空串 |
|
||
|
||
`judged_at` 单独说明:该列需要非空(判定时间是命中记录的查询与排序依据),但若不给默认值,回退到上一版本二进制时旧代码写入停机锁不带该列就会违反 NOT NULL,使达量停机事实无法落库。因此保留 `DEFAULT now()`,让旧代码插入的命中事实以插入时刻作为判定时间,与「既有行以创建时间回填」的语义自洽。
|
||
|
||
### 2.2 读侧兼容
|
||
|
||
- 读侧对上述空值与默认值一律按「无」处理,不因新列缺失或为空阻断查询(命中读数/阈值历史行为空按「无」展示,判定时间取既有创建时间)。
|
||
- 既有优先轮询行的有效期起算时间(`priority_effective_from`)为迁移时刻,**不会**在上线后被首轮到期扫描批量判为已过期;既有行的 `next_run_at` 为空时,读侧 MUST NOT 据此判定已过期。
|
||
- 历史审批尝试不受本变更的必填与留痕影响:退款原因必填只对上线后新提交与重提生效,历史申请与补发历史审批不追溯;提现历史尝试的资格校验留痕为空按「历史尝试无资格校验留痕」处理。
|
||
|
||
### 2.3 企微控件配置回滚
|
||
|
||
代码回滚时需**同步移除**本变更新增的控件映射(退款审批的套餐用量/资产类型/设备类型与型号/原支付渠道交易流水号,代理注册审批的业务员),避免模板残留未使用控件。
|
||
|
||
### 2.4 时间参数替换回滚
|
||
|
||
员工账单列表「产生时间」参数改名属有意的破坏性收敛,**旧参数名不再被接受**;回滚需**同步前端**(见第 4 节)。
|
||
|
||
### 2.5 迁移 down
|
||
|
||
如需实际回滚 Schema,按 6→1 逆序执行六对迁移的 down;注意各 down 均声明不可逆事实的丢弃(H5 类型、退款结算标识与备注、优先轮询留痕、命中数字证据、解绑人名称快照、资格校验留痕),其中 `000234` 的 down 在存在 `closed`/`expired` 终态行时会拒绝执行。
|
||
|
||
## 3. 新增端点与失效字段默认值
|
||
|
||
### 3.1 新增端点(方法 / 路径 / 权限主体)
|
||
|
||
| 方法 | 路径 | 权限主体 |
|
||
| --- | --- | --- |
|
||
| GET | `/api/admin/refunds/order-options` | 退款组门禁(超级管理员/平台/代理,企业账号拒绝)+ 订单数据范围 |
|
||
| POST | `/api/admin/refunds/:id/offline-settlement` | 同退款组门禁 + 订单数据范围 |
|
||
| POST | `/api/admin/polling-priority-items/:id/close` | 超级管理员与平台账号 |
|
||
| POST | `/api/admin/polling-priority-items/:id/retrigger` | 与人工入队一致(含数据范围内的代理账号) |
|
||
| GET | `/api/admin/carrier-traffic-threshold-hits` | 超级管理员与平台账号 + 卡数据范围 |
|
||
|
||
同时新增周期任务类型:优先轮询有效期到期扫描与出队(Worker 调度注册,`@every` 周期)。
|
||
|
||
### 3.2 失效字段默认值(新增列的上线默认值)
|
||
|
||
见 2.1 表;一句话概括:新增列一律可空或带默认值(空串 / `0` / `3` / `announcement` / `now()`),既有行零变更。
|
||
|
||
## 4. 调用方同步要求
|
||
|
||
- **员工账单列表**:既有「产生时间」参数由 `created_from`/`created_to` **改名为 `start_time`/`end_time`**,并改用统一严格解析器。旧参数名(`created_from`/`created_to`)与旧格式(date-only、无时区串、空格分隔、小数秒、`±hhmm`)**一律以参数非法错误拒绝,不保留别名或兼容**;前端 MUST 同步改用 `start_time`/`end_time`。
|
||
- 员工账单「核销通过时间」使用 `decided_start_time`/`decided_end_time`,与主字段同一解析器、同一闭区间(带时区 RFC3339 秒级、含两端)。
|
||
- 优先轮询项查询、通道阈值命中查询的筛选时间字段亦使用 `start_time`/`end_time`。
|
||
- 员工账单列表与统计响应新增「未核销金额」与「剩余可核销金额」两个并列字段;详情新增操作日志与来源订单快照投影。
|