Files
junhong_cmp_fiber/migrations/000235_extend_carrier_threshold_hit.up.sql
break 5ed6b39deb
Some checks failed
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Has been cancelled
feat(收口): 补齐 8 月迭代缺口并同步 Spec 与证据链
- 新增六对成对迁移 000232–000237:H5 弹窗类型、退款结算标识与申请人备注、优先轮询事实字段与两个新终态、通道阈值命中留痕、手机号最近解绑人、提现资格校验留痕
- 退款:原因必填与申请人备注、来源支付与渠道流水冻结、线下处理流水号补录审计、按订单查询可选退款方式、企微审批材料补齐且新增字段缺失映射即明确失败
- 优先轮询:人工关闭、有效期到期独立周期任务、失败与过期人工重触发、事实字段与异常重试查询、资产解析端点只读投影
- 通道阈值:命中事实同事务留痕与命中记录查询;员工账单:列表筛选与详情投影;商户池:列表投影与统计周期语义;H5:弹窗类型与类别排序
- 手机号:有效关联数量与最近解绑人、短信验证码失败次数限制;导出:佣金明细十五列与报表序号列
- 时间筛选:三处新增筛选纳入统一严格解析契约,员工账单产生时间参数改名
- 同步 12 份主 Spec 需求、两端点与异步任务证据链,门禁 context-health 与 OpenSpec 校验通过
2026-09-18 15:34:29 +08:00

75 lines
6.3 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- 运营商通道阈值命中事实留痕。
-- 背景111.md 要求阈值命中可解释、可查询:停机后运维必须能看到「命中时该卡累计流量多少、
-- 判定用的阈值是多少(含改阈值前的历史值)、属于哪个计费周期、什么时候判定、由什么触发」,
-- 并能在周期恢复时看到解锁时间与复机结果。既有 tb_carrier_traffic_threshold_lock 只有
-- 锁生命周期与停复机子任务状态,没有任何数字证据,改阈值后历史命中无法解释。
--
-- 设计选择:
-- 1. 加列到既有锁表而不新建命中事实表:锁表本身即「一次命中一条」(一个卡一个计费周期至多一条),
-- 新建表会与锁表 1:1 冗余并需要额外一致性约束。
-- 2. hit_* 三列冻结命中时值hit_traffic_mb 取与停机判定同一来源的网关累计读数换算值MB
-- 不使用本地用量或套餐真流量hit_threshold_value/hit_threshold_unit 取该次判定实际生效的
-- 通道配置值,因此之后修改通道阈值不会改写历史命中。
-- 3. judged_at 是判定时间:既有行以创建时间回填(历史读数与阈值不可重建),回填后置为非空。
-- hit_traffic_mb 与 hit_threshold_value 允许为空,读侧按「无」展示而不阻断查询。
-- 4. trigger_source 记录触发本次判定的流量观测来源(与 pkg/constants.CardObservationSource*
-- 一致),使自动判定与重放可区分;允许空串以兼容回滚期旧代码插入。
-- 5. unlocked_at/resume_result 记录周期恢复结果MUST NOT 覆盖上面的停机命中事实:
-- resumed-已发起复机 skipped-仅解锁未复机 manual-周期归属不可判定转人工;跳过原因沿用既有失败原因列。
-- 6. 新增按通道与按卡的判定时间索引,服务命中记录查询的筛选与排序。
-- 7. 本迁移不改动既有达量判定、停机调用、持锁拒绝复机与新周期解锁语义。
ALTER TABLE tb_carrier_traffic_threshold_lock
ADD COLUMN hit_traffic_mb NUMERIC(18,2),
ADD COLUMN hit_threshold_value NUMERIC(18,2),
ADD COLUMN hit_threshold_unit VARCHAR(8) NOT NULL DEFAULT '',
ADD COLUMN judged_at TIMESTAMPTZ,
ADD COLUMN trigger_source VARCHAR(20) NOT NULL DEFAULT '',
ADD COLUMN unlocked_at TIMESTAMPTZ,
ADD COLUMN resume_result VARCHAR(30) NOT NULL DEFAULT '';
-- 历史行判定时间取创建时间;命中数值与阈值留空(历史读数不可重建,读侧按「无」展示)。
UPDATE tb_carrier_traffic_threshold_lock
SET judged_at = created_at
WHERE judged_at IS NULL;
ALTER TABLE tb_carrier_traffic_threshold_lock
ALTER COLUMN judged_at SET NOT NULL;
-- judged_at 保留默认值 NOW():本次硬规则要求「新列可空或带默认值」,而 judged_at 需要非空
-- (判定时间是命中记录的查询与排序依据)。若不给默认值,回滚到上一版本二进制时,旧代码写入
-- 停机锁不带该列会直接违反 NOT NULL使达量停机事实无法落库。默认值让旧代码插入的命中事实
-- 以插入时刻作为判定时间,与「既有行以创建时间回填」的语义自洽。
ALTER TABLE tb_carrier_traffic_threshold_lock
ALTER COLUMN judged_at SET DEFAULT NOW();
ALTER TABLE tb_carrier_traffic_threshold_lock
ADD CONSTRAINT ck_carrier_traffic_threshold_lock_hit_traffic CHECK (hit_traffic_mb IS NULL OR hit_traffic_mb >= 0),
ADD CONSTRAINT ck_carrier_traffic_threshold_lock_hit_threshold CHECK (hit_threshold_value IS NULL OR hit_threshold_value > 0),
ADD CONSTRAINT ck_carrier_traffic_threshold_lock_hit_unit CHECK (hit_threshold_unit IN ('', 'MB', 'GB')),
ADD CONSTRAINT ck_carrier_traffic_threshold_lock_trigger_source CHECK (
trigger_source IN ('', 'polling', 'manual_sync', 'manual_override', 'carrier_callback', 'business_event')
),
ADD CONSTRAINT ck_carrier_traffic_threshold_lock_resume_result CHECK (
resume_result IN ('', 'resumed', 'skipped', 'manual')
);
COMMENT ON COLUMN tb_carrier_traffic_threshold_lock.hit_traffic_mb IS '命中时该卡当前计费周期的累计流量读数MB取与停机判定同一来源的网关累计读数换算值不使用本地用量或套餐真流量历史行为空表示读数不可重建';
COMMENT ON COLUMN tb_carrier_traffic_threshold_lock.hit_threshold_value IS '本次判定实际生效的通道阈值数值,冻结命中时值,改阈值后历史命中不被改写;历史行为空';
COMMENT ON COLUMN tb_carrier_traffic_threshold_lock.hit_threshold_unit IS '本次判定阈值的单位 MB-兆字节 GB-吉字节,空字符串-历史行未记录';
COMMENT ON COLUMN tb_carrier_traffic_threshold_lock.judged_at IS '判定时间,既有行以创建时间回填;命中记录查询与排序以此为业务时间。列默认值为 NOW(),使回滚期不写该列的旧代码插入的命中事实以插入时刻作为判定时间';
COMMENT ON COLUMN tb_carrier_traffic_threshold_lock.trigger_source IS '触发本次判定的流量观测来源 polling-周期轮询 manual_sync-手动同步 manual_override-人工纠偏 carrier_callback-运营商回调 business_event-业务成功后的观测;空字符串-历史行未记录';
COMMENT ON COLUMN tb_carrier_traffic_threshold_lock.unlocked_at IS '周期恢复时的解锁时间,只在跨期解锁成功时写入;不覆盖停机命中事实';
COMMENT ON COLUMN tb_carrier_traffic_threshold_lock.resume_result IS '周期恢复的复机结果 resumed-已发起复机 skipped-仅解锁未复机 manual-周期归属不可判定转人工;空字符串-未处理或历史行,跳过原因沿用失败原因列';
-- 命中记录查询按判定时间倒序:分别按运营商通道与按卡提供索引,避免查询走顺序扫描。
CREATE INDEX idx_carrier_traffic_threshold_lock_carrier_judged
ON tb_carrier_traffic_threshold_lock (carrier_id, judged_at DESC, id DESC)
WHERE deleted_at IS NULL;
CREATE INDEX idx_carrier_traffic_threshold_lock_card_judged
ON tb_carrier_traffic_threshold_lock (card_id, judged_at DESC, id DESC)
WHERE deleted_at IS NULL;
COMMENT ON INDEX idx_carrier_traffic_threshold_lock_carrier_judged IS '通道阈值命中记录按通道与判定时间分页索引';
COMMENT ON INDEX idx_carrier_traffic_threshold_lock_card_judged IS '通道阈值命中记录按卡与判定时间分页索引';