2076 lines
140 KiB
SQL
2076 lines
140 KiB
SQL
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||
|
||
|
||
-- 使用 utf8mb4 连接字符集,保证中文注释、中文名称和 emoji 在导入时不被降级。
|
||
CREATE DATABASE IF NOT EXISTS hyapp_wallet DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||
|
||
USE hyapp_wallet;
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_accounts (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
asset_type VARCHAR(32) NOT NULL COMMENT '钱包资产类型',
|
||
available_amount BIGINT NOT NULL COMMENT '可用数量',
|
||
frozen_amount BIGINT NOT NULL COMMENT '冻结数量',
|
||
version BIGINT NOT NULL COMMENT '版本号',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id, asset_type)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包账户余额表';
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_transactions (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
|
||
biz_type VARCHAR(64) NOT NULL COMMENT '业务类型',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
request_hash VARCHAR(128) NOT NULL COMMENT '请求哈希值',
|
||
external_ref VARCHAR(128) NOT NULL DEFAULT '' COMMENT '外部引用',
|
||
metadata_json JSON NULL COMMENT '扩展元数据 JSON',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, transaction_id),
|
||
UNIQUE KEY uk_wallet_tx_command (app_code, command_id),
|
||
KEY idx_wallet_tx_biz_time (app_code, biz_type, created_at_ms),
|
||
KEY idx_wallet_tx_biz_status_time (app_code, biz_type, status, created_at_ms),
|
||
KEY idx_wallet_tx_external_ref (app_code, external_ref)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包交易主表';
|
||
|
||
-- App 用户送礼榜历史应急查询会按 app_code/biz_type/status/created_at_ms 过滤;
|
||
-- 老索引缺 status 时会在 10GB 级 wallet_transactions 上读取大量失败/非成功交易再做 JSON 聚合。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_transactions' AND INDEX_NAME = 'idx_wallet_tx_biz_status_time') = 0,
|
||
'ALTER TABLE wallet_transactions ADD INDEX idx_wallet_tx_biz_status_time (app_code, biz_type, status, created_at_ms)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_entries (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
entry_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '流水 ID',
|
||
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
asset_type VARCHAR(32) NOT NULL COMMENT '钱包资产类型',
|
||
available_delta BIGINT NOT NULL COMMENT '可用变动',
|
||
frozen_delta BIGINT NOT NULL COMMENT '冻结变动',
|
||
available_after BIGINT NOT NULL COMMENT '可用后',
|
||
frozen_after BIGINT NOT NULL COMMENT '冻结后',
|
||
counterparty_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '交易对手用户 ID',
|
||
room_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '房间 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
KEY idx_wallet_entries_user_time (app_code, user_id, created_at_ms),
|
||
KEY idx_wallet_entries_tx (app_code, transaction_id),
|
||
KEY idx_wallet_entries_asset_time (app_code, asset_type, created_at_ms),
|
||
KEY idx_wallet_entries_asset_user_time (app_code, asset_type, user_id, created_at_ms, entry_id),
|
||
KEY idx_wallet_entries_asset_counterparty_time (app_code, asset_type, counterparty_user_id, created_at_ms, entry_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包复式流水表';
|
||
|
||
-- 金币流水和统计回放会按 app/asset/user/time 顺序读取钱包分录;
|
||
-- 老索引只能按 asset/time 或 user/time 命中,百万级 COIN 分录回放时会退化成大范围扫描和排序。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_entries' AND INDEX_NAME = 'idx_wallet_entries_asset_user_time') = 0,
|
||
'ALTER TABLE wallet_entries ADD INDEX idx_wallet_entries_asset_user_time (app_code, asset_type, user_id, created_at_ms, entry_id)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 工资转币商查询从币商侧分录反查来源工资用户;老表缺对手用户组合索引时,
|
||
-- source_user 关键词会在 COIN_SELLER_COIN 分录中做大范围过滤。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_entries' AND INDEX_NAME = 'idx_wallet_entries_asset_counterparty_time') = 0,
|
||
'ALTER TABLE wallet_entries ADD INDEX idx_wallet_entries_asset_counterparty_time (app_code, asset_type, counterparty_user_id, created_at_ms, entry_id)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_outbox (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
|
||
event_type VARCHAR(64) NOT NULL COMMENT '事件类型',
|
||
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
asset_type VARCHAR(32) NOT NULL COMMENT '钱包资产类型',
|
||
available_delta BIGINT NOT NULL COMMENT '可用变动',
|
||
frozen_delta BIGINT NOT NULL COMMENT '冻结变动',
|
||
payload JSON NOT NULL COMMENT '业务负载快照',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
worker_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'MQ 投递 worker ID',
|
||
lock_until_ms BIGINT NULL COMMENT 'MQ 投递锁过期时间,UTC epoch ms',
|
||
retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数',
|
||
next_retry_at_ms BIGINT NULL COMMENT '下一次 MQ 投递重试时间,UTC epoch ms',
|
||
last_error TEXT NULL COMMENT '最后一次失败原因',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, event_id),
|
||
KEY idx_wallet_outbox_pending (app_code, status, next_retry_at_ms, created_at_ms, event_id),
|
||
KEY idx_wallet_outbox_claim (app_code, status, lock_until_ms, created_at_ms, event_id),
|
||
KEY idx_wallet_outbox_event_pending (app_code, status, event_type, next_retry_at_ms, created_at_ms, event_id),
|
||
KEY idx_wallet_outbox_event_claim (app_code, status, event_type, lock_until_ms, created_at_ms, event_id),
|
||
KEY idx_wallet_outbox_retention (app_code, status, updated_at_ms, event_id),
|
||
KEY idx_wallet_outbox_event_created (app_code, event_type, created_at_ms, event_id),
|
||
KEY idx_wallet_outbox_asset_event_created (app_code, asset_type, event_type, created_at_ms, event_id),
|
||
KEY idx_wallet_outbox_tx (app_code, transaction_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包事件 outbox 表';
|
||
|
||
-- 钱包运行侧收益政策实例:由 admin-server 发布写入,wallet 送礼、提现和结算只读本库运行快照。
|
||
CREATE TABLE IF NOT EXISTS wallet_policy_instances (
|
||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码',
|
||
instance_code VARCHAR(96) NOT NULL COMMENT '后台策略实例编码',
|
||
template_code VARCHAR(96) NOT NULL COMMENT '模板编码快照',
|
||
template_version VARCHAR(64) NOT NULL COMMENT '模板版本快照',
|
||
region_id BIGINT NOT NULL DEFAULT 0 COMMENT '适用地区,0 表示 App 兜底',
|
||
status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT 'active/disabled',
|
||
effective_from_ms BIGINT NOT NULL DEFAULT 0 COMMENT 'UTC epoch ms',
|
||
effective_to_ms BIGINT NOT NULL DEFAULT 0 COMMENT '0 表示长期有效',
|
||
host_point_asset_type VARCHAR(32) NOT NULL DEFAULT 'POINT' COMMENT '主播收益积分资产',
|
||
host_point_ratio_ppm BIGINT NOT NULL DEFAULT 700000 COMMENT '有效付费礼物转 POINT 比例,ppm',
|
||
points_per_usd BIGINT NOT NULL DEFAULT 100000 COMMENT 'POINT/USD 展示换算比例',
|
||
withdraw_fee_bps INT NOT NULL DEFAULT 500 COMMENT '提现手续费 bps',
|
||
rule_json JSON NOT NULL COMMENT '完整政策快照',
|
||
published_by_admin_id BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
||
published_at_ms BIGINT NOT NULL DEFAULT 0,
|
||
created_at_ms BIGINT NOT NULL,
|
||
updated_at_ms BIGINT NOT NULL,
|
||
PRIMARY KEY (app_code, instance_code, region_id),
|
||
KEY idx_wallet_policy_active (app_code, region_id, status, effective_from_ms, effective_to_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包运行侧收益政策实例表';
|
||
|
||
-- 主播工资周期钻石账户:只记录政策结算用累计值,不作为用户可消费或可提现的钱包资产。
|
||
-- cycle_key 当前固定为 UTC yyyy-MM;后续日结/半月结不清空该账户,月末清算任务按策略处理。
|
||
CREATE TABLE IF NOT EXISTS host_period_diamond_accounts (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '主播用户 ID',
|
||
cycle_key VARCHAR(16) NOT NULL COMMENT '工资周期键,UTC yyyy-MM',
|
||
region_id BIGINT NOT NULL COMMENT '主播身份所属区域 ID,用于匹配区域工资政策',
|
||
agency_owner_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '送礼入账时主播归属 Agency 的 owner 用户 ID,0 表示无代理收款人',
|
||
total_diamonds BIGINT NOT NULL DEFAULT 0 COMMENT '周期累计钻石',
|
||
gift_diamond_total BIGINT NOT NULL DEFAULT 0 COMMENT '送礼产生的周期钻石累计',
|
||
version BIGINT NOT NULL DEFAULT 1 COMMENT '版本号',
|
||
first_gift_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '本周期首次收礼时间,UTC epoch ms',
|
||
last_gift_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '本周期最后收礼时间,UTC epoch ms',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id, cycle_key),
|
||
KEY idx_host_period_diamond_region_cycle (app_code, region_id, cycle_key),
|
||
KEY idx_host_period_diamond_cycle_total (app_code, cycle_key, total_diamonds),
|
||
KEY idx_host_period_diamond_cycle_owner (app_code, cycle_key, agency_owner_user_id, total_diamonds)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播工资周期钻石账户表';
|
||
|
||
-- 经理中心团队工资统计按 (cycle_key, agency_owner_user_id) 圈定团队主播;
|
||
-- 存量环境缺该索引时聚合会退化为整周期扫描,这里幂等补建。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'host_period_diamond_accounts' AND INDEX_NAME = 'idx_host_period_diamond_cycle_owner') = 0,
|
||
'ALTER TABLE host_period_diamond_accounts ADD INDEX idx_host_period_diamond_cycle_owner (app_code, cycle_key, agency_owner_user_id, total_diamonds)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 主播工资周期钻石流水:每笔成功送礼只在 target 为 active host 时写入,用于审计和补偿重建周期账户。
|
||
CREATE TABLE IF NOT EXISTS host_period_diamond_entries (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
entry_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '流水 ID',
|
||
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
|
||
user_id BIGINT NOT NULL COMMENT '主播用户 ID',
|
||
cycle_key VARCHAR(16) NOT NULL COMMENT '工资周期键,UTC yyyy-MM',
|
||
region_id BIGINT NOT NULL COMMENT '主播身份所属区域 ID',
|
||
agency_owner_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '本次送礼入账使用的代理收款用户快照',
|
||
diamond_delta BIGINT NOT NULL COMMENT '本次增加钻石',
|
||
diamond_after BIGINT NOT NULL COMMENT '本次入账后周期累计钻石',
|
||
gift_charge_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '礼物扣费资产类型快照',
|
||
gift_charge_amount BIGINT NOT NULL DEFAULT 0 COMMENT '礼物扣费金额快照',
|
||
gift_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '礼物 ID',
|
||
gift_count INT NOT NULL DEFAULT 0 COMMENT '礼物数量',
|
||
sender_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '送礼用户 ID',
|
||
room_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '房间 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
UNIQUE KEY uk_host_period_diamond_tx (app_code, transaction_id, user_id, cycle_key),
|
||
KEY idx_host_period_diamond_entries_user_cycle (app_code, user_id, cycle_key, created_at_ms),
|
||
KEY idx_host_period_diamond_entries_region_cycle (app_code, region_id, cycle_key, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播工资周期钻石流水表';
|
||
|
||
-- 运行侧工资政策表:字段与 admin_host_agency_salary_policies 对齐,wallet-service 结算只读取这里的已发布快照。
|
||
-- 后台配置仍由 admin-server 管理;同步/导入时必须整份写入 policy + levels,结算事务不直接读 admin 库。
|
||
CREATE TABLE IF NOT EXISTS host_agency_salary_policies (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
policy_id BIGINT UNSIGNED NOT NULL COMMENT '工资政策 ID,来自后台配置',
|
||
name VARCHAR(120) NOT NULL DEFAULT '' COMMENT '政策名称',
|
||
region_id BIGINT NOT NULL COMMENT '适用区域 ID',
|
||
status VARCHAR(24) NOT NULL DEFAULT 'disabled' COMMENT '状态:active/disabled',
|
||
settlement_mode VARCHAR(24) NOT NULL DEFAULT 'daily' COMMENT '结算方式:daily/half_month',
|
||
settlement_trigger_mode VARCHAR(24) NOT NULL DEFAULT 'automatic' COMMENT '结算触发方式:automatic/manual',
|
||
gift_coin_to_diamond_ratio DECIMAL(18,6) NOT NULL DEFAULT 1.000000 COMMENT '礼物金币转主播钻石比例快照',
|
||
residual_diamond_to_usd_rate DECIMAL(24,12) NOT NULL DEFAULT 0.000000000000 COMMENT '月底剩余钻石转美元比例',
|
||
effective_from_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效开始时间,UTC epoch ms',
|
||
effective_to_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效结束时间,0 表示长期有效',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, policy_id),
|
||
KEY idx_host_agency_salary_policy_active (app_code, region_id, status, settlement_mode, settlement_trigger_mode, effective_from_ms, effective_to_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播代理工资政策运行快照表';
|
||
|
||
CREATE TABLE IF NOT EXISTS host_agency_salary_policy_levels (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
policy_id BIGINT UNSIGNED NOT NULL COMMENT '工资政策 ID',
|
||
level_no INT NOT NULL COMMENT '等级',
|
||
required_diamonds BIGINT NOT NULL COMMENT '达到该等级所需主播当月钻石',
|
||
host_salary_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '主播累计美元工资,单位美分',
|
||
host_coin_reward BIGINT NOT NULL DEFAULT 0 COMMENT '主播累计金币奖励',
|
||
agency_salary_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '代理累计美元工资,单位美分',
|
||
status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT '等级状态:active/disabled',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, policy_id, level_no),
|
||
KEY idx_host_agency_salary_policy_level_required (app_code, policy_id, status, required_diamonds)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播代理工资政策等级运行快照表';
|
||
|
||
-- 结算进度按主播+月份独立记录累计已发值;日结/半月结只更新累计,月底清算只打 cleared 标记。
|
||
-- 这里不覆盖 host_period_diamond_accounts.total_diamonds,历史累计钻石必须可审计和可重放。
|
||
CREATE TABLE IF NOT EXISTS host_salary_settlement_progress (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '主播用户 ID',
|
||
cycle_key VARCHAR(16) NOT NULL COMMENT '工资周期键,UTC yyyy-MM',
|
||
settled_level_no INT NOT NULL DEFAULT 0 COMMENT '已结算到的最高等级',
|
||
settled_host_salary_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '已发主播美元工资累计,单位美分',
|
||
settled_host_coin_reward BIGINT NOT NULL DEFAULT 0 COMMENT '已发主播金币奖励累计',
|
||
settled_agency_salary_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '已发代理美元工资累计,单位美分',
|
||
last_settled_total_diamonds BIGINT NOT NULL DEFAULT 0 COMMENT '上次结算任务已处理到的周期累计钻石,避免未升档时重复空跑',
|
||
residual_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '月底剩余钻石已转主播美元金额,单位美分',
|
||
month_end_cleared_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '月底清算完成时间,0 表示未清算',
|
||
last_policy_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后一次使用的政策 ID',
|
||
version BIGINT NOT NULL DEFAULT 1 COMMENT '版本号',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id, cycle_key),
|
||
KEY idx_host_salary_settlement_progress_cycle (app_code, cycle_key, month_end_cleared_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播工资周期结算进度表';
|
||
|
||
CREATE TABLE IF NOT EXISTS host_salary_settlement_records (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
settlement_id VARCHAR(128) NOT NULL COMMENT '结算记录 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '钱包交易幂等命令 ID',
|
||
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
settlement_type VARCHAR(24) NOT NULL COMMENT '结算类型:daily/half_month/month_end',
|
||
trigger_mode VARCHAR(24) NOT NULL DEFAULT 'automatic' COMMENT '触发方式:automatic/manual',
|
||
settlement_role VARCHAR(24) NOT NULL DEFAULT 'all' COMMENT '结算身份:all/host/agency',
|
||
user_id BIGINT NOT NULL COMMENT '主播用户 ID',
|
||
agency_owner_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '代理收款用户 ID',
|
||
cycle_key VARCHAR(16) NOT NULL COMMENT '工资周期键,UTC yyyy-MM',
|
||
policy_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用的政策 ID',
|
||
level_no INT NOT NULL DEFAULT 0 COMMENT '本次结算后的等级',
|
||
total_diamonds BIGINT NOT NULL DEFAULT 0 COMMENT '结算时周期累计钻石',
|
||
host_salary_usd_minor_delta BIGINT NOT NULL DEFAULT 0 COMMENT '本次主播美元工资增量,单位美分',
|
||
host_coin_reward_delta BIGINT NOT NULL DEFAULT 0 COMMENT '本次主播金币奖励增量',
|
||
agency_salary_usd_minor_delta BIGINT NOT NULL DEFAULT 0 COMMENT '本次代理美元工资增量,单位美分',
|
||
residual_usd_minor_delta BIGINT NOT NULL DEFAULT 0 COMMENT '本次月底剩余钻石转美元增量,单位美分',
|
||
status VARCHAR(24) NOT NULL DEFAULT 'succeeded' COMMENT '状态:succeeded/skipped/failed',
|
||
reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '跳过或失败原因',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, settlement_id),
|
||
UNIQUE KEY uk_host_salary_settlement_command (app_code, command_id),
|
||
KEY idx_host_salary_settlement_user_cycle (app_code, user_id, cycle_key, created_at_ms),
|
||
KEY idx_host_salary_settlement_agency_cycle (app_code, agency_owner_user_id, cycle_key, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主播代理工资结算记录表';
|
||
|
||
CREATE TABLE IF NOT EXISTS team_salary_settlement_progress (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
policy_type VARCHAR(24) NOT NULL COMMENT '团队工资类型:bd/admin',
|
||
user_id BIGINT NOT NULL COMMENT '收款用户 ID:BD 或 Admin',
|
||
cycle_key VARCHAR(16) NOT NULL COMMENT '工资周期键,UTC yyyy-MM',
|
||
region_id BIGINT NOT NULL COMMENT '结算时使用的区域 ID',
|
||
settled_level_no INT NOT NULL DEFAULT 0 COMMENT '已结算到的最高等级',
|
||
settled_salary_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '已发团队工资累计,单位美分',
|
||
last_settled_income_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '上次已处理收入累计,单位美分,用于避免未升档重复空跑',
|
||
last_policy_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '最后一次使用的政策 ID',
|
||
month_closed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '完整月结算关闭时间,0 表示未关闭',
|
||
version BIGINT NOT NULL DEFAULT 1 COMMENT '版本号',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, policy_type, user_id, cycle_key),
|
||
KEY idx_team_salary_progress_cycle (app_code, policy_type, cycle_key, region_id, month_closed_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='BD/Admin 工资周期结算进度表';
|
||
|
||
CREATE TABLE IF NOT EXISTS team_salary_settlement_records (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
settlement_id VARCHAR(128) NOT NULL COMMENT '结算记录 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '钱包交易幂等命令 ID',
|
||
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
policy_type VARCHAR(24) NOT NULL COMMENT '团队工资类型:bd/admin',
|
||
trigger_mode VARCHAR(24) NOT NULL DEFAULT 'manual' COMMENT '触发方式:automatic/manual',
|
||
user_id BIGINT NOT NULL COMMENT '收款用户 ID:BD 或 Admin',
|
||
cycle_key VARCHAR(16) NOT NULL COMMENT '工资周期键,UTC yyyy-MM',
|
||
region_id BIGINT NOT NULL COMMENT '结算时使用的区域 ID',
|
||
policy_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '使用的政策 ID',
|
||
level_no INT NOT NULL DEFAULT 0 COMMENT '本次结算后的等级',
|
||
income_usd_minor BIGINT NOT NULL DEFAULT 0 COMMENT '结算时团队收入累计,单位美分',
|
||
salary_usd_minor_delta BIGINT NOT NULL DEFAULT 0 COMMENT '本次团队美元工资增量,单位美分',
|
||
status VARCHAR(24) NOT NULL DEFAULT 'succeeded' COMMENT '状态:succeeded/skipped/failed',
|
||
reason VARCHAR(255) NOT NULL DEFAULT '' COMMENT '跳过或失败原因',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, settlement_id),
|
||
UNIQUE KEY uk_team_salary_settlement_command (app_code, command_id),
|
||
KEY idx_team_salary_records_user_cycle (app_code, policy_type, user_id, cycle_key, created_at_ms),
|
||
KEY idx_team_salary_records_cycle (app_code, policy_type, cycle_key, region_id, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='BD/Admin 工资结算记录表';
|
||
|
||
-- 老环境已建过主播周期账户时,CREATE TABLE IF NOT EXISTS 不会补新字段;结算前必须有代理收款快照。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'host_period_diamond_accounts' AND COLUMN_NAME = 'agency_owner_user_id') = 0,
|
||
'ALTER TABLE host_period_diamond_accounts ADD COLUMN agency_owner_user_id BIGINT NOT NULL DEFAULT 0 COMMENT ''送礼入账时主播归属 Agency 的 owner 用户 ID,0 表示无代理收款人'' AFTER region_id',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'host_period_diamond_entries' AND COLUMN_NAME = 'agency_owner_user_id') = 0,
|
||
'ALTER TABLE host_period_diamond_entries ADD COLUMN agency_owner_user_id BIGINT NOT NULL DEFAULT 0 COMMENT ''本次送礼入账使用的代理收款用户快照'' AFTER region_id',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'host_agency_salary_policies' AND COLUMN_NAME = 'settlement_trigger_mode') = 0,
|
||
'ALTER TABLE host_agency_salary_policies ADD COLUMN settlement_trigger_mode VARCHAR(24) NOT NULL DEFAULT ''automatic'' COMMENT ''结算触发方式:automatic/manual'' AFTER settlement_mode',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'host_salary_settlement_progress' AND COLUMN_NAME = 'last_settled_total_diamonds') = 0,
|
||
'ALTER TABLE host_salary_settlement_progress ADD COLUMN last_settled_total_diamonds BIGINT NOT NULL DEFAULT 0 COMMENT ''上次结算任务已处理到的周期累计钻石,避免未升档时重复空跑'' AFTER settled_agency_salary_usd_minor',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'host_salary_settlement_records' AND COLUMN_NAME = 'trigger_mode') = 0,
|
||
'ALTER TABLE host_salary_settlement_records ADD COLUMN trigger_mode VARCHAR(24) NOT NULL DEFAULT ''automatic'' COMMENT ''触发方式:automatic/manual'' AFTER settlement_type',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'host_salary_settlement_records' AND COLUMN_NAME = 'settlement_role') = 0,
|
||
'ALTER TABLE host_salary_settlement_records ADD COLUMN settlement_role VARCHAR(24) NOT NULL DEFAULT ''all'' COMMENT ''结算身份:all/host/agency'' AFTER trigger_mode',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 老环境可能已经存在 wallet_outbox,CREATE TABLE IF NOT EXISTS 不会补齐后续新增的投递锁字段。
|
||
-- 这里用 information_schema 生成幂等 ALTER,保证重复执行 initdb 时不会因重复列名失败。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND COLUMN_NAME = 'worker_id') = 0,
|
||
'ALTER TABLE wallet_outbox ADD COLUMN worker_id VARCHAR(128) NOT NULL DEFAULT '''' COMMENT ''MQ 投递 worker ID'' AFTER status',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 投递锁过期时间用于多实例 claim outbox,老库缺这个列时会导致 worker 查询直接 1054。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND COLUMN_NAME = 'lock_until_ms') = 0,
|
||
'ALTER TABLE wallet_outbox ADD COLUMN lock_until_ms BIGINT NULL COMMENT ''MQ 投递锁过期时间,UTC epoch ms'' AFTER worker_id',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 下一次重试时间让失败 outbox 可延迟重投;老库缺列时待投递扫描会直接失败。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND COLUMN_NAME = 'next_retry_at_ms') = 0,
|
||
'ALTER TABLE wallet_outbox ADD COLUMN next_retry_at_ms BIGINT NULL COMMENT ''下一次 MQ 投递重试时间,UTC epoch ms'' AFTER retry_count',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- pending 索引的列顺序跟 outbox 扫描条件绑定;为兼容历史索引,存在就先删除再按当前结构重建。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND INDEX_NAME = 'idx_wallet_outbox_pending') > 0,
|
||
'ALTER TABLE wallet_outbox DROP INDEX idx_wallet_outbox_pending',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := 'ALTER TABLE wallet_outbox ADD INDEX idx_wallet_outbox_pending (app_code, status, next_retry_at_ms, created_at_ms, event_id)';
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- claim 索引用于查找锁过期的消息;列顺序也跟查询条件绑定,存在旧结构时重建。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND INDEX_NAME = 'idx_wallet_outbox_claim') > 0,
|
||
'ALTER TABLE wallet_outbox DROP INDEX idx_wallet_outbox_claim',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := 'ALTER TABLE wallet_outbox ADD INDEX idx_wallet_outbox_claim (app_code, status, lock_until_ms, created_at_ms, event_id)';
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 实时红包/房间 UI 事件按 event_type 独立 claim;缺这个索引会在通用账务 backlog 上扫描,仍然可能延迟弹窗。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND INDEX_NAME = 'idx_wallet_outbox_event_pending') = 0,
|
||
'ALTER TABLE wallet_outbox ADD INDEX idx_wallet_outbox_event_pending (app_code, status, event_type, next_retry_at_ms, created_at_ms, event_id)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND INDEX_NAME = 'idx_wallet_outbox_event_claim') = 0,
|
||
'ALTER TABLE wallet_outbox ADD INDEX idx_wallet_outbox_event_claim (app_code, status, event_type, lock_until_ms, created_at_ms, event_id)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND INDEX_NAME = 'idx_wallet_outbox_retention') = 0,
|
||
'ALTER TABLE wallet_outbox ADD INDEX idx_wallet_outbox_retention (app_code, status, updated_at_ms, event_id)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- projection worker 只扫描单租户、单事件类型的 wallet_outbox;缺少该索引会退化成百万级全表扫描。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND INDEX_NAME = 'idx_wallet_outbox_event_created') = 0,
|
||
'ALTER TABLE wallet_outbox ADD INDEX idx_wallet_outbox_event_created (app_code, event_type, created_at_ms, event_id)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_outbox' AND INDEX_NAME = 'idx_wallet_outbox_asset_event_created') = 0,
|
||
'ALTER TABLE wallet_outbox ADD INDEX idx_wallet_outbox_asset_event_created (app_code, asset_type, event_type, created_at_ms, event_id)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_gift_prices (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID',
|
||
price_version VARCHAR(64) NOT NULL COMMENT '价格版本',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
charge_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '扣费资产类型',
|
||
coin_price BIGINT NOT NULL COMMENT '金币价格',
|
||
gift_point_amount BIGINT NOT NULL COMMENT '历史字段:GIFT_POINT 已下线,新写入固定 0',
|
||
heat_value BIGINT NOT NULL COMMENT '热度值',
|
||
effective_at_ms BIGINT NOT NULL COMMENT '生效时间,UTC epoch ms',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, gift_id, price_version),
|
||
KEY idx_wallet_gift_prices_effective (app_code, gift_id, status, effective_at_ms),
|
||
KEY idx_wallet_gift_prices_updated (app_code, updated_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包礼物价格表';
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_recharge_policies (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
policy_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '策略 ID',
|
||
region_id BIGINT NOT NULL COMMENT '区域 ID',
|
||
policy_version VARCHAR(64) NOT NULL COMMENT '策略版本',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
currency_code VARCHAR(3) NOT NULL DEFAULT 'USD' COMMENT '币种编码',
|
||
coin_amount BIGINT NOT NULL COMMENT '金币数量',
|
||
usd_minor_amount BIGINT NOT NULL COMMENT '美元最小单位数量',
|
||
effective_from_ms BIGINT NOT NULL COMMENT '生效开始时间,UTC epoch ms',
|
||
effective_to_ms BIGINT NULL COMMENT '生效结束时间,UTC epoch ms',
|
||
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
KEY idx_wallet_recharge_policies_active (app_code, region_id, status, effective_from_ms),
|
||
UNIQUE KEY uk_wallet_recharge_policy_version (app_code, region_id, policy_version)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包充值策略表';
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_recharge_records (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
recharge_sequence BIGINT NOT NULL DEFAULT 0 COMMENT '该用户成功充值序号,从 1 开始',
|
||
seller_user_id BIGINT NOT NULL COMMENT '商户用户 ID',
|
||
seller_region_id BIGINT NOT NULL COMMENT '商户区域 ID',
|
||
target_region_id BIGINT NOT NULL COMMENT '目标区域 ID',
|
||
policy_id BIGINT NOT NULL COMMENT '策略 ID',
|
||
policy_version VARCHAR(64) NOT NULL COMMENT '策略版本',
|
||
currency_code VARCHAR(8) NOT NULL COMMENT '币种编码',
|
||
coin_amount BIGINT NOT NULL COMMENT '金币数量',
|
||
usd_minor_amount BIGINT NOT NULL COMMENT '美元最小单位数量',
|
||
exchange_coin_amount BIGINT NOT NULL COMMENT '兑换金币数量',
|
||
exchange_usd_minor_amount BIGINT NOT NULL COMMENT '兑换美元最小单位数量',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, transaction_id),
|
||
KEY idx_wallet_recharge_records_user_time (app_code, user_id, created_at_ms),
|
||
KEY idx_wallet_recharge_records_seller_time (app_code, seller_user_id, created_at_ms),
|
||
KEY idx_wallet_recharge_records_region_time (app_code, target_region_id, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包充值记录表';
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_user_recharge_stats (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
recharge_count BIGINT NOT NULL DEFAULT 0 COMMENT '成功充值次数',
|
||
first_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '首笔充值交易 ID',
|
||
first_recharged_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '首笔充值时间,UTC epoch ms',
|
||
total_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '累计充值金币',
|
||
total_usd_minor_amount BIGINT NOT NULL DEFAULT 0 COMMENT '累计充值美元最小单位金额',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户充值统计表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_recharge_records' AND COLUMN_NAME = 'recharge_sequence') = 0,
|
||
'ALTER TABLE wallet_recharge_records ADD COLUMN recharge_sequence BIGINT NOT NULL DEFAULT 0 COMMENT ''该用户成功充值序号,从 1 开始'' AFTER user_id',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_recharge_products (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
product_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '商品 ID',
|
||
product_code VARCHAR(128) NULL COMMENT '商品编码',
|
||
product_name VARCHAR(128) NOT NULL COMMENT '商品名称',
|
||
description VARCHAR(512) NOT NULL DEFAULT '' COMMENT '描述信息',
|
||
audience_type VARCHAR(32) NOT NULL DEFAULT 'normal' COMMENT '购买对象:normal 普通用户,coin_seller 币商',
|
||
platform VARCHAR(16) NOT NULL COMMENT '平台',
|
||
channel VARCHAR(32) NOT NULL COMMENT '渠道',
|
||
currency_code VARCHAR(8) NOT NULL DEFAULT 'USDT' COMMENT '币种编码',
|
||
amount_micro BIGINT NOT NULL COMMENT '微单位金额',
|
||
coin_amount BIGINT NOT NULL COMMENT '金币数量',
|
||
resource_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '资源资产类型',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
app_visible BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否在 App 普通充值列表展示;不影响 Google Play 验单',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
created_by_user_id BIGINT NULL COMMENT '创建人用户 ID',
|
||
updated_by_user_id BIGINT NULL COMMENT '更新人用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_wallet_recharge_products_code (app_code, product_code),
|
||
KEY idx_wallet_recharge_products_scope (app_code, platform, audience_type, status, app_visible, amount_micro, product_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包充值商品表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_recharge_products' AND COLUMN_NAME = 'audience_type') = 0,
|
||
'ALTER TABLE wallet_recharge_products ADD COLUMN audience_type VARCHAR(32) NOT NULL DEFAULT ''normal'' COMMENT ''购买对象:normal 普通用户,coin_seller 币商'' AFTER description',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_recharge_products' AND COLUMN_NAME = 'app_visible') = 0,
|
||
'ALTER TABLE wallet_recharge_products ADD COLUMN app_visible BOOLEAN NOT NULL DEFAULT TRUE COMMENT ''是否在 App 普通充值列表展示;不影响 Google Play 验单'' AFTER status',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_recharge_product_regions (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
product_id BIGINT NOT NULL COMMENT '商品 ID',
|
||
region_id BIGINT NOT NULL COMMENT '区域 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, product_id, region_id),
|
||
KEY idx_wallet_recharge_product_regions_region (app_code, region_id, product_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包充值商品区域表';
|
||
|
||
CREATE TABLE IF NOT EXISTS third_party_payment_channels (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
provider_code VARCHAR(32) NOT NULL COMMENT '三方支付渠道编码',
|
||
provider_name VARCHAR(64) NOT NULL COMMENT '三方支付渠道名称',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '渠道状态',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, provider_code),
|
||
KEY idx_third_party_payment_channels_status (app_code, status, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='三方支付渠道表';
|
||
|
||
CREATE TABLE IF NOT EXISTS third_party_payment_methods (
|
||
method_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '支付方式 ID',
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
provider_code VARCHAR(32) NOT NULL COMMENT '三方支付渠道编码',
|
||
country_code VARCHAR(8) NOT NULL COMMENT '国家码,GLOBAL 表示全球方式',
|
||
country_name VARCHAR(64) NOT NULL DEFAULT '' COMMENT '国家名称',
|
||
currency_code VARCHAR(8) NOT NULL COMMENT '下单币种',
|
||
pay_way VARCHAR(64) NOT NULL COMMENT 'MiFaPay payWay',
|
||
pay_type VARCHAR(64) NOT NULL COMMENT 'MiFaPay payType',
|
||
method_name VARCHAR(128) NOT NULL COMMENT '支付方式名称',
|
||
logo_url VARCHAR(1024) NOT NULL DEFAULT '' COMMENT '支付方式图标',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '方式状态',
|
||
usd_to_currency_rate DECIMAL(20,8) NOT NULL DEFAULT 1 COMMENT 'USD 到支付币种汇率',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_third_party_payment_methods_scope (app_code, provider_code, country_code, pay_way, pay_type),
|
||
KEY idx_third_party_payment_methods_h5 (app_code, provider_code, country_code, status, sort_order),
|
||
CONSTRAINT fk_third_party_payment_methods_channel FOREIGN KEY (app_code, provider_code) REFERENCES third_party_payment_channels(app_code, provider_code)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='三方支付国家方式配置表';
|
||
|
||
CREATE TABLE IF NOT EXISTS external_recharge_orders (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
order_id VARCHAR(96) NOT NULL COMMENT '外部充值订单号',
|
||
command_id VARCHAR(128) NOT NULL COMMENT 'H5 幂等命令 ID',
|
||
target_user_id BIGINT NOT NULL COMMENT '目标用户 ID',
|
||
target_region_id BIGINT NOT NULL COMMENT '目标区域 ID',
|
||
target_country_id BIGINT NOT NULL DEFAULT 0 COMMENT '目标国家 ID',
|
||
target_country_code VARCHAR(8) NOT NULL DEFAULT '' COMMENT '目标国家码',
|
||
audience_type VARCHAR(32) NOT NULL COMMENT '购买对象',
|
||
product_id BIGINT NOT NULL COMMENT '商品 ID',
|
||
product_code VARCHAR(128) NOT NULL COMMENT '商品编码快照',
|
||
product_name VARCHAR(128) NOT NULL COMMENT '商品名称快照',
|
||
coin_amount BIGINT NOT NULL COMMENT '到账金币数量',
|
||
usd_minor_amount BIGINT NOT NULL COMMENT 'USD cent 金额快照',
|
||
provider_code VARCHAR(32) NOT NULL COMMENT '支付渠道',
|
||
payment_method_id BIGINT NOT NULL DEFAULT 0 COMMENT '三方支付方式 ID',
|
||
country_code VARCHAR(8) NOT NULL DEFAULT '' COMMENT '支付方式国家码',
|
||
currency_code VARCHAR(8) NOT NULL DEFAULT '' COMMENT '支付币种',
|
||
provider_amount_minor BIGINT NOT NULL DEFAULT 0 COMMENT '三方支付币种最小单位金额',
|
||
pay_way VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'MiFaPay payWay',
|
||
pay_type VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'MiFaPay payType',
|
||
pay_url VARCHAR(2048) NOT NULL DEFAULT '' COMMENT '三方支付跳转 URL',
|
||
provider_order_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT '三方支付订单号',
|
||
tx_hash VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'USDT tx hash',
|
||
receive_address VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'USDT 收款地址',
|
||
status VARCHAR(32) NOT NULL COMMENT '订单状态',
|
||
failure_reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '失败原因',
|
||
wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
|
||
provider_payload JSON NULL COMMENT '下单、回调或链上校验原始数据',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, order_id),
|
||
UNIQUE KEY uk_external_recharge_orders_command (app_code, command_id),
|
||
KEY idx_external_recharge_orders_user_time (app_code, target_user_id, created_at_ms),
|
||
KEY idx_external_recharge_orders_provider_order (app_code, provider_code, provider_order_id),
|
||
KEY idx_external_recharge_orders_reconcile (app_code, status, provider_code, updated_at_ms, created_at_ms),
|
||
KEY idx_external_recharge_orders_wallet_tx (app_code, wallet_transaction_id),
|
||
KEY idx_external_recharge_orders_tx (app_code, provider_code, tx_hash)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='H5 外部充值订单表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'external_recharge_orders' AND COLUMN_NAME = 'target_country_id') = 0,
|
||
'ALTER TABLE external_recharge_orders ADD COLUMN target_country_id BIGINT NOT NULL DEFAULT 0 COMMENT ''目标国家 ID'' AFTER target_region_id',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @now_ms = CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED);
|
||
|
||
INSERT IGNORE INTO third_party_payment_channels (app_code, provider_code, provider_name, status, sort_order, created_at_ms, updated_at_ms)
|
||
VALUES ('lalu', 'mifapay', 'MiFaPay', 'active', 10, @now_ms, @now_ms);
|
||
|
||
-- MiFaPay 是 H5 统一三方支付入口;真实商户号、商户标识、商户私钥、平台公钥只放运行环境配置。
|
||
-- 国家和支付方式默认打开,运营可在后台逐项关闭;默认汇率为 1,避免新环境缺配置时 H5 完全不可见。
|
||
INSERT IGNORE INTO third_party_payment_methods (
|
||
app_code, provider_code, country_code, country_name, currency_code, pay_way, pay_type,
|
||
method_name, logo_url, status, usd_to_currency_rate, sort_order, created_at_ms, updated_at_ms
|
||
) VALUES
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'BCA', 'BCA Bank', '', 'active', 1, 110, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'BNI', 'BNI Bank', '', 'active', 1, 120, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'BRI', 'BRI Bank', '', 'active', 1, 130, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'Mandiri', 'Mandiri Bank', '', 'active', 1, 140, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'Permata', 'Permata Bank', '', 'active', 1, 150, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'Ewallet', 'DANA', 'DANA', '', 'active', 1, 160, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'Ewallet', 'LinkAja', 'LinkAja', '', 'active', 1, 170, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'Ewallet', 'OVO', 'OVO', '', 'active', 1, 180, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'Ewallet', 'ShopeePay', 'ShopeePay', '', 'active', 1, 190, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'ID', 'Indonesia', 'IDR', 'QR', 'QRIS', 'QRIS', '', 'active', 1, 200, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'VN', 'Vietnam', 'VND', 'BankTransfer', 'VN_BankTransfer', 'Vietnam Bank Transfer', '', 'active', 1, 210, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'VN', 'Vietnam', 'VND', 'QR', 'VietQR', 'VietQR', '', 'active', 1, 220, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'BH', 'Bahrain', 'BHD', 'Card', 'CreditCard', 'Bahrain Credit Card', '', 'active', 1, 310, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'QA', 'Qatar', 'QAR', 'Card', 'CreditCard', 'Qatar Credit Card', '', 'active', 1, 410, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'OM', 'Oman', 'OMR', 'Card', 'CreditCard', 'Oman Credit Card', '', 'active', 1, 510, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'AE', 'United Arab Emirates', 'AED', 'Card', 'CreditCard', 'UAE Credit Card', '', 'active', 1, 610, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'KW', 'Kuwait', 'KWD', 'Card', 'Knet', 'KNET', '', 'active', 1, 710, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'SA', 'Saudi Arabia', 'SAR', 'Card', 'MADA', 'MADA', '', 'active', 1, 810, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'SA', 'Saudi Arabia', 'SAR', 'Ewallet', 'ApplePay', 'ApplePay', '', 'active', 1, 820, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'SA', 'Saudi Arabia', 'SAR', 'Ewallet', 'STCPay', 'STCPay', '', 'active', 1, 830, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'IN', 'India', 'INR', 'Ewallet', 'BHIM', 'BHIM', '', 'active', 1, 910, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'IN', 'India', 'INR', 'Ewallet', 'GooglePay', 'GooglePay', '', 'active', 1, 920, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'IN', 'India', 'INR', 'Ewallet', 'Mobikwik', 'Mobikwik', '', 'active', 1, 930, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'IN', 'India', 'INR', 'Ewallet', 'Paytm', 'Paytm', '', 'active', 1, 940, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'IN', 'India', 'INR', 'Ewallet', 'PhonePe', 'PhonePe', '', 'active', 1, 950, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'IN', 'India', 'INR', 'Ewallet', 'UPI', 'UPI', '', 'active', 1, 960, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'BD', 'Bangladesh', 'BDT', 'Ewallet', 'bKash', 'bKash', '', 'active', 1, 1010, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'PK', 'Pakistan', 'PKR', 'Ewallet', 'Easypaisa', 'Easypaisa', '', 'active', 1, 1110, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'PK', 'Pakistan', 'PKR', 'Ewallet', 'JazzCash', 'JazzCash', '', 'active', 1, 1120, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'EG', 'Egypt', 'EGP', 'Ewallet', 'FawryPay', 'FawryPay', '', 'active', 1, 1210, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'EG', 'Egypt', 'EGP', 'Ewallet', 'Meeza', 'Meeza', '', 'active', 1, 1220, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'EG', 'Egypt', 'EGP', 'Ewallet', 'Orange', 'Orange', '', 'active', 1, 1230, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'EG', 'Egypt', 'EGP', 'Ewallet', 'Vodafone', 'Vodafone', '', 'active', 1, 1240, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'PH', 'Philippines', 'PHP', 'Ewallet', 'Gcash', 'GCash', '', 'active', 1, 1310, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'PH', 'Philippines', 'PHP', 'Ewallet', 'PayMaya', 'PayMaya', '', 'active', 1, 1320, @now_ms, @now_ms),
|
||
('lalu', 'mifapay', 'PH', 'Philippines', 'PHP', 'QR', 'QRPH', 'QRPH', '', 'active', 1, 1330, @now_ms, @now_ms);
|
||
|
||
INSERT IGNORE INTO third_party_payment_channels (app_code, provider_code, provider_name, status, sort_order, created_at_ms, updated_at_ms)
|
||
VALUES ('lalu', 'v5pay', 'V5Pay', 'active', 20, @now_ms, @now_ms);
|
||
|
||
-- V5Pay 的 pay_type 直接保存 productType;运行时还会按 V5Pay productTypes 接口过滤当前 appKey 真实可用的产品。
|
||
INSERT IGNORE INTO third_party_payment_methods (
|
||
app_code, provider_code, country_code, country_name, currency_code, pay_way, pay_type,
|
||
method_name, logo_url, status, usd_to_currency_rate, sort_order, created_at_ms, updated_at_ms
|
||
) VALUES
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'UB_ONLINE', 'UnionBank Online', '', 'active', 1, 2010, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'INSTAPAY', 'InstaPay', '', 'active', 1, 2020, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'PESONET', 'PESONet', '', 'active', 1, 2030, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'Ewallet', 'GCASH_ONLINE', 'GCash Online', '', 'active', 1, 2040, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'Ewallet', 'COINS_ONLINE', 'Coins.ph Online', '', 'active', 1, 2050, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'BPI_ONLINE', 'BPI Online', '', 'active', 1, 2060, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'RCBC_ONLINE', 'RCBC Online', '', 'active', 1, 2070, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'UCPB_ONLINE', 'UCPB Online', '', 'active', 1, 2080, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'ROBINSONSBANK_ONLINE', 'Robinsons Bank Online', '', 'active', 1, 2090, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'PSBANK_ONLINE', 'PSBank Online', '', 'active', 1, 2100, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'METROBANK_ONLINE', 'Metrobank Online', '', 'active', 1, 2110, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'LANDBANK_ONLINE', 'Landbank Online', '', 'active', 1, 2120, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'CHINABANK_ONLINE', 'China Bank Online', '', 'active', 1, 2130, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'BDO_ONLINE', 'BDO Online', '', 'active', 1, 2140, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'BankTransfer', 'BOC_ONLINE', 'Bank of Commerce Online', '', 'active', 1, 2150, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'Ewallet', 'GRABPAY_ONLINE', 'GrabPay Online', '', 'active', 1, 2160, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'QR', 'INSTAPAY_QR', 'InstaPay QR', '', 'active', 1, 2170, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'QR', 'ALIPAY_QR', 'Alipay QR', '', 'active', 1, 2180, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'Ewallet', 'ALIPAY_PLUS', 'Alipay+', '', 'active', 1, 2190, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'Billing', 'BILL', 'Bills Payment', '', 'active', 1, 2200, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PH', 'Philippines', 'PHP', 'QR', 'QRPH_GCASH', 'QRPh GCash', '', 'active', 1, 2210, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'SA', 'Saudi Arabia', 'SAR', 'Ewallet', 'STCPAY', 'STC Pay', '', 'active', 1, 2310, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'SA', 'Saudi Arabia', 'SAR', 'Card', 'MADA', 'MADA', '', 'active', 1, 2320, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'SA', 'Saudi Arabia', 'SAR', 'Ewallet', 'APPLEPAY', 'Apple Pay', '', 'active', 1, 2330, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'EG', 'Egypt', 'EGP', 'Card', 'CARD', 'Egypt Card', '', 'active', 1, 2410, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'AE', 'United Arab Emirates', 'AED', 'Card', 'CARD', 'UAE Card', '', 'active', 1, 2510, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'BNI_VA', 'BNI Virtual Account', '', 'active', 1, 2610, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'BRI_VA', 'BRI Virtual Account', '', 'active', 1, 2620, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'CIMB_VA', 'CIMB Virtual Account', '', 'active', 1, 2630, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'MANDIRI_VA', 'Mandiri Virtual Account', '', 'active', 1, 2640, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'MAYBANK_VA', 'Maybank Virtual Account', '', 'active', 1, 2650, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'QR', 'NOBU_BANK_QRIS', 'Nobu Bank QRIS', '', 'active', 1, 2660, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'Ewallet', 'OVO', 'OVO', '', 'active', 1, 2670, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'BankTransfer', 'PERMATA_VA', 'Permata Virtual Account', '', 'active', 1, 2680, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'Ewallet', 'SHOPEEPAY_JUMPAPP', 'ShopeePay Jump App', '', 'active', 1, 2690, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'Ewallet', 'GOPAY', 'GoPay', '', 'active', 1, 2700, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'ID', 'Indonesia', 'IDR', 'Ewallet', 'ALIPAY_CN_ALIPAYPLUS', 'Alipay+ Indonesia', '', 'active', 1, 2710, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'IN', 'India', 'INR', 'BankTransfer', 'BANK_ONLINE', 'Bank Online', '', 'active', 1, 2810, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'IN', 'India', 'INR', 'UPI', 'UPI', 'UPI', '', 'active', 1, 2820, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'IN', 'India', 'INR', 'BankTransfer', 'ONLINE_BANKING', 'Online Banking', '', 'active', 1, 2830, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PK', 'Pakistan', 'PKR', 'Ewallet', 'EASYPAISA', 'Easypaisa', '', 'active', 1, 2910, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PK', 'Pakistan', 'PKR', 'Ewallet', 'JAZZCASH', 'JazzCash', '', 'active', 1, 2920, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PK', 'Pakistan', 'PKR', 'BankTransfer', 'ALFA', 'Bank Alfalah', '', 'active', 1, 2930, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PK', 'Pakistan', 'PKR', 'Ewallet', 'HBL_KONNECT', 'HBL Konnect', '', 'active', 1, 2940, @now_ms, @now_ms),
|
||
('lalu', 'v5pay', 'PK', 'Pakistan', 'PKR', 'Billing', 'BILL_PK', 'Pakistan Bill Payment', '', 'active', 1, 2950, @now_ms, @now_ms);
|
||
|
||
-- MiFaPay logo 使用已上传 COS 的固定对象地址;仅覆盖空值、早期占位图和 Apifox 临时预览图,避免误改运营手工替换的正式图。
|
||
UPDATE third_party_payment_methods m
|
||
JOIN (
|
||
SELECT 'AE' AS country_code, 'Card' AS pay_way, 'CreditCard' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/ae/card-creditcard.png' AS logo_url
|
||
UNION ALL SELECT 'BD' AS country_code, 'Ewallet' AS pay_way, 'Nagad' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/bd/ewallet-nagad.png' AS logo_url
|
||
UNION ALL SELECT 'BD' AS country_code, 'Ewallet' AS pay_way, 'bKash' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/bd/ewallet-bkash.png' AS logo_url
|
||
UNION ALL SELECT 'BH' AS country_code, 'Card' AS pay_way, 'CreditCard' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/bh/card-creditcard.png' AS logo_url
|
||
UNION ALL SELECT 'EG' AS country_code, 'Card' AS pay_way, 'CreditCard' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/eg/card-creditcard.png' AS logo_url
|
||
UNION ALL SELECT 'EG' AS country_code, 'Ewallet' AS pay_way, 'FawryPay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/eg/ewallet-fawrypay.png' AS logo_url
|
||
UNION ALL SELECT 'EG' AS country_code, 'Ewallet' AS pay_way, 'Meeza' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/eg/ewallet-meeza.png' AS logo_url
|
||
UNION ALL SELECT 'EG' AS country_code, 'Ewallet' AS pay_way, 'Opay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/eg/ewallet-opay.png' AS logo_url
|
||
UNION ALL SELECT 'EG' AS country_code, 'Ewallet' AS pay_way, 'Orange' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/eg/ewallet-orange.png' AS logo_url
|
||
UNION ALL SELECT 'EG' AS country_code, 'Ewallet' AS pay_way, 'Vodafone' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/eg/ewallet-vodafone.png' AS logo_url
|
||
UNION ALL SELECT 'GLOBAL' AS country_code, 'BankTransfer' AS pay_way, 'UnionPay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/global/banktransfer-unionpay.png' AS logo_url
|
||
UNION ALL SELECT 'GLOBAL' AS country_code, 'Card' AS pay_way, 'CreditCard' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/global/card-creditcard.png' AS logo_url
|
||
UNION ALL SELECT 'GLOBAL' AS country_code, 'Ewallet' AS pay_way, 'ApplePay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/global/ewallet-applepay.png' AS logo_url
|
||
UNION ALL SELECT 'GLOBAL' AS country_code, 'Ewallet' AS pay_way, 'GooglePay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/global/ewallet-googlepay.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'BankTransfer' AS pay_way, 'BCA' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/banktransfer-bca.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'BankTransfer' AS pay_way, 'BNI' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/banktransfer-bni.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'BankTransfer' AS pay_way, 'BRI' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/banktransfer-bri.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'BankTransfer' AS pay_way, 'Mandiri' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/banktransfer-mandiri.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'BankTransfer' AS pay_way, 'Permata' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/banktransfer-permata.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'BankTransfer' AS pay_way, 'QRIS' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/banktransfer-qris.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'Ewallet' AS pay_way, 'DANA' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/ewallet-dana.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'Ewallet' AS pay_way, 'LinkAja' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/ewallet-linkaja.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'Ewallet' AS pay_way, 'OVO' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/ewallet-ovo.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'Ewallet' AS pay_way, 'ShopeePay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/ewallet-shopeepay.png' AS logo_url
|
||
UNION ALL SELECT 'ID' AS country_code, 'QR' AS pay_way, 'QRIS' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/id/qr-qris.png' AS logo_url
|
||
UNION ALL SELECT 'IN' AS country_code, 'Ewallet' AS pay_way, 'BHIM' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/in/ewallet-bhim.png' AS logo_url
|
||
UNION ALL SELECT 'IN' AS country_code, 'Ewallet' AS pay_way, 'GooglePay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/in/ewallet-googlepay.png' AS logo_url
|
||
UNION ALL SELECT 'IN' AS country_code, 'Ewallet' AS pay_way, 'Mobikwik' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/in/ewallet-mobikwik.png' AS logo_url
|
||
UNION ALL SELECT 'IN' AS country_code, 'Ewallet' AS pay_way, 'Paytm' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/in/ewallet-paytm.png' AS logo_url
|
||
UNION ALL SELECT 'IN' AS country_code, 'Ewallet' AS pay_way, 'PhonePe' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/in/ewallet-phonepe.png' AS logo_url
|
||
UNION ALL SELECT 'IN' AS country_code, 'Ewallet' AS pay_way, 'UPI' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/in/ewallet-upi.png' AS logo_url
|
||
UNION ALL SELECT 'KW' AS country_code, 'Card' AS pay_way, 'KENT' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/kw/card-kent.png' AS logo_url
|
||
UNION ALL SELECT 'KW' AS country_code, 'Card' AS pay_way, 'Knet' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/kw/card-knet.png' AS logo_url
|
||
UNION ALL SELECT 'MY' AS country_code, 'BankTransfer' AS pay_way, 'FPX' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/my/banktransfer-fpx.png' AS logo_url
|
||
UNION ALL SELECT 'MY' AS country_code, 'Ewallet' AS pay_way, 'TNG' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/my/ewallet-tng.png' AS logo_url
|
||
UNION ALL SELECT 'OM' AS country_code, 'Card' AS pay_way, 'CreditCard' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/om/card-creditcard.png' AS logo_url
|
||
UNION ALL SELECT 'PH' AS country_code, 'BankTransfer' AS pay_way, 'QRPH' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/ph/banktransfer-qrph.png' AS logo_url
|
||
UNION ALL SELECT 'PH' AS country_code, 'Ewallet' AS pay_way, 'Gcash' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/ph/ewallet-gcash.png' AS logo_url
|
||
UNION ALL SELECT 'PH' AS country_code, 'Ewallet' AS pay_way, 'PayMaya' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/ph/ewallet-paymaya.png' AS logo_url
|
||
UNION ALL SELECT 'PH' AS country_code, 'QR' AS pay_way, 'QRPH' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/ph/qr-qrph.png' AS logo_url
|
||
UNION ALL SELECT 'PK' AS country_code, 'Ewallet' AS pay_way, 'Easypaisa' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/pk/ewallet-easypaisa.png' AS logo_url
|
||
UNION ALL SELECT 'PK' AS country_code, 'Ewallet' AS pay_way, 'JazzCash' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/pk/ewallet-jazzcash.png' AS logo_url
|
||
UNION ALL SELECT 'QA' AS country_code, 'Card' AS pay_way, 'CreditCard' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/qa/card-creditcard.png' AS logo_url
|
||
UNION ALL SELECT 'SA' AS country_code, 'Card' AS pay_way, 'MADA' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/sa/card-mada.png' AS logo_url
|
||
UNION ALL SELECT 'SA' AS country_code, 'Ewallet' AS pay_way, 'ApplePay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/sa/ewallet-applepay.png' AS logo_url
|
||
UNION ALL SELECT 'SA' AS country_code, 'Ewallet' AS pay_way, 'STCPay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/sa/ewallet-stcpay.png' AS logo_url
|
||
UNION ALL SELECT 'TH' AS country_code, 'BankTransfer' AS pay_way, 'PromptPay' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/th/banktransfer-promptpay.png' AS logo_url
|
||
UNION ALL SELECT 'TH' AS country_code, 'Ewallet' AS pay_way, 'TrueMoney' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/th/ewallet-truemoney.png' AS logo_url
|
||
UNION ALL SELECT 'VN' AS country_code, 'BankTransfer' AS pay_way, 'VN_BankTransfer' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/vn/banktransfer-vn-banktransfer.png' AS logo_url
|
||
UNION ALL SELECT 'VN' AS country_code, 'QR' AS pay_way, 'VietQR' AS pay_type, 'https://media.haiyihy.com/admin/payment/mifapay/logos/vn/qr-vietqr.png' AS logo_url
|
||
) logos
|
||
ON UPPER(m.country_code) = logos.country_code
|
||
AND LOWER(m.pay_way) = LOWER(logos.pay_way)
|
||
AND LOWER(m.pay_type) = LOWER(logos.pay_type)
|
||
SET m.logo_url = logos.logo_url,
|
||
m.updated_at_ms = @now_ms
|
||
WHERE m.app_code = 'lalu'
|
||
AND m.provider_code = 'mifapay'
|
||
AND (m.logo_url = '' OR m.logo_url LIKE 'https://placehold.co/%' OR m.logo_url LIKE '%/image-preview');
|
||
|
||
CREATE TABLE IF NOT EXISTS payment_orders (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
payment_order_id VARCHAR(96) NOT NULL COMMENT '平台支付订单 ID',
|
||
provider VARCHAR(32) NOT NULL COMMENT '支付提供方',
|
||
channel VARCHAR(32) NOT NULL COMMENT '充值渠道',
|
||
status VARCHAR(32) NOT NULL COMMENT '订单状态',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '客户端确认命令幂等 ID',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
product_id BIGINT NOT NULL COMMENT '后台充值商品 ID',
|
||
product_code VARCHAR(128) NOT NULL COMMENT 'Google Play 商品 ID',
|
||
package_name VARCHAR(256) NOT NULL DEFAULT '' COMMENT 'Google Play 包名',
|
||
provider_order_id VARCHAR(128) NOT NULL DEFAULT '' COMMENT 'Google Play orderId',
|
||
purchase_token_hash VARCHAR(128) NOT NULL COMMENT 'Google purchase token SHA256,不落明文 token',
|
||
purchase_state VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'Google purchase state',
|
||
consume_state VARCHAR(32) NOT NULL DEFAULT '' COMMENT 'Google consume 状态',
|
||
wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
|
||
coin_amount BIGINT NOT NULL COMMENT '到账金币数量',
|
||
currency_code VARCHAR(8) NOT NULL DEFAULT '' COMMENT '商品币种编码',
|
||
amount_micro BIGINT NOT NULL DEFAULT 0 COMMENT '商品金额微单位',
|
||
paid_currency_code VARCHAR(8) NOT NULL DEFAULT '' COMMENT '用户实付币种,来自 Google Orders API',
|
||
paid_amount_micro BIGINT NOT NULL DEFAULT 0 COMMENT '用户实付总额微单位(实付币种)',
|
||
paid_tax_micro BIGINT NOT NULL DEFAULT 0 COMMENT '订单税额微单位(实付币种)',
|
||
paid_net_micro BIGINT NOT NULL DEFAULT 0 COMMENT 'Google 扣费后开发者净收入微单位(实付币种)',
|
||
paid_synced_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '实付明细同步时间,UTC epoch ms;0 表示未同步',
|
||
paid_sync_attempt_count INT NOT NULL DEFAULT 0 COMMENT 'Google 实付同步连续失败次数',
|
||
paid_sync_last_error VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'Google 实付同步最近错误',
|
||
paid_sync_next_retry_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT 'Google 实付同步下次重试时间,UTC epoch ms',
|
||
provider_payload JSON NULL COMMENT 'Google Play 校验返回快照',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, payment_order_id),
|
||
UNIQUE KEY uk_payment_orders_token (app_code, provider, purchase_token_hash),
|
||
UNIQUE KEY uk_payment_orders_command (app_code, command_id),
|
||
KEY idx_payment_orders_user_time (app_code, user_id, created_at_ms),
|
||
KEY idx_payment_orders_provider_order (app_code, provider, provider_order_id),
|
||
KEY idx_payment_orders_wallet_tx (app_code, wallet_transaction_id),
|
||
KEY idx_payment_orders_paid_sync (provider, paid_synced_at_ms, paid_sync_next_retry_at_ms, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='支付订单与 provider 审计表';
|
||
|
||
CREATE TABLE IF NOT EXISTS coin_seller_stock_records (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
stock_id VARCHAR(96) NOT NULL COMMENT '库存 ID',
|
||
transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
|
||
seller_user_id BIGINT NOT NULL COMMENT '商户用户 ID',
|
||
stock_type VARCHAR(32) NOT NULL COMMENT '库存类型',
|
||
counts_as_seller_recharge BOOLEAN NOT NULL COMMENT '数量as商户充值',
|
||
coin_amount BIGINT NOT NULL COMMENT '金币数量',
|
||
paid_currency_code VARCHAR(8) NOT NULL DEFAULT '' COMMENT '付款币种编码',
|
||
paid_amount_micro BIGINT NOT NULL DEFAULT 0 COMMENT '付款数量微单位',
|
||
payment_ref VARCHAR(128) NULL COMMENT '支付外部引用',
|
||
evidence_ref VARCHAR(256) NOT NULL DEFAULT '' COMMENT '凭证外部引用',
|
||
operator_user_id BIGINT NOT NULL COMMENT '操作人用户 ID',
|
||
reason VARCHAR(512) NOT NULL DEFAULT '' COMMENT '原因',
|
||
balance_after BIGINT NOT NULL COMMENT '余额后',
|
||
metadata_json JSON NULL COMMENT '扩展元数据 JSON',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, stock_id),
|
||
UNIQUE KEY uk_coin_seller_stock_command (app_code, command_id),
|
||
UNIQUE KEY uk_coin_seller_stock_payment_ref (app_code, stock_type, payment_ref),
|
||
KEY idx_coin_seller_stock_seller_time (app_code, seller_user_id, created_at_ms),
|
||
KEY idx_coin_seller_stock_type_time (app_code, stock_type, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='金币商户库存记录表';
|
||
|
||
CREATE TABLE IF NOT EXISTS coin_seller_salary_exchange_rate_tiers (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
region_id BIGINT NOT NULL COMMENT '币商所属区域 ID',
|
||
tier_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '区间 ID',
|
||
min_usd_minor BIGINT NOT NULL COMMENT '起始美元金额,单位美分,包含',
|
||
max_usd_minor BIGINT NOT NULL COMMENT '结束美元金额,单位美分,包含',
|
||
coin_per_usd BIGINT NOT NULL COMMENT '每 1 USD 工资可兑换的币商专用金币数量',
|
||
status VARCHAR(24) NOT NULL DEFAULT 'active' COMMENT '状态:active/disabled',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
|
||
created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID',
|
||
updated_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新人用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (tier_id),
|
||
KEY idx_coin_seller_salary_rates_region (app_code, region_id, status, min_usd_minor, max_usd_minor),
|
||
KEY idx_coin_seller_salary_rates_sort (app_code, region_id, status, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='币商工资兑换比例区间表';
|
||
|
||
CREATE TABLE IF NOT EXISTS resources (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
resource_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '资源 ID',
|
||
resource_code VARCHAR(96) NOT NULL COMMENT '资源编码',
|
||
resource_type VARCHAR(32) NOT NULL COMMENT '资源类型',
|
||
name VARCHAR(128) NOT NULL COMMENT '名称',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
grantable BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否允许发放',
|
||
manager_grant_enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '管理端是否允许发放',
|
||
grant_strategy VARCHAR(32) NOT NULL COMMENT '发放策略',
|
||
wallet_asset_type VARCHAR(32) NOT NULL DEFAULT '' COMMENT '钱包资产类型',
|
||
wallet_asset_amount BIGINT NOT NULL DEFAULT 0 COMMENT '钱包资产数量',
|
||
price_type VARCHAR(32) NOT NULL DEFAULT '' COMMENT '资源价格类型:coin/free',
|
||
coin_price BIGINT NOT NULL DEFAULT 0 COMMENT '资源金币价格',
|
||
gift_point_amount BIGINT NOT NULL DEFAULT 0 COMMENT '历史字段:GIFT_POINT 已下线,新写入固定 0',
|
||
usage_scope_json JSON NOT NULL COMMENT '使用范围 JSON 配置或快照',
|
||
asset_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '资产 URL',
|
||
preview_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '预览 URL',
|
||
animation_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '动画 URL',
|
||
metadata_json JSON NULL COMMENT '扩展元数据 JSON',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID',
|
||
updated_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新人用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_resources_code (app_code, resource_code),
|
||
KEY idx_resources_type_status (app_code, resource_type, status, sort_order),
|
||
KEY idx_resources_type_updated (app_code, resource_type, updated_at_ms),
|
||
KEY idx_resources_manager_grant (app_code, manager_grant_enabled, status, grantable, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='资源表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resources' AND COLUMN_NAME = 'manager_grant_enabled') = 0,
|
||
'ALTER TABLE resources ADD COLUMN manager_grant_enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT ''管理端是否允许发放'' AFTER grantable',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resources' AND COLUMN_NAME = 'price_type') = 0,
|
||
'ALTER TABLE resources ADD COLUMN price_type VARCHAR(32) NOT NULL DEFAULT '''' COMMENT ''资源价格类型:coin/free'' AFTER wallet_asset_amount',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resources' AND COLUMN_NAME = 'coin_price') = 0,
|
||
'ALTER TABLE resources ADD COLUMN coin_price BIGINT NOT NULL DEFAULT 0 COMMENT ''资源金币价格'' AFTER price_type',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resources' AND COLUMN_NAME = 'gift_point_amount') = 0,
|
||
'ALTER TABLE resources ADD COLUMN gift_point_amount BIGINT NOT NULL DEFAULT 0 COMMENT ''历史字段:GIFT_POINT 已下线,新写入固定 0'' AFTER coin_price',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resources' AND INDEX_NAME = 'idx_resources_manager_grant') = 0,
|
||
'ALTER TABLE resources ADD KEY idx_resources_manager_grant (app_code, manager_grant_enabled, status, grantable, sort_order)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS resource_groups (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
group_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '分组 ID',
|
||
group_code VARCHAR(96) NOT NULL COMMENT '分组编码',
|
||
name VARCHAR(128) NOT NULL COMMENT '名称',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
description VARCHAR(512) NOT NULL DEFAULT '' COMMENT '描述信息',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID',
|
||
updated_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新人用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_resource_groups_code (app_code, group_code),
|
||
KEY idx_resource_groups_status (app_code, status, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='资源分组表';
|
||
|
||
CREATE TABLE IF NOT EXISTS resource_group_items (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
group_item_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '分组明细 ID',
|
||
group_id BIGINT NOT NULL COMMENT '分组 ID',
|
||
item_type VARCHAR(32) NOT NULL DEFAULT 'resource' COMMENT '明细类型',
|
||
resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '资源 ID',
|
||
wallet_asset_type VARCHAR(32) NOT NULL DEFAULT '' COMMENT '钱包资产类型',
|
||
wallet_asset_amount BIGINT NOT NULL DEFAULT 0 COMMENT '钱包资产数量',
|
||
quantity BIGINT NOT NULL DEFAULT 1 COMMENT '数量',
|
||
duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '持续时长,毫秒',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_resource_group_items_member (app_code, group_id, item_type, resource_id, wallet_asset_type),
|
||
KEY idx_resource_group_items_group (app_code, group_id, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='资源分组明细表';
|
||
|
||
CREATE TABLE IF NOT EXISTS resource_shop_items (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
shop_item_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '道具商店条目 ID',
|
||
resource_id BIGINT NOT NULL COMMENT '售卖资源 ID',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
duration_days INT NOT NULL COMMENT '售卖天数,只允许 1/3/7',
|
||
effective_from_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效开始时间,UTC epoch ms,0 表示立即生效',
|
||
effective_to_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效结束时间,UTC epoch ms,0 表示长期有效',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID',
|
||
updated_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新人用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_resource_shop_items_resource (app_code, resource_id),
|
||
KEY idx_resource_shop_items_status_sort (app_code, status, sort_order),
|
||
KEY idx_resource_shop_items_effective (app_code, status, effective_from_ms, effective_to_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='道具商店售卖资源表';
|
||
|
||
CREATE TABLE IF NOT EXISTS resource_shop_purchase_orders (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
order_id VARCHAR(96) NOT NULL COMMENT '道具商店订单 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT 'App 购买命令幂等 ID',
|
||
user_id BIGINT NOT NULL COMMENT '购买用户 ID',
|
||
shop_item_id BIGINT NOT NULL COMMENT '道具商店条目 ID',
|
||
resource_id BIGINT NOT NULL COMMENT '资源 ID',
|
||
duration_days INT NOT NULL COMMENT '购买生效天数,订单快照',
|
||
price_coin BIGINT NOT NULL COMMENT '实扣金币,订单快照',
|
||
status VARCHAR(32) NOT NULL COMMENT '订单状态',
|
||
wallet_transaction_id VARCHAR(96) NOT NULL COMMENT '扣费钱包交易 ID',
|
||
resource_grant_id VARCHAR(96) NOT NULL COMMENT '资源发放 ID',
|
||
entitlement_id VARCHAR(96) NOT NULL COMMENT '最终权益 ID',
|
||
request_hash VARCHAR(128) NOT NULL COMMENT '购买请求语义哈希',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, order_id),
|
||
UNIQUE KEY uk_resource_shop_purchase_command (app_code, command_id),
|
||
KEY idx_resource_shop_purchase_user_time (app_code, user_id, created_at_ms),
|
||
KEY idx_resource_shop_purchase_tx (app_code, wallet_transaction_id),
|
||
KEY idx_resource_shop_purchase_entitlement (app_code, entitlement_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='道具商店购买订单表';
|
||
|
||
CREATE TABLE IF NOT EXISTS gift_type_configs (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
type_code VARCHAR(32) NOT NULL COMMENT '礼物类型编码,供 gift_configs 引用',
|
||
name VARCHAR(64) NOT NULL COMMENT '后台展示名称',
|
||
tab_key VARCHAR(32) NOT NULL COMMENT 'App 礼物面板 tab 展示 key',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT 'tab 状态,active 才在 App 面板展示',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT 'tab 排序权重,数值越小越靠前',
|
||
created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID',
|
||
updated_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新人用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, type_code),
|
||
UNIQUE KEY uk_gift_type_configs_tab_key (app_code, tab_key),
|
||
KEY idx_gift_type_configs_status_sort (app_code, status, sort_order),
|
||
KEY idx_gift_type_configs_updated (app_code, updated_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物类型和 App 面板 tab 配置表';
|
||
|
||
CREATE TABLE IF NOT EXISTS gift_configs (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID',
|
||
resource_id BIGINT NOT NULL COMMENT '资源 ID',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
name VARCHAR(128) NOT NULL COMMENT '名称',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
presentation_json JSON NULL COMMENT '展示配置 JSON 配置或快照',
|
||
gift_type_code VARCHAR(32) NOT NULL DEFAULT 'normal' COMMENT '礼物类型编码',
|
||
effective_from_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效开始时间,UTC epoch ms',
|
||
effective_to_ms BIGINT NOT NULL DEFAULT 0 COMMENT '生效结束时间,UTC epoch ms',
|
||
effect_types_json JSON NULL COMMENT '礼物特效类型 JSON 配置',
|
||
created_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建人用户 ID',
|
||
updated_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新人用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, gift_id),
|
||
KEY idx_gift_configs_resource (app_code, resource_id),
|
||
KEY idx_gift_configs_status_sort (app_code, status, sort_order),
|
||
KEY idx_gift_configs_effective (app_code, status, effective_from_ms, effective_to_ms),
|
||
KEY idx_gift_configs_updated (app_code, updated_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物配置表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_gift_prices' AND COLUMN_NAME = 'charge_asset_type') = 0,
|
||
'ALTER TABLE wallet_gift_prices ADD COLUMN charge_asset_type VARCHAR(32) NOT NULL DEFAULT ''COIN'' COMMENT ''扣费资产类型'' AFTER status',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gift_configs' AND COLUMN_NAME = 'gift_type_code') = 0,
|
||
'ALTER TABLE gift_configs ADD COLUMN gift_type_code VARCHAR(32) NOT NULL DEFAULT ''normal'' COMMENT ''礼物类型编码'' AFTER presentation_json',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gift_configs' AND COLUMN_NAME = 'effective_from_ms') = 0,
|
||
'ALTER TABLE gift_configs ADD COLUMN effective_from_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''生效开始时间,UTC epoch ms'' AFTER gift_type_code',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gift_configs' AND COLUMN_NAME = 'effective_to_ms') = 0,
|
||
'ALTER TABLE gift_configs ADD COLUMN effective_to_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''生效结束时间,UTC epoch ms'' AFTER effective_from_ms',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gift_configs' AND COLUMN_NAME = 'effect_types_json') = 0,
|
||
'ALTER TABLE gift_configs ADD COLUMN effect_types_json JSON NULL COMMENT ''礼物特效类型 JSON 配置'' AFTER effective_to_ms',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS gift_config_regions (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID',
|
||
region_id BIGINT NOT NULL COMMENT '区域 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, gift_id, region_id),
|
||
KEY idx_gift_config_regions_region (app_code, region_id, gift_id),
|
||
KEY idx_gift_config_regions_updated (app_code, updated_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物配置区域表';
|
||
|
||
-- gateway 礼物面板每次请求只读取 owner 版本号;这些索引让版本探测保持为单租户索引最大值查询。
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'wallet_gift_prices' AND INDEX_NAME = 'idx_wallet_gift_prices_updated') = 0,
|
||
'ALTER TABLE wallet_gift_prices ADD INDEX idx_wallet_gift_prices_updated (app_code, updated_at_ms)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'resources' AND INDEX_NAME = 'idx_resources_type_updated') = 0,
|
||
'ALTER TABLE resources ADD INDEX idx_resources_type_updated (app_code, resource_type, updated_at_ms)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gift_type_configs' AND INDEX_NAME = 'idx_gift_type_configs_updated') = 0,
|
||
'ALTER TABLE gift_type_configs ADD INDEX idx_gift_type_configs_updated (app_code, updated_at_ms)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gift_configs' AND INDEX_NAME = 'idx_gift_configs_updated') = 0,
|
||
'ALTER TABLE gift_configs ADD INDEX idx_gift_configs_updated (app_code, updated_at_ms)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gift_config_regions' AND INDEX_NAME = 'idx_gift_config_regions_updated') = 0,
|
||
'ALTER TABLE gift_config_regions ADD INDEX idx_gift_config_regions_updated (app_code, updated_at_ms)',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS user_gift_wall (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
gift_id VARCHAR(96) NOT NULL COMMENT '礼物 ID',
|
||
gift_name VARCHAR(128) NOT NULL COMMENT '礼物名称',
|
||
resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '资源 ID',
|
||
resource_snapshot_json JSON NOT NULL COMMENT '资源快照 JSON',
|
||
gift_type_code VARCHAR(32) NOT NULL DEFAULT 'normal' COMMENT '礼物类型编码',
|
||
presentation_json JSON NULL COMMENT '展示配置 JSON 配置或快照',
|
||
gift_count BIGINT NOT NULL DEFAULT 0 COMMENT '礼物数量',
|
||
total_value BIGINT NOT NULL DEFAULT 0 COMMENT '总值',
|
||
total_coin_value BIGINT NOT NULL DEFAULT 0 COMMENT '总金币值',
|
||
total_diamond_value BIGINT NOT NULL DEFAULT 0 COMMENT '总钻石值',
|
||
total_gift_point BIGINT NOT NULL DEFAULT 0 COMMENT '历史字段:GIFT_POINT 已下线,新送礼不再累加',
|
||
total_heat_value BIGINT NOT NULL DEFAULT 0 COMMENT '总热度值',
|
||
charge_asset_type VARCHAR(32) NOT NULL DEFAULT 'COIN' COMMENT '扣费资产类型',
|
||
last_price_version VARCHAR(64) NOT NULL DEFAULT '' COMMENT '最后价格版本',
|
||
first_received_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '首次收到时间,UTC epoch ms',
|
||
last_received_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '最后收到时间,UTC epoch ms',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id, gift_id),
|
||
KEY idx_user_gift_wall_user_sort (app_code, user_id, sort_order, total_value, last_received_at_ms),
|
||
KEY idx_user_gift_wall_gift (app_code, gift_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户礼物墙表';
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_projection_events (
|
||
projection_name VARCHAR(64) NOT NULL COMMENT '投影名称',
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
event_id VARCHAR(128) NOT NULL COMMENT '事件幂等 ID',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
retry_count INT NOT NULL DEFAULT 0 COMMENT '重试次数',
|
||
locked_by VARCHAR(96) NOT NULL DEFAULT '' COMMENT '当前锁定 worker',
|
||
locked_until_ms BIGINT NOT NULL DEFAULT 0 COMMENT '锁定截止时间,UTC epoch ms',
|
||
last_error TEXT NULL COMMENT '最后一次失败原因',
|
||
processed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '处理时间,UTC epoch ms',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (projection_name, app_code, event_id),
|
||
KEY idx_wallet_projection_claim (projection_name, app_code, status, locked_until_ms, updated_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包投影事件表';
|
||
|
||
CREATE TABLE IF NOT EXISTS resource_grants (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
grant_id VARCHAR(96) NOT NULL COMMENT '发放 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
|
||
target_user_id BIGINT NOT NULL COMMENT '目标用户 ID',
|
||
grant_source VARCHAR(32) NOT NULL COMMENT '发放来源',
|
||
grant_subject_type VARCHAR(32) NOT NULL COMMENT '发放主体类型',
|
||
grant_subject_id VARCHAR(96) NOT NULL COMMENT '发放主体 ID',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
request_hash VARCHAR(128) NOT NULL COMMENT '请求哈希值',
|
||
group_snapshot_json JSON NULL COMMENT '资源分组快照 JSON',
|
||
reason VARCHAR(256) NOT NULL COMMENT '原因',
|
||
operator_user_id BIGINT NOT NULL COMMENT '操作人用户 ID',
|
||
revoked_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '撤销时间,UTC epoch ms',
|
||
revoked_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '撤销操作人用户 ID',
|
||
revoke_reason VARCHAR(256) NOT NULL DEFAULT '' COMMENT '撤销原因',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, grant_id),
|
||
UNIQUE KEY uk_resource_grants_command (app_code, command_id),
|
||
KEY idx_resource_grants_target_time (app_code, target_user_id, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='资源发放表';
|
||
|
||
CREATE TABLE IF NOT EXISTS resource_grant_items (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
grant_item_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '发放明细 ID',
|
||
grant_id VARCHAR(96) NOT NULL COMMENT '发放 ID',
|
||
resource_id BIGINT NOT NULL COMMENT '资源 ID',
|
||
resource_snapshot_json JSON NOT NULL COMMENT '资源快照 JSON',
|
||
quantity BIGINT NOT NULL DEFAULT 1 COMMENT '数量',
|
||
duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '持续时长,毫秒',
|
||
result_type VARCHAR(32) NOT NULL COMMENT '结果类型',
|
||
wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '钱包交易 ID',
|
||
entitlement_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '权益 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
KEY idx_resource_grant_items_grant (app_code, grant_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='资源发放明细表';
|
||
|
||
CREATE TABLE IF NOT EXISTS user_resource_entitlements (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
entitlement_id VARCHAR(96) NOT NULL COMMENT '权益 ID',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
resource_id BIGINT NOT NULL COMMENT '资源 ID',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
quantity BIGINT NOT NULL DEFAULT 1 COMMENT '数量',
|
||
remaining_quantity BIGINT NOT NULL DEFAULT 1 COMMENT '剩余数量',
|
||
effective_at_ms BIGINT NOT NULL COMMENT '生效时间,UTC epoch ms',
|
||
expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '过期时间,UTC epoch ms',
|
||
source_grant_id VARCHAR(96) NOT NULL COMMENT '来源发放 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, entitlement_id),
|
||
KEY idx_user_resource_active (app_code, user_id, resource_id, status, expires_at_ms),
|
||
KEY idx_user_resource_user_type (app_code, user_id, status, updated_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户资源权益表';
|
||
|
||
CREATE TABLE IF NOT EXISTS user_resource_equipment (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
resource_type VARCHAR(32) NOT NULL COMMENT '资源类型',
|
||
entitlement_id VARCHAR(96) NOT NULL COMMENT '权益 ID',
|
||
resource_id BIGINT NOT NULL COMMENT '资源 ID',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id, resource_type, entitlement_id),
|
||
KEY idx_user_resource_equipment_user (app_code, user_id, updated_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户资源装备表';
|
||
|
||
CREATE TABLE IF NOT EXISTS wallet_diamond_exchange_rules (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
rule_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '规则 ID',
|
||
exchange_type VARCHAR(32) NOT NULL COMMENT '兑换类型',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
from_asset_type VARCHAR(32) NOT NULL DEFAULT 'DIAMOND' COMMENT '源资产类型',
|
||
to_asset_type VARCHAR(32) NOT NULL COMMENT '目标资产类型',
|
||
from_amount BIGINT NOT NULL COMMENT '源数量',
|
||
to_amount BIGINT NOT NULL COMMENT '目标数量',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_diamond_exchange_rule (app_code, exchange_type, from_amount, to_asset_type),
|
||
KEY idx_diamond_exchange_active (app_code, status, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='钱包钻石兑换规则表';
|
||
|
||
CREATE TABLE IF NOT EXISTS gift_diamond_ratio_configs (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
region_id BIGINT NOT NULL DEFAULT 0 COMMENT '房间可见区域,0 表示全局默认',
|
||
gift_type_code VARCHAR(32) NOT NULL COMMENT '礼物类型编码',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态',
|
||
ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 100.00 COMMENT '房间贡献热度和主播周期钻石入账比例,百分比',
|
||
coin_return_ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 0.00 COMMENT '收礼人金币返还比例,百分比',
|
||
created_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '创建后台用户 ID',
|
||
updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '更新后台用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, region_id, gift_type_code),
|
||
KEY idx_gift_diamond_ratio_region (app_code, region_id, status)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='礼物钻石和房间贡献比例配置表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'gift_diamond_ratio_configs' AND COLUMN_NAME = 'coin_return_ratio_percent') = 0,
|
||
'ALTER TABLE gift_diamond_ratio_configs ADD COLUMN coin_return_ratio_percent DECIMAL(5,2) NOT NULL DEFAULT 0.00 COMMENT ''收礼人金币返还比例,百分比'' AFTER ratio_percent',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS red_packet_configs (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否启用红包',
|
||
delayed_open_seconds INT NOT NULL DEFAULT 0 COMMENT '延迟红包打开秒数',
|
||
expire_seconds INT NOT NULL DEFAULT 86400 COMMENT '红包过期秒数,房内红包固定 24 小时',
|
||
daily_send_limit INT NOT NULL DEFAULT 0 COMMENT '每用户 UTC 日发送上限,0 表示禁止发送',
|
||
rule_url VARCHAR(512) NOT NULL DEFAULT '' COMMENT '红包规则说明链接',
|
||
updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '最后更新后台用户 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包配置主表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'red_packet_configs' AND COLUMN_NAME = 'rule_url') = 0,
|
||
'ALTER TABLE red_packet_configs ADD COLUMN rule_url VARCHAR(512) NOT NULL DEFAULT '''' COMMENT ''红包规则说明链接'' AFTER daily_send_limit',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS red_packet_count_tiers (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
tier_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '数量档位 ID',
|
||
packet_count INT NOT NULL COMMENT '红包数量',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_red_packet_count_tier (app_code, packet_count),
|
||
KEY idx_red_packet_count_tier_status (app_code, status, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包数量档位表';
|
||
|
||
CREATE TABLE IF NOT EXISTS red_packet_amount_tiers (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
tier_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '金额档位 ID',
|
||
total_amount BIGINT NOT NULL COMMENT '红包总金币金额',
|
||
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '业务状态',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
UNIQUE KEY uk_red_packet_amount_tier (app_code, total_amount),
|
||
KEY idx_red_packet_amount_tier_status (app_code, status, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包金额档位表';
|
||
|
||
CREATE TABLE IF NOT EXISTS red_packets (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
packet_id VARCHAR(96) NOT NULL COMMENT '红包 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '发红包命令幂等 ID',
|
||
sender_user_id BIGINT NOT NULL COMMENT '发送者用户 ID',
|
||
room_id VARCHAR(96) NOT NULL COMMENT '房间 ID',
|
||
region_id BIGINT NOT NULL COMMENT '房间区域 ID',
|
||
packet_type VARCHAR(32) NOT NULL COMMENT '红包类型:normal/delayed',
|
||
total_amount BIGINT NOT NULL COMMENT '红包总金币金额',
|
||
packet_count INT NOT NULL COMMENT '红包份数',
|
||
remaining_amount BIGINT NOT NULL COMMENT '剩余未领取金币金额',
|
||
remaining_count INT NOT NULL COMMENT '剩余未领取份数',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
open_at_ms BIGINT NOT NULL COMMENT '可领取时间,UTC epoch ms',
|
||
expires_at_ms BIGINT NOT NULL COMMENT '过期时间,UTC epoch ms',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, packet_id),
|
||
UNIQUE KEY uk_red_packets_command (app_code, command_id),
|
||
KEY idx_red_packets_room_time (app_code, room_id, created_at_ms),
|
||
KEY idx_red_packets_sender_time (app_code, sender_user_id, created_at_ms),
|
||
KEY idx_red_packets_expire (app_code, status, expires_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包主表';
|
||
|
||
CREATE TABLE IF NOT EXISTS red_packet_allocations (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
packet_id VARCHAR(96) NOT NULL COMMENT '红包 ID',
|
||
allocation_no INT NOT NULL COMMENT '份额序号',
|
||
amount BIGINT NOT NULL COMMENT '份额金币金额',
|
||
status VARCHAR(32) NOT NULL COMMENT '份额状态',
|
||
claimed_by_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '领取用户 ID',
|
||
claim_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '领取记录 ID',
|
||
claimed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '领取时间,UTC epoch ms',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, packet_id, allocation_no),
|
||
KEY idx_red_packet_alloc_claimable (app_code, packet_id, status, allocation_no),
|
||
KEY idx_red_packet_alloc_user (app_code, claimed_by_user_id, claimed_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包随机份额表';
|
||
|
||
CREATE TABLE IF NOT EXISTS red_packet_claims (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
claim_id VARCHAR(96) NOT NULL COMMENT '领取记录 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '抢红包命令幂等 ID',
|
||
packet_id VARCHAR(96) NOT NULL COMMENT '红包 ID',
|
||
user_id BIGINT NOT NULL COMMENT '领取用户 ID',
|
||
amount BIGINT NOT NULL COMMENT '领取金币金额',
|
||
wallet_transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
failure_reason VARCHAR(64) NOT NULL DEFAULT '' COMMENT '失败原因',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, claim_id),
|
||
UNIQUE KEY uk_red_packet_claim_command (app_code, command_id),
|
||
UNIQUE KEY uk_red_packet_claim_user (app_code, packet_id, user_id),
|
||
KEY idx_red_packet_claim_packet (app_code, packet_id, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包领取记录表';
|
||
|
||
CREATE TABLE IF NOT EXISTS red_packet_refunds (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
refund_id VARCHAR(96) NOT NULL COMMENT '退款记录 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '退款命令幂等 ID',
|
||
packet_id VARCHAR(96) NOT NULL COMMENT '红包 ID',
|
||
sender_user_id BIGINT NOT NULL COMMENT '发送者用户 ID',
|
||
refund_amount BIGINT NOT NULL COMMENT '退款金币金额',
|
||
wallet_transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, refund_id),
|
||
UNIQUE KEY uk_red_packet_refund_command (app_code, command_id),
|
||
UNIQUE KEY uk_red_packet_refund_packet (app_code, packet_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包过期退款记录表';
|
||
|
||
CREATE TABLE IF NOT EXISTS red_packet_user_daily_counters (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
send_day CHAR(10) NOT NULL COMMENT 'UTC 日期,YYYY-MM-DD',
|
||
sent_count INT NOT NULL COMMENT '当日已发送次数',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id, send_day)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='红包用户每日发送计数表';
|
||
|
||
-- vip_program_configs 是 VIP 行为的唯一 App 级策略来源。购买、发放和权益查询必须读取该表,
|
||
-- 禁止在服务代码中用 app_code 分支复制 Lalu/Fami 两套状态机。
|
||
CREATE TABLE IF NOT EXISTS vip_program_configs (
|
||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||
program_type VARCHAR(32) NOT NULL COMMENT '体系类型:legacy_timed/tiered_privilege_v1',
|
||
level_count INT NOT NULL COMMENT '该 App 可配置等级数量',
|
||
same_level_expiry_policy VARCHAR(32) NOT NULL COMMENT '同级续费有效期策略:extend_remaining',
|
||
upgrade_expiry_policy VARCHAR(32) NOT NULL COMMENT '升级有效期策略:extend_remaining/replace_from_now',
|
||
downgrade_purchase_policy VARCHAR(32) NOT NULL COMMENT '降级购买策略:reject',
|
||
benefit_inheritance_policy VARCHAR(32) NOT NULL COMMENT '权益矩阵策略:当前固定 target_only,每级保存完整集合',
|
||
grant_mode VARCHAR(32) NOT NULL COMMENT '后台赠送语义:direct_membership/trial_card',
|
||
trial_card_enabled BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否允许体验卡背包和佩戴流程',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态:active/disabled',
|
||
config_version BIGINT NOT NULL DEFAULT 1 COMMENT '配置版本;订单和会员状态持久化该快照版本',
|
||
updated_by_admin_id BIGINT NOT NULL DEFAULT 0 COMMENT '最后更新管理员 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code),
|
||
KEY idx_vip_program_status (status, updated_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='按 App 配置的 VIP 体系规则';
|
||
|
||
CREATE TABLE IF NOT EXISTS vip_levels (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
level INT NOT NULL COMMENT '等级',
|
||
name VARCHAR(64) NOT NULL COMMENT '名称',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
price_coin BIGINT NOT NULL COMMENT 'VIP 价格金币数',
|
||
duration_ms BIGINT NOT NULL COMMENT '持续时长,毫秒',
|
||
reward_resource_group_id BIGINT NOT NULL DEFAULT 0 COMMENT '奖励资源分组 ID',
|
||
required_recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT '兼容旧 VIP 累充门槛字段,当前不参与购买资格',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序权重,数值越小越靠前',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, level),
|
||
KEY idx_vip_levels_status_sort (app_code, status, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 等级表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'vip_levels' AND COLUMN_NAME = 'required_recharge_coin_amount') = 0,
|
||
'ALTER TABLE vip_levels ADD COLUMN required_recharge_coin_amount BIGINT NOT NULL DEFAULT 0 COMMENT ''兼容旧 VIP 累充门槛字段,当前不参与购买资格'' AFTER reward_resource_group_id',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS user_vip_memberships (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
level INT NOT NULL COMMENT '等级',
|
||
name VARCHAR(64) NOT NULL DEFAULT '' COMMENT '名称',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
program_type VARCHAR(32) NOT NULL DEFAULT 'legacy_timed' COMMENT '激活时使用的 VIP 体系快照',
|
||
config_version BIGINT NOT NULL DEFAULT 1 COMMENT '激活时使用的 VIP 配置版本',
|
||
started_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '开始时间,UTC epoch ms',
|
||
expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '过期时间,UTC epoch ms',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id),
|
||
KEY idx_user_vip_expiry (app_code, status, expires_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 VIP 成员关系表';
|
||
|
||
-- 用户偏好和 VIP 资格分离:没有记录时运行时默认两项开启;首次 PATCH 才物化。
|
||
-- 主键包含 app_code,确保同一 user_id 在 Fami/Lalu 可独立设置。
|
||
CREATE TABLE IF NOT EXISTS user_vip_settings (
|
||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
room_entry_notice_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启进房通知',
|
||
online_global_notice_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否开启上线全服通知',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, user_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户按 App 隔离的 VIP 功能开关';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_memberships' AND COLUMN_NAME = 'program_type') = 0,
|
||
'ALTER TABLE user_vip_memberships ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''激活时使用的 VIP 体系快照'' AFTER status',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_memberships' AND COLUMN_NAME = 'config_version') = 0,
|
||
'ALTER TABLE user_vip_memberships ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''激活时使用的 VIP 配置版本'' AFTER program_type',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS vip_purchase_orders (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
order_id VARCHAR(96) NOT NULL COMMENT '订单 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '业务命令幂等 ID',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
target_level INT NOT NULL COMMENT '目标等级',
|
||
previous_level INT NOT NULL COMMENT '原等级',
|
||
previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '购买前会员过期时间快照,UTC epoch ms',
|
||
new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '购买后会员过期时间快照,UTC epoch ms',
|
||
price_coin BIGINT NOT NULL COMMENT 'VIP 价格金币数',
|
||
duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT '购买等级的有效期配置快照',
|
||
program_type VARCHAR(32) NOT NULL DEFAULT 'legacy_timed' COMMENT '订单执行的 VIP 体系快照',
|
||
config_version BIGINT NOT NULL DEFAULT 1 COMMENT '订单执行的 VIP 配置版本',
|
||
expiry_policy VARCHAR(32) NOT NULL DEFAULT 'extend_remaining' COMMENT '本单实际采用的有效期策略',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态',
|
||
wallet_transaction_id VARCHAR(96) NOT NULL COMMENT '钱包交易 ID',
|
||
resource_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '资源发放 ID',
|
||
request_hash VARCHAR(128) NOT NULL COMMENT '请求哈希值',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, order_id),
|
||
UNIQUE KEY uk_vip_purchase_command (app_code, command_id),
|
||
KEY idx_vip_purchase_user_time (app_code, user_id, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 购买订单表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'vip_purchase_orders' AND COLUMN_NAME = 'previous_expires_at_ms') = 0,
|
||
'ALTER TABLE vip_purchase_orders ADD COLUMN previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买前会员过期时间快照,UTC epoch ms'' AFTER previous_level',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'vip_purchase_orders' AND COLUMN_NAME = 'new_expires_at_ms') = 0,
|
||
'ALTER TABLE vip_purchase_orders ADD COLUMN new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买后会员过期时间快照,UTC epoch ms'' AFTER previous_expires_at_ms',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'vip_purchase_orders' AND COLUMN_NAME = 'duration_ms') = 0,
|
||
'ALTER TABLE vip_purchase_orders ADD COLUMN duration_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''购买等级的有效期配置快照'' AFTER price_coin',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'vip_purchase_orders' AND COLUMN_NAME = 'program_type') = 0,
|
||
'ALTER TABLE vip_purchase_orders ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''订单执行的 VIP 体系快照'' AFTER duration_ms',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'vip_purchase_orders' AND COLUMN_NAME = 'config_version') = 0,
|
||
'ALTER TABLE vip_purchase_orders ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''订单执行的 VIP 配置版本'' AFTER program_type',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'vip_purchase_orders' AND COLUMN_NAME = 'expiry_policy') = 0,
|
||
'ALTER TABLE vip_purchase_orders ADD COLUMN expiry_policy VARCHAR(32) NOT NULL DEFAULT ''extend_remaining'' COMMENT ''本单实际采用的有效期策略'' AFTER config_version',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
CREATE TABLE IF NOT EXISTS user_vip_history (
|
||
app_code VARCHAR(32) NOT NULL DEFAULT 'lalu' COMMENT '应用编码,用于多租户隔离',
|
||
history_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '历史 ID',
|
||
user_id BIGINT NOT NULL COMMENT '用户 ID',
|
||
action VARCHAR(32) NOT NULL COMMENT '操作',
|
||
previous_level INT NOT NULL COMMENT '原等级',
|
||
new_level INT NOT NULL COMMENT '新等级',
|
||
previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '变更前过期时间快照,UTC epoch ms',
|
||
new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '变更后过期时间快照,UTC epoch ms',
|
||
program_type VARCHAR(32) NOT NULL DEFAULT 'legacy_timed' COMMENT '变更使用的 VIP 体系快照',
|
||
config_version BIGINT NOT NULL DEFAULT 1 COMMENT '变更使用的 VIP 配置版本',
|
||
order_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '订单 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
KEY idx_user_vip_history_user_time (app_code, user_id, created_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户 VIP 历史表';
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_history' AND COLUMN_NAME = 'previous_expires_at_ms') = 0,
|
||
'ALTER TABLE user_vip_history ADD COLUMN previous_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''变更前过期时间快照,UTC epoch ms'' AFTER new_level',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_history' AND COLUMN_NAME = 'new_expires_at_ms') = 0,
|
||
'ALTER TABLE user_vip_history ADD COLUMN new_expires_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT ''变更后过期时间快照,UTC epoch ms'' AFTER previous_expires_at_ms',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_history' AND COLUMN_NAME = 'program_type') = 0,
|
||
'ALTER TABLE user_vip_history ADD COLUMN program_type VARCHAR(32) NOT NULL DEFAULT ''legacy_timed'' COMMENT ''变更使用的 VIP 体系快照'' AFTER new_expires_at_ms',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
SET @ddl := IF(
|
||
(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'user_vip_history' AND COLUMN_NAME = 'config_version') = 0,
|
||
'ALTER TABLE user_vip_history ADD COLUMN config_version BIGINT NOT NULL DEFAULT 1 COMMENT ''变更使用的 VIP 配置版本'' AFTER program_type',
|
||
'SELECT 1'
|
||
);
|
||
PREPARE stmt FROM @ddl;
|
||
EXECUTE stmt;
|
||
DEALLOCATE PREPARE stmt;
|
||
|
||
-- 重复执行 initdb 也可能面对旧 history 有效期快照为 0 的开发库。只为没有任何完整
|
||
-- 新格式 history 的当前会员补迁移基线;不 UPDATE 旧行,也不改写已有新格式历史语义。
|
||
SET @vip_history_baseline_ms := CAST(UNIX_TIMESTAMP(UTC_TIMESTAMP(3)) * 1000 AS UNSIGNED);
|
||
|
||
INSERT INTO user_vip_history (
|
||
app_code, user_id, action, previous_level, new_level, previous_expires_at_ms,
|
||
new_expires_at_ms, program_type, config_version, order_id, created_at_ms
|
||
)
|
||
SELECT
|
||
memberships.app_code,
|
||
memberships.user_id,
|
||
'migration_baseline',
|
||
0,
|
||
memberships.level,
|
||
0,
|
||
memberships.expires_at_ms,
|
||
memberships.program_type,
|
||
memberships.config_version,
|
||
'vip_configurable_060_baseline',
|
||
@vip_history_baseline_ms
|
||
FROM user_vip_memberships AS memberships
|
||
WHERE memberships.level > 0
|
||
AND memberships.expires_at_ms > 0
|
||
AND NOT EXISTS (
|
||
SELECT 1
|
||
FROM user_vip_history AS complete_history
|
||
WHERE complete_history.app_code = memberships.app_code
|
||
AND complete_history.user_id = memberships.user_id
|
||
AND complete_history.new_level > 0
|
||
AND complete_history.new_expires_at_ms > 0
|
||
)
|
||
AND NOT EXISTS (
|
||
SELECT 1
|
||
FROM user_vip_history AS existing_baseline
|
||
WHERE existing_baseline.app_code = memberships.app_code
|
||
AND existing_baseline.user_id = memberships.user_id
|
||
AND existing_baseline.order_id = 'vip_configurable_060_baseline'
|
||
);
|
||
|
||
-- vip_level_benefits 按“具体等级”保存完整权益集合。unlock_level 只保留 P1 来源信息,
|
||
-- 运行时不得靠它自动继承,以便后台将来可以显式调整任意等级的最终集合。
|
||
CREATE TABLE IF NOT EXISTS vip_level_benefits (
|
||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||
level INT NOT NULL COMMENT '拥有该权益的具体 VIP 等级',
|
||
benefit_code VARCHAR(96) NOT NULL COMMENT '稳定权益编码,跨服务权限判断只使用该值',
|
||
name VARCHAR(128) NOT NULL COMMENT '权益展示名称',
|
||
benefit_type VARCHAR(32) NOT NULL COMMENT '权益类型:decoration/function',
|
||
unlock_level INT NOT NULL COMMENT 'P1 初始解锁等级,仅用于展示来源,不参与运行时继承',
|
||
status VARCHAR(32) NOT NULL COMMENT '业务状态:active/disabled',
|
||
trial_enabled BOOLEAN NOT NULL DEFAULT TRUE COMMENT '体验卡是否可获得;金币返现必须为 false',
|
||
resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '绑定资源 ID;0 表示尚未绑定或纯功能权益',
|
||
resource_type VARCHAR(32) NOT NULL DEFAULT '' COMMENT '绑定资源类型;空表示纯功能或待运营配置',
|
||
execution_scope VARCHAR(32) NOT NULL COMMENT '实际执行方:wallet/room/user/notice',
|
||
auto_equip BOOLEAN NOT NULL DEFAULT FALSE COMMENT '资源下发后是否自动佩戴最高等级样式',
|
||
sort_order INT NOT NULL DEFAULT 0 COMMENT '权益展示顺序',
|
||
metadata_json JSON NULL COMMENT '执行方扩展配置;初始 P1 权益不猜测参数',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, level, benefit_code),
|
||
KEY idx_vip_benefit_code (app_code, benefit_code, status, level),
|
||
KEY idx_vip_benefit_level_sort (app_code, level, status, sort_order)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每等级完整权益矩阵';
|
||
|
||
-- user_vip_trial_cards 只保存体验卡的 VIP 元数据;卡片库存与当前佩戴仍分别复用
|
||
-- user_resource_entitlements 和 user_resource_equipment,切换佩戴不会重置或作废其它卡片。
|
||
CREATE TABLE IF NOT EXISTS user_vip_trial_cards (
|
||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||
trial_card_id VARCHAR(96) NOT NULL COMMENT '体验卡实例 ID',
|
||
command_id VARCHAR(128) NOT NULL COMMENT '发卡命令幂等 ID',
|
||
request_hash VARCHAR(128) NOT NULL COMMENT '发卡请求语义哈希',
|
||
user_id BIGINT NOT NULL COMMENT '持有用户 ID',
|
||
entitlement_id VARCHAR(96) NOT NULL COMMENT '通用背包权益实例 ID,也是佩戴入口标识',
|
||
resource_id BIGINT NOT NULL DEFAULT 0 COMMENT '可选资源 ID;0 表示直接按等级和时长发卡',
|
||
level INT NOT NULL COMMENT '体验卡 VIP 等级快照',
|
||
name VARCHAR(64) NOT NULL DEFAULT '' COMMENT 'VIP 等级名称快照',
|
||
status VARCHAR(32) NOT NULL COMMENT '卡片业务状态:active/revoked',
|
||
duration_ms BIGINT NOT NULL COMMENT '发卡时长快照;佩戴切换不改变该值',
|
||
effective_at_ms BIGINT NOT NULL COMMENT '卡片开始计时,UTC epoch ms',
|
||
expires_at_ms BIGINT NOT NULL COMMENT '卡片绝对过期时间,UTC epoch ms',
|
||
grant_source VARCHAR(32) NOT NULL COMMENT '发放来源',
|
||
source_grant_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '通用资源发放 ID',
|
||
operator_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '发放操作人用户 ID',
|
||
reason VARCHAR(256) NOT NULL DEFAULT '' COMMENT '发放原因',
|
||
program_type VARCHAR(32) NOT NULL COMMENT '发卡时 VIP 体系快照',
|
||
config_version BIGINT NOT NULL COMMENT '发卡时 VIP 配置版本',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, trial_card_id),
|
||
UNIQUE KEY uk_vip_trial_card_command (app_code, command_id),
|
||
UNIQUE KEY uk_vip_trial_card_entitlement (app_code, entitlement_id),
|
||
KEY idx_vip_trial_card_user (app_code, user_id, status, expires_at_ms),
|
||
KEY idx_vip_trial_card_resource (app_code, resource_id, status)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 体验卡背包元数据';
|
||
|
||
-- VIP 购买、直发、体验卡和返现领取先锁定同一守卫键,再进入会员、账户或资源业务锁。守卫与业务事实同事务提交,
|
||
-- 既避免并发首发返回可变错误,也禁止 purchase/direct grant/trial grant 交叉复用 command_id。
|
||
CREATE TABLE IF NOT EXISTS vip_command_locks (
|
||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||
command_id VARCHAR(128) NOT NULL COMMENT 'VIP 写命令幂等 ID',
|
||
biz_type VARCHAR(64) NOT NULL COMMENT '命令类型:vip_purchase/vip_grant/vip_trial_card_grant/vip_daily_coin_rebate',
|
||
request_hash VARCHAR(128) NOT NULL COMMENT '请求语义哈希',
|
||
created_at_ms BIGINT NOT NULL COMMENT '首次命令时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '最后写入时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, command_id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 写命令串行化守卫';
|
||
|
||
-- vip_daily_coin_rebate_runs 固化单 App、单 UTC 日的金额矩阵和配置版本。分页只推进本表游标,
|
||
-- 不能在每页重新读取 vip_level_benefits,否则日切期间后台改价会让同一天用户拿到不同金额版本。
|
||
CREATE TABLE IF NOT EXISTS vip_daily_coin_rebate_runs (
|
||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||
task_day CHAR(10) NOT NULL COMMENT 'UTC 日期,YYYY-MM-DD',
|
||
run_id VARCHAR(96) NOT NULL COMMENT '稳定批任务 ID',
|
||
day_start_ms BIGINT NOT NULL COMMENT 'UTC 当日开始,epoch ms',
|
||
day_end_ms BIGINT NOT NULL COMMENT 'UTC 次日开始,排他结束 epoch ms',
|
||
config_version BIGINT NOT NULL COMMENT '创建 run 时 VIP 配置版本',
|
||
level_amounts_json JSON NOT NULL COMMENT '等级到返现金额的不可变快照',
|
||
status VARCHAR(32) NOT NULL COMMENT 'running/completed',
|
||
last_user_id BIGINT NOT NULL DEFAULT 0 COMMENT '已扫描会员游标',
|
||
scanned_count BIGINT NOT NULL DEFAULT 0 COMMENT '累计扫描会员数',
|
||
created_count BIGINT NOT NULL DEFAULT 0 COMMENT '累计创建返现数',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
completed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '完成时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, task_day),
|
||
UNIQUE KEY uk_vip_rebate_run_id (app_code, run_id),
|
||
KEY idx_vip_rebate_run_status (app_code, status, task_day)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每日金币返现运行快照';
|
||
|
||
-- vip_daily_coin_rebates 是付费 VIP 日切资格事实。体验卡不写入此表;领取只允许在
|
||
-- [available_at_ms, expires_at_ms) 内完成,并与 COIN 账户、分录和 outbox 同事务提交。
|
||
CREATE TABLE IF NOT EXISTS vip_daily_coin_rebates (
|
||
app_code VARCHAR(32) NOT NULL COMMENT '应用编码,用于多租户隔离',
|
||
rebate_id VARCHAR(96) NOT NULL COMMENT '返现事实 ID',
|
||
run_id VARCHAR(96) NOT NULL COMMENT '来源日 run ID',
|
||
task_day CHAR(10) NOT NULL COMMENT 'UTC 日期,YYYY-MM-DD',
|
||
user_id BIGINT NOT NULL COMMENT '领取用户 ID',
|
||
vip_level INT NOT NULL COMMENT 'UTC 日切时付费 VIP 等级快照',
|
||
vip_name VARCHAR(64) NOT NULL COMMENT 'VIP 名称快照',
|
||
coin_amount BIGINT NOT NULL COMMENT '返现金币正整数快照',
|
||
status VARCHAR(32) NOT NULL COMMENT 'claimable/claimed;expired 由查询层投影',
|
||
available_at_ms BIGINT NOT NULL COMMENT '领取开始,UTC epoch ms',
|
||
expires_at_ms BIGINT NOT NULL COMMENT '领取排他结束,UTC epoch ms',
|
||
config_version BIGINT NOT NULL COMMENT '来源 run 的 VIP 配置版本',
|
||
claimed_at_ms BIGINT NOT NULL DEFAULT 0 COMMENT '实际领取时间,UTC epoch ms',
|
||
wallet_transaction_id VARCHAR(96) NOT NULL DEFAULT '' COMMENT '领取入账交易 ID',
|
||
created_at_ms BIGINT NOT NULL COMMENT '创建时间,UTC epoch ms',
|
||
updated_at_ms BIGINT NOT NULL COMMENT '更新时间,UTC epoch ms',
|
||
PRIMARY KEY (app_code, rebate_id),
|
||
UNIQUE KEY uk_vip_rebate_user_day (app_code, task_day, user_id),
|
||
KEY idx_vip_rebate_user_day (app_code, user_id, task_day, rebate_id),
|
||
KEY idx_vip_rebate_expiry (app_code, status, expires_at_ms)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='VIP 每日金币返现领取事实';
|
||
|
||
-- initdb 也允许在保留数据的开发库重复执行,因此同步补齐守卫,不能只覆盖全新空库。
|
||
INSERT IGNORE INTO vip_command_locks (
|
||
app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms
|
||
)
|
||
SELECT app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms
|
||
FROM wallet_transactions
|
||
WHERE biz_type IN ('vip_purchase', 'vip_grant', 'vip_daily_coin_rebate');
|
||
|
||
INSERT IGNORE INTO vip_command_locks (
|
||
app_code, command_id, biz_type, request_hash, created_at_ms, updated_at_ms
|
||
)
|
||
SELECT app_code, command_id, 'vip_trial_card_grant', request_hash, created_at_ms, updated_at_ms
|
||
FROM user_vip_trial_cards;
|
||
|
||
INSERT IGNORE INTO vip_program_configs (
|
||
app_code, program_type, level_count, same_level_expiry_policy, upgrade_expiry_policy,
|
||
downgrade_purchase_policy, benefit_inheritance_policy, grant_mode, trial_card_enabled,
|
||
status, config_version, updated_by_admin_id, created_at_ms, updated_at_ms
|
||
) VALUES
|
||
('lalu', 'legacy_timed', 10, 'extend_remaining', 'extend_remaining',
|
||
'reject', 'target_only', 'direct_membership', FALSE, 'active', 1, 0, 0, 0),
|
||
('fami', 'tiered_privilege_v1', 9, 'extend_remaining', 'replace_from_now',
|
||
'reject', 'target_only', 'trial_card', TRUE, 'active', 1, 0, 0, 0);
|
||
|
||
INSERT IGNORE INTO vip_levels (
|
||
app_code, level, name, status, price_coin, duration_ms, reward_resource_group_id, required_recharge_coin_amount,
|
||
sort_order, created_at_ms, updated_at_ms
|
||
) VALUES
|
||
('lalu', 1, 'VIP1', 'active', 1000, 604800000, 0, 0, 10, 0, 0),
|
||
('lalu', 2, 'VIP2', 'active', 3000, 604800000, 0, 0, 20, 0, 0),
|
||
('lalu', 3, 'VIP3', 'active', 8000, 604800000, 0, 0, 30, 0, 0),
|
||
('lalu', 4, 'VIP4', 'disabled', 0, 604800000, 0, 0, 40, 0, 0),
|
||
('lalu', 5, 'VIP5', 'disabled', 0, 604800000, 0, 0, 50, 0, 0),
|
||
('lalu', 6, 'VIP6', 'disabled', 0, 604800000, 0, 0, 60, 0, 0),
|
||
('lalu', 7, 'VIP7', 'disabled', 0, 604800000, 0, 0, 70, 0, 0),
|
||
('lalu', 8, 'VIP8', 'disabled', 0, 604800000, 0, 0, 80, 0, 0),
|
||
('lalu', 9, 'VIP9', 'disabled', 0, 604800000, 0, 0, 90, 0, 0),
|
||
('lalu', 10, 'VIP10', 'disabled', 0, 604800000, 0, 0, 100, 0, 0),
|
||
-- Fami 的价格和资源组必须由运营后台配置;30 天仅满足后台正数校验且等级保持 disabled,
|
||
-- 不能把 Lalu 的任何商业参数复制为可购买默认值。
|
||
('fami', 1, 'VIP1', 'disabled', 0, 2592000000, 0, 0, 10, 0, 0),
|
||
('fami', 2, 'VIP2', 'disabled', 0, 2592000000, 0, 0, 20, 0, 0),
|
||
('fami', 3, 'VIP3', 'disabled', 0, 2592000000, 0, 0, 30, 0, 0),
|
||
('fami', 4, 'VIP4', 'disabled', 0, 2592000000, 0, 0, 40, 0, 0),
|
||
('fami', 5, 'VIP5', 'disabled', 0, 2592000000, 0, 0, 50, 0, 0),
|
||
('fami', 6, 'VIP6', 'disabled', 0, 2592000000, 0, 0, 60, 0, 0),
|
||
('fami', 7, 'VIP7', 'disabled', 0, 2592000000, 0, 0, 70, 0, 0),
|
||
('fami', 8, 'VIP8', 'disabled', 0, 2592000000, 0, 0, 80, 0, 0),
|
||
('fami', 9, 'VIP9', 'disabled', 0, 2592000000, 0, 0, 90, 0, 0);
|
||
|
||
-- P1 权益按每个等级展开成完整集合:例如 VIP4 会实际写入 VIP1..VIP4 的全部权益。
|
||
-- resource_id/resource_type 保持空,待运营绑定真实资源;体验卡仅排除每日金币返现。
|
||
INSERT IGNORE INTO vip_level_benefits (
|
||
app_code, level, benefit_code, name, benefit_type, unlock_level, status, trial_enabled,
|
||
resource_id, resource_type, execution_scope, auto_equip, sort_order, metadata_json,
|
||
created_at_ms, updated_at_ms
|
||
)
|
||
SELECT
|
||
'fami', levels.level, benefits.benefit_code, benefits.name, benefits.benefit_type,
|
||
benefits.unlock_level,
|
||
CASE WHEN benefits.benefit_code = 'daily_coin_rebate' THEN 'disabled' ELSE 'active' END,
|
||
benefits.trial_enabled, 0, '', benefits.execution_scope,
|
||
benefits.auto_equip, benefits.sort_order,
|
||
CASE
|
||
WHEN benefits.benefit_code = 'online_global_notice'
|
||
THEN JSON_OBJECT('message', '欢迎进入Fami,祝你有美好的一天')
|
||
ELSE NULL
|
||
END,
|
||
0, 0
|
||
FROM (
|
||
SELECT 1 AS level UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5
|
||
UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9
|
||
) AS levels
|
||
INNER JOIN (
|
||
SELECT 'vip_badge_identity' AS benefit_code, 'VIP标识' AS name, 'function' AS benefit_type, 1 AS unlock_level, TRUE AS trial_enabled, 'user' AS execution_scope, FALSE AS auto_equip, 10 AS sort_order
|
||
UNION ALL SELECT 'vip_medal', 'VIP勋章', 'decoration', 1, TRUE, 'user', TRUE, 20
|
||
UNION ALL SELECT 'avatar_frame', 'VIP头像框', 'decoration', 1, TRUE, 'user', TRUE, 30
|
||
UNION ALL SELECT 'vip_title', 'VIP称号', 'function', 1, TRUE, 'user', FALSE, 40
|
||
UNION ALL SELECT 'chat_bubble', 'VIP聊天气泡', 'decoration', 2, TRUE, 'room', TRUE, 50
|
||
UNION ALL SELECT 'vip_gift', 'VIP礼物', 'function', 2, TRUE, 'room', FALSE, 60
|
||
UNION ALL SELECT 'entry_effect', 'VIP进场通知', 'function', 2, TRUE, 'room', FALSE, 70
|
||
UNION ALL SELECT 'visitor_history', '查看访客', 'function', 2, TRUE, 'user', FALSE, 80
|
||
UNION ALL SELECT 'voice_wave', 'VIP声波纹', 'decoration', 3, TRUE, 'room', TRUE, 90
|
||
UNION ALL SELECT 'profile_card', 'VIP资料卡皮肤', 'decoration', 3, TRUE, 'user', TRUE, 100
|
||
UNION ALL SELECT 'custom_room_background', '自定义房间背景', 'function', 3, TRUE, 'room', FALSE, 110
|
||
UNION ALL SELECT 'room_image_message', '房间发图', 'function', 3, TRUE, 'room', FALSE, 120
|
||
UNION ALL SELECT 'animated_avatar', '动态头像', 'function', 4, TRUE, 'user', FALSE, 130
|
||
UNION ALL SELECT 'animated_room_cover', '动态房间封面', 'function', 4, TRUE, 'room', FALSE, 140
|
||
UNION ALL SELECT 'mic_skin', '麦克风皮肤', 'decoration', 4, TRUE, 'room', TRUE, 150
|
||
UNION ALL SELECT 'room_border', '房间边框', 'decoration', 4, TRUE, 'room', TRUE, 160
|
||
UNION ALL SELECT 'vehicle', 'VIP座驾', 'decoration', 4, TRUE, 'room', TRUE, 170
|
||
UNION ALL SELECT 'colored_room_name', 'VIP彩色房间名称', 'function', 5, TRUE, 'room', FALSE, 180
|
||
UNION ALL SELECT 'colored_nickname', 'VIP彩色昵称', 'function', 5, TRUE, 'user', FALSE, 190
|
||
UNION ALL SELECT 'colored_id', 'VIP彩色ID', 'function', 5, TRUE, 'user', FALSE, 200
|
||
UNION ALL SELECT 'gift_tray_skin', '送礼托盘皮肤', 'function', 5, TRUE, 'room', FALSE, 210
|
||
UNION ALL SELECT 'hide_profile_data', '隐藏个人数据', 'function', 6, TRUE, 'user', FALSE, 220
|
||
UNION ALL SELECT 'custom_avatar_frame', '定制头框', 'function', 6, TRUE, 'user', FALSE, 230
|
||
UNION ALL SELECT 'leaderboard_invisible', '榜单隐身', 'function', 6, TRUE, 'user', FALSE, 240
|
||
UNION ALL SELECT 'daily_coin_rebate', '金币返现', 'function', 6, FALSE, 'wallet', FALSE, 250
|
||
UNION ALL SELECT 'custom_profile_card', '定制资料卡', 'function', 7, TRUE, 'user', FALSE, 260
|
||
UNION ALL SELECT 'anonymous_profile_visit', '匿名访问主页', 'function', 7, TRUE, 'user', FALSE, 270
|
||
UNION ALL SELECT 'custom_gift', '定制礼物', 'function', 7, TRUE, 'room', FALSE, 280
|
||
-- 产品已确认该权益只在当前房间展示,编码和名称均不再使用“全服”。
|
||
UNION ALL SELECT 'room_entry_notice', '进房高亮通知', 'function', 8, TRUE, 'room', FALSE, 290
|
||
UNION ALL SELECT 'custom_pretty_id', '定制靓号', 'function', 8, TRUE, 'user', FALSE, 300
|
||
UNION ALL SELECT 'custom_vehicle', '定制座驾', 'function', 8, TRUE, 'room', FALSE, 310
|
||
UNION ALL SELECT 'anti_kick', '防踢', 'function', 9, TRUE, 'room', FALSE, 320
|
||
UNION ALL SELECT 'anti_mute', '防禁言', 'function', 9, TRUE, 'room', FALSE, 330
|
||
UNION ALL SELECT 'online_global_notice', '上线全服通知', 'function', 9, TRUE, 'notice', FALSE, 340
|
||
) AS benefits ON benefits.unlock_level <= levels.level;
|
||
|
||
-- 原型未给出各等级金额,不能猜默认值。未配置正 int64 金额前保持 disabled;运营填入
|
||
-- metadata_json.coin_amount 并启用后,后台校验和日 run 创建都会再次严格校验。
|
||
UPDATE vip_level_benefits
|
||
SET status = 'disabled', trial_enabled = FALSE
|
||
WHERE app_code = 'fami'
|
||
AND benefit_code = 'daily_coin_rebate'
|
||
AND (
|
||
JSON_EXTRACT(metadata_json, '$.coin_amount') IS NULL
|
||
OR JSON_TYPE(JSON_EXTRACT(metadata_json, '$.coin_amount')) <> 'INTEGER'
|
||
OR CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_amount')) AS DECIMAL(65, 0)) <= 0
|
||
OR CAST(JSON_UNQUOTE(JSON_EXTRACT(metadata_json, '$.coin_amount')) AS DECIMAL(65, 0)) > 9223372036854775807
|
||
);
|
||
|
||
-- 老环境可能先执行过不含文案的 seed;这里只补空元数据,运营已配置的 App 文案必须保留。
|
||
UPDATE vip_level_benefits
|
||
SET metadata_json = JSON_OBJECT('message', '欢迎进入Fami,祝你有美好的一天')
|
||
WHERE app_code = 'fami'
|
||
AND benefit_code = 'online_global_notice'
|
||
AND COALESCE(JSON_LENGTH(metadata_json), 0) = 0;
|
||
|
||
-- Fami 的九种体验卡只预置可发放的背包资源和等级元数据,不预置素材、不固定 resource_id、
|
||
-- 不猜测卡片时长;实际发放必须由 GrantVipTrialCard 显式提交 level+duration_ms。
|
||
INSERT IGNORE INTO resources (
|
||
app_code, resource_code, resource_type, name, status, grantable, manager_grant_enabled,
|
||
grant_strategy, wallet_asset_type, wallet_asset_amount, price_type, coin_price, gift_point_amount,
|
||
usage_scope_json, asset_url, preview_url, animation_url, metadata_json, sort_order,
|
||
created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms
|
||
) VALUES
|
||
('fami', 'vip_trial_card_1', 'vip_trial_card', 'VIP1体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":1}', 10, 0, 0, 0, 0),
|
||
('fami', 'vip_trial_card_2', 'vip_trial_card', 'VIP2体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":2}', 20, 0, 0, 0, 0),
|
||
('fami', 'vip_trial_card_3', 'vip_trial_card', 'VIP3体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":3}', 30, 0, 0, 0, 0),
|
||
('fami', 'vip_trial_card_4', 'vip_trial_card', 'VIP4体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":4}', 40, 0, 0, 0, 0),
|
||
('fami', 'vip_trial_card_5', 'vip_trial_card', 'VIP5体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":5}', 50, 0, 0, 0, 0),
|
||
('fami', 'vip_trial_card_6', 'vip_trial_card', 'VIP6体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":6}', 60, 0, 0, 0, 0),
|
||
('fami', 'vip_trial_card_7', 'vip_trial_card', 'VIP7体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":7}', 70, 0, 0, 0, 0),
|
||
('fami', 'vip_trial_card_8', 'vip_trial_card', 'VIP8体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":8}', 80, 0, 0, 0, 0),
|
||
('fami', 'vip_trial_card_9', 'vip_trial_card', 'VIP9体验卡', 'active', TRUE, TRUE,
|
||
'new_entitlement', '', 0, 'free', 0, 0, '{}', '', '', '', '{"vip_level":9}', 90, 0, 0, 0, 0);
|
||
|
||
INSERT IGNORE INTO gift_type_configs (
|
||
app_code, type_code, name, tab_key, status, sort_order,
|
||
created_by_user_id, updated_by_user_id, created_at_ms, updated_at_ms
|
||
) VALUES
|
||
('lalu', 'normal', '普通礼物', 'Gift', 'active', 10, 0, 0, 0, 0),
|
||
('lalu', 'cp', 'CP礼物', 'CP', 'active', 20, 0, 0, 0, 0),
|
||
('lalu', 'lucky', '幸运礼物', 'Lucky', 'active', 30, 0, 0, 0, 0),
|
||
('lalu', 'super_lucky', '超级幸运礼物', 'Super Lucky', 'active', 40, 0, 0, 0, 0),
|
||
('lalu', 'exclusive', '专属礼物', 'Exclusive', 'active', 50, 0, 0, 0, 0),
|
||
('lalu', 'noble', '贵族礼物', 'Noble', 'active', 60, 0, 0, 0, 0),
|
||
('lalu', 'flag', '国旗礼物', 'Flag', 'active', 70, 0, 0, 0, 0),
|
||
('lalu', 'activity', '活动礼物', 'Activity', 'active', 80, 0, 0, 0, 0),
|
||
('lalu', 'magic', '魔法礼物', 'Magic', 'active', 90, 0, 0, 0, 0),
|
||
('lalu', 'custom', '定制礼物', 'Custom', 'active', 100, 0, 0, 0, 0);
|
||
|
||
INSERT IGNORE INTO gift_diamond_ratio_configs (
|
||
app_code, region_id, gift_type_code, status, ratio_percent, coin_return_ratio_percent,
|
||
created_by_admin_id, updated_by_admin_id, created_at_ms, updated_at_ms
|
||
) VALUES
|
||
('lalu', 0, 'normal', 'active', 100.00, 30.00, 0, 0, 0, 0),
|
||
('lalu', 0, 'lucky', 'active', 10.00, 10.00, 0, 0, 0, 0),
|
||
('lalu', 0, 'super_lucky', 'active', 1.00, 1.00, 0, 0, 0, 0);
|