Files
junhong_cmp_fiber/migrations/000055_package_system_upgrade.up.sql
huang c665f32976
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m54s
feat: 套餐系统升级 - Worker 重构、流量重置、文档与规范更新
- 重构 Worker 启动流程,引入 bootstrap 模块统一管理依赖注入
- 实现套餐流量重置服务(日/月/年周期重置)
- 新增套餐激活排队、加油包绑定、囤货待实名激活逻辑
- 新增订单创建幂等性防重(Redis 业务键 + 分布式锁)
- 更新 AGENTS.md/CLAUDE.md:新增注释规范、幂等性规范,移除测试要求
- 添加套餐系统升级完整文档(API文档、使用指南、功能总结、运维指南)
- 归档 OpenSpec package-system-upgrade 变更,同步 specs 到主目录
- 新增 queue types 抽象和 Redis 常量定义
2026-02-12 14:24:15 +08:00

112 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.
-- Package 表扩展:新增周期类型、流量重置周期、实名激活开关
ALTER TABLE tb_package
ADD COLUMN IF NOT EXISTS calendar_type VARCHAR(20) DEFAULT 'by_day',
ADD COLUMN IF NOT EXISTS duration_days INT,
ADD COLUMN IF NOT EXISTS data_reset_cycle VARCHAR(20) DEFAULT 'monthly',
ADD COLUMN IF NOT EXISTS enable_realname_activation BOOLEAN DEFAULT TRUE;
-- PackageUsage 表扩展:新增优先级、主套餐关联、独立有效期、实名激活等字段
-- 注status 字段枚举值扩展为 0-40=待生效1=生效中2=已用完3=已过期4=已失效)
ALTER TABLE tb_package_usage
ADD COLUMN IF NOT EXISTS priority INT DEFAULT 1,
ADD COLUMN IF NOT EXISTS master_usage_id BIGINT,
ADD COLUMN IF NOT EXISTS has_independent_expiry BOOLEAN DEFAULT FALSE,
ADD COLUMN IF NOT EXISTS pending_realname_activation BOOLEAN DEFAULT FALSE,
ADD COLUMN IF NOT EXISTS data_reset_cycle VARCHAR(20),
ADD COLUMN IF NOT EXISTS last_reset_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS next_reset_at TIMESTAMP;
-- IotCard 表扩展:新增首次实名时间、停复机相关字段
ALTER TABLE tb_iot_card
ADD COLUMN IF NOT EXISTS first_realname_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS stopped_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS resumed_at TIMESTAMP,
ADD COLUMN IF NOT EXISTS stop_reason VARCHAR(50);
-- Carrier 表扩展新增计费日字段联通27号其他1号
ALTER TABLE tb_carrier
ADD COLUMN IF NOT EXISTS billing_day INT DEFAULT 1;
-- 创建 PackageUsageDailyRecord 表:套餐流量日记录
CREATE TABLE IF NOT EXISTS tb_package_usage_daily_record (
id BIGSERIAL PRIMARY KEY,
package_usage_id BIGINT NOT NULL,
date DATE NOT NULL,
daily_usage_mb INT DEFAULT 0,
cumulative_usage_mb BIGINT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 创建 CardDailyUsage 表:卡流量日记录(用于轮询系统)
CREATE TABLE IF NOT EXISTS tb_card_daily_usage (
id BIGSERIAL PRIMARY KEY,
card_id BIGINT NOT NULL,
usage_date DATE NOT NULL,
total_data_usage BIGINT DEFAULT 0,
carrier_id BIGINT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 创建索引
-- PackageUsage 表索引
CREATE INDEX IF NOT EXISTS idx_package_usage_priority ON tb_package_usage(priority);
CREATE INDEX IF NOT EXISTS idx_package_usage_master_usage_id ON tb_package_usage(master_usage_id);
CREATE INDEX IF NOT EXISTS idx_package_usage_next_reset_at ON tb_package_usage(next_reset_at);
-- PackageUsageDailyRecord 表唯一索引(同一套餐同一天只有一条记录)
CREATE UNIQUE INDEX IF NOT EXISTS idx_package_usage_daily_record_unique ON tb_package_usage_daily_record(package_usage_id, date);
CREATE INDEX IF NOT EXISTS idx_package_usage_daily_record_date ON tb_package_usage_daily_record(date);
-- CardDailyUsage 表唯一索引(同一卡同一天只有一条记录)
CREATE UNIQUE INDEX IF NOT EXISTS idx_card_daily_usage_unique ON tb_card_daily_usage(card_id, usage_date);
CREATE INDEX IF NOT EXISTS idx_card_daily_usage_date ON tb_card_daily_usage(usage_date);
-- 数据初始化:设置运营商的 billing_day
-- 联通(假设 carrier_name 或 carrier_code 包含 "unicom" 或 "联通"
UPDATE tb_carrier
SET billing_day = 27
WHERE LOWER(carrier_name) LIKE '%unicom%' OR carrier_name LIKE '%联通%';
-- 其他运营商默认为 1 号(已通过 DEFAULT 设置)
-- 添加字段注释PostgreSQL 语法)
-- Package 表字段注释
COMMENT ON COLUMN tb_package.calendar_type IS '套餐周期类型natural_month=自然月by_day=按天)';
COMMENT ON COLUMN tb_package.duration_days IS '套餐天数calendar_type=by_day 时必填)';
COMMENT ON COLUMN tb_package.data_reset_cycle IS '流量重置周期daily/monthly/yearly/none';
COMMENT ON COLUMN tb_package.enable_realname_activation IS '是否启用实名激活true=需实名后激活false=立即激活)';
-- PackageUsage 表字段注释
COMMENT ON COLUMN tb_package_usage.priority IS '优先级(主套餐和加油包都按此字段排队,数字越小优先级越高)';
COMMENT ON COLUMN tb_package_usage.master_usage_id IS '主套餐使用记录ID加油包关联主套餐主套餐此字段为NULL';
COMMENT ON COLUMN tb_package_usage.has_independent_expiry IS '加油包是否有独立有效期true=有独立到期时间false=跟随主套餐)';
COMMENT ON COLUMN tb_package_usage.pending_realname_activation IS '是否等待实名激活true=待实名后激活false=已激活或不需实名)';
COMMENT ON COLUMN tb_package_usage.data_reset_cycle IS '流量重置周期(从 Package 复制,用于历史记录)';
COMMENT ON COLUMN tb_package_usage.last_reset_at IS '最后一次流量重置时间';
COMMENT ON COLUMN tb_package_usage.next_reset_at IS '下次流量重置时间(用于定时任务查询)';
-- IotCard 表字段注释
COMMENT ON COLUMN tb_iot_card.first_realname_at IS '首次实名时间(用于触发首次实名激活)';
COMMENT ON COLUMN tb_iot_card.stopped_at IS '停机时间';
COMMENT ON COLUMN tb_iot_card.resumed_at IS '最近复机时间';
COMMENT ON COLUMN tb_iot_card.stop_reason IS '停机原因traffic_exhausted=流量耗尽manual=手动停机arrears=欠费)';
-- Carrier 表字段注释
COMMENT ON COLUMN tb_carrier.billing_day IS '运营商计费日(用于流量查询接口的计费周期计算,联通=27其他=1';
-- PackageUsageDailyRecord 表和字段注释
COMMENT ON TABLE tb_package_usage_daily_record IS '套餐流量日记录';
COMMENT ON COLUMN tb_package_usage_daily_record.package_usage_id IS '套餐使用记录ID';
COMMENT ON COLUMN tb_package_usage_daily_record.date IS '日期';
COMMENT ON COLUMN tb_package_usage_daily_record.daily_usage_mb IS '当日流量使用量MB';
COMMENT ON COLUMN tb_package_usage_daily_record.cumulative_usage_mb IS '截止当日的累计流量MB';
-- CardDailyUsage 表和字段注释
COMMENT ON TABLE tb_card_daily_usage IS '卡流量日记录';
COMMENT ON COLUMN tb_card_daily_usage.card_id IS '卡ID可能是 iot_card_id 或 device_id';
COMMENT ON COLUMN tb_card_daily_usage.usage_date IS '日期';
COMMENT ON COLUMN tb_card_daily_usage.total_data_usage IS '上游返回的累计流量MB';
COMMENT ON COLUMN tb_card_daily_usage.carrier_id IS '运营商ID';