-- 账户管理模型扩展 - 数据库迁移脚本
-- 创建时间: 2026-01-05
-- 说明: 扩展三科目余额模型，增强交易状态机

-- =====================================================
-- 1. 扩展账户余额表 - 三科目模型
-- =====================================================

-- 添加三科目余额字段
ALTER TABLE account_balance 
ADD COLUMN personal_balance DECIMAL(20,2) DEFAULT 0 COMMENT '个人余额(可用)' AFTER account_type,
ADD COLUMN labor_balance DECIMAL(20,2) DEFAULT 0 COMMENT '劳动报酬(可用)' AFTER personal_balance;

-- 重命名 frozen_amount 为 frozen_balance（语义更清晰）
ALTER TABLE account_balance 
CHANGE COLUMN frozen_amount frozen_balance DECIMAL(20,2) DEFAULT 0 COMMENT '冻结余额(不可用)';

-- 数据迁移：将现有 system_balance 分配到 personal_balance
-- 注意：这是保守迁移，将全部可用余额放入个人余额
UPDATE account_balance 
SET personal_balance = system_balance - COALESCE(frozen_balance, 0),
    labor_balance = 0
WHERE personal_balance = 0;

-- 添加不变量校验的注释
ALTER TABLE account_balance 
COMMENT = '账户余额表 - 不变量: personal_balance + labor_balance + frozen_balance = bank_balance';

-- =====================================================
-- 2. 扩展系统交易表 - 增强状态机和幂等键
-- =====================================================

-- 添加来源幂等键（用于外部入账去重）
ALTER TABLE system_transaction
ADD COLUMN source_key VARCHAR(128) COMMENT '来源幂等键(SourceKey)' AFTER bank_ref_no,
ADD COLUMN submitted_at DATETIME COMMENT '提交银行时间' AFTER confirmed_at,
ADD COLUMN version INT DEFAULT 0 COMMENT '乐观锁版本' AFTER submitted_at;

-- 创建来源幂等键的唯一索引（MySQL 自动忽略 NULL 值的唯一约束）
CREATE UNIQUE INDEX idx_source_key ON system_transaction(source_key);

-- 修改状态枚举以支持新状态机
-- 注意：MySQL 的 ENUM 修改需要包含所有旧值和新值
ALTER TABLE system_transaction
MODIFY COLUMN status ENUM(
    'created',        -- 已创建（初始状态）
    'pending',        -- 待处理（已建立在途）
    'bank_submitted', -- 已提交银行
    'success',        -- 成功
    'failed',         -- 失败
    'timeout',        -- 超时
    'reversed',       -- 已冲正
    'processing',     -- 兼容旧状态
    'confirmed',      -- 兼容旧状态
    'mismatch'        -- 对账不匹配
) DEFAULT 'created' COMMENT '交易状态';

-- 数据迁移：将旧状态映射到新状态
UPDATE system_transaction SET status = 'bank_submitted' WHERE status = 'processing';
UPDATE system_transaction SET status = 'success' WHERE status = 'confirmed';

-- 添加提交时间索引（用于超时检测）
CREATE INDEX idx_submitted_at ON system_transaction(submitted_at);
CREATE INDEX idx_status_submitted ON system_transaction(status, submitted_at);

-- =====================================================
-- 3. 创建在途交易明细表（可选，用于细粒度在途管理）
-- =====================================================

CREATE TABLE IF NOT EXISTS transit_detail (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    account_id BIGINT NOT NULL COMMENT '账户ID',
    txn_no VARCHAR(32) NOT NULL COMMENT '关联交易号',
    amount DECIMAL(20,2) NOT NULL COMMENT '在途金额',
    from_personal DECIMAL(20,2) DEFAULT 0 COMMENT '来自个人余额',
    from_labor DECIMAL(20,2) DEFAULT 0 COMMENT '来自劳动报酬',
    status ENUM('pending', 'settled', 'rolled_back') DEFAULT 'pending' COMMENT '状态',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    settled_at DATETIME COMMENT '结转/回退时间',
    INDEX idx_account_id (account_id),
    UNIQUE KEY uk_txn_no (txn_no),
    INDEX idx_account_status (account_id, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='在途交易明细表';

-- =====================================================
-- 4. 创建补偿任务表
-- =====================================================

CREATE TABLE IF NOT EXISTS compensation_task (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    txn_no VARCHAR(32) NOT NULL COMMENT '关联交易号',
    task_type ENUM('timeout_check', 'reconcile', 'reverse', 'retry') NOT NULL COMMENT '任务类型',
    status ENUM('pending', 'processing', 'completed', 'failed', 'dead_letter') DEFAULT 'pending' COMMENT '任务状态',
    retry_count INT DEFAULT 0 COMMENT '重试次数',
    max_retries INT DEFAULT 3 COMMENT '最大重试次数',
    next_retry_at DATETIME COMMENT '下次重试时间',
    error_message TEXT COMMENT '错误信息',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
    completed_at DATETIME COMMENT '完成时间',
    INDEX idx_status (status),
    INDEX idx_next_retry (status, next_retry_at),
    INDEX idx_txn_no (txn_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='补偿任务表';

-- =====================================================
-- 5. 创建不变量校验日志表（审计用途）
-- =====================================================

CREATE TABLE IF NOT EXISTS invariant_check_log (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    account_id BIGINT NOT NULL COMMENT '账户ID',
    check_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '校验时间',
    personal_balance DECIMAL(20,2) NOT NULL COMMENT '个人余额',
    labor_balance DECIMAL(20,2) NOT NULL COMMENT '劳动报酬',
    frozen_balance DECIMAL(20,2) NOT NULL COMMENT '冻结余额',
    bank_balance DECIMAL(20,2) NOT NULL COMMENT '银行余额',
    transit_amount DECIMAL(20,2) NOT NULL COMMENT '在途金额',
    is_valid TINYINT(1) NOT NULL COMMENT '是否有效',
    difference DECIMAL(20,2) COMMENT '差异金额',
    trigger_source VARCHAR(100) COMMENT '触发来源',
    INDEX idx_account_time (account_id, check_time),
    INDEX idx_is_valid (is_valid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='不变量校验日志表';

-- =====================================================
-- 6. 扩展对账表 - 支持三账对齐
-- =====================================================

-- 添加三账对账结果字段
ALTER TABLE reconciliation_batch
ADD COLUMN bank_total DECIMAL(20,2) COMMENT '银行账汇总' AFTER mismatch_count,
ADD COLUMN transit_net DECIMAL(20,2) COMMENT '在途净额' AFTER bank_total,
ADD COLUMN ledger_total DECIMAL(20,2) COMMENT '总账汇总' AFTER transit_net,
ADD COLUMN three_account_balanced TINYINT(1) DEFAULT NULL COMMENT '三账是否平衡' AFTER ledger_total;


