113 lines
5.3 KiB
PL/PgSQL
113 lines
5.3 KiB
PL/PgSQL
BEGIN;
|
||
|
||
LOCK TABLE tb_agent_wallet IN ACCESS EXCLUSIVE MODE;
|
||
|
||
ALTER TABLE tb_agent_wallet
|
||
ADD COLUMN IF NOT EXISTS credit_enabled boolean NOT NULL DEFAULT false,
|
||
ADD COLUMN IF NOT EXISTS credit_limit bigint NOT NULL DEFAULT 0;
|
||
|
||
COMMENT ON COLUMN tb_agent_wallet.credit_enabled IS '是否启用代理主钱包信用额度;分佣钱包固定关闭';
|
||
COMMENT ON COLUMN tb_agent_wallet.credit_limit IS '代理主钱包信用额度,单位为分;关闭信用时固定为0';
|
||
|
||
-- 迁移在目标库读取真实约束定义,不依赖归档迁移中的约束名称。
|
||
DO $$
|
||
DECLARE
|
||
balance_attnum smallint;
|
||
constraint_row record;
|
||
normalized_definition text;
|
||
BEGIN
|
||
SELECT attnum
|
||
INTO balance_attnum
|
||
FROM pg_attribute
|
||
WHERE attrelid = 'tb_agent_wallet'::regclass
|
||
AND attname = 'balance'
|
||
AND NOT attisdropped;
|
||
|
||
FOR constraint_row IN
|
||
SELECT conname, conkey, pg_get_constraintdef(oid) AS definition
|
||
FROM pg_constraint
|
||
WHERE conrelid = 'tb_agent_wallet'::regclass
|
||
AND contype = 'c'
|
||
LOOP
|
||
normalized_definition := regexp_replace(lower(constraint_row.definition), '[[:space:]()]', '', 'g');
|
||
IF (array_length(constraint_row.conkey, 1) = 1
|
||
AND constraint_row.conkey[1] = balance_attnum
|
||
AND normalized_definition LIKE 'check%balance%>=%0%')
|
||
OR normalized_definition LIKE '%frozen_balance%<=%balance%' THEN
|
||
RAISE NOTICE '移除代理钱包历史约束 %:%', constraint_row.conname, constraint_row.definition;
|
||
EXECUTE format('ALTER TABLE tb_agent_wallet DROP CONSTRAINT %I', constraint_row.conname);
|
||
END IF;
|
||
END LOOP;
|
||
END
|
||
$$;
|
||
|
||
ALTER TABLE tb_agent_wallet
|
||
DROP CONSTRAINT IF EXISTS chk_agent_wallet_credit_config,
|
||
DROP CONSTRAINT IF EXISTS chk_agent_wallet_credit_scope,
|
||
DROP CONSTRAINT IF EXISTS chk_agent_wallet_frozen_nonnegative,
|
||
DROP CONSTRAINT IF EXISTS chk_agent_wallet_arithmetic_range,
|
||
DROP CONSTRAINT IF EXISTS chk_agent_wallet_available_balance,
|
||
DROP CONSTRAINT IF EXISTS chk_agent_wallet_version_nonnegative;
|
||
|
||
-- 历史钱包默认关闭信用;任何既有异常都必须先形成清单并修复,禁止迁移静默改账。
|
||
DO $$
|
||
DECLARE
|
||
abnormal_count bigint;
|
||
BEGIN
|
||
SELECT COUNT(*)
|
||
INTO abnormal_count
|
||
FROM tb_agent_wallet
|
||
WHERE wallet_type NOT IN ('main', 'commission')
|
||
OR frozen_balance < 0
|
||
OR version < 0
|
||
OR credit_enabled
|
||
OR credit_limit <> 0
|
||
OR (wallet_type = 'main' AND balance::numeric - frozen_balance::numeric < 0)
|
||
OR (wallet_type = 'commission' AND (balance < 0 OR frozen_balance > balance));
|
||
|
||
IF abnormal_count > 0 THEN
|
||
RAISE EXCEPTION '代理钱包信用迁移发现 % 条异常数据,请先导出钱包ID、约束定义并修复后重试', abnormal_count;
|
||
END IF;
|
||
END
|
||
$$;
|
||
|
||
ALTER TABLE tb_agent_wallet
|
||
ADD CONSTRAINT chk_agent_wallet_credit_config CHECK (
|
||
(credit_enabled = false AND credit_limit = 0) OR
|
||
(credit_enabled = true AND credit_limit > 0)
|
||
),
|
||
ADD CONSTRAINT chk_agent_wallet_credit_scope CHECK (
|
||
wallet_type = 'main' OR (credit_enabled = false AND credit_limit = 0)
|
||
),
|
||
ADD CONSTRAINT chk_agent_wallet_frozen_nonnegative CHECK (frozen_balance >= 0),
|
||
ADD CONSTRAINT chk_agent_wallet_arithmetic_range CHECK (
|
||
wallet_type <> 'main' OR (
|
||
balance > -9223372036854775808::numeric AND
|
||
balance::numeric - frozen_balance::numeric BETWEEN -9223372036854775808::numeric AND 9223372036854775807::numeric AND
|
||
balance::numeric - frozen_balance::numeric +
|
||
CASE WHEN credit_enabled THEN credit_limit::numeric ELSE 0::numeric END
|
||
BETWEEN -9223372036854775808::numeric AND 9223372036854775807::numeric
|
||
)
|
||
),
|
||
ADD CONSTRAINT chk_agent_wallet_available_balance CHECK (
|
||
(wallet_type = 'main' AND
|
||
balance::numeric - frozen_balance::numeric +
|
||
CASE WHEN credit_enabled THEN credit_limit::numeric ELSE 0::numeric END >= 0) OR
|
||
(wallet_type = 'commission' AND balance >= 0 AND frozen_balance <= balance)
|
||
),
|
||
ADD CONSTRAINT chk_agent_wallet_version_nonnegative CHECK (version >= 0);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_agent_wallet_main_credit_enabled
|
||
ON tb_agent_wallet (shop_id)
|
||
WHERE wallet_type = 'main' AND credit_enabled = true AND deleted_at IS NULL;
|
||
|
||
COMMENT ON CONSTRAINT chk_agent_wallet_credit_config ON tb_agent_wallet IS '保证信用开关与额度组合一致';
|
||
COMMENT ON CONSTRAINT chk_agent_wallet_credit_scope ON tb_agent_wallet IS '保证只有代理主钱包可以启用信用额度';
|
||
COMMENT ON CONSTRAINT chk_agent_wallet_frozen_nonnegative ON tb_agent_wallet IS '保证冻结金额不为负数';
|
||
COMMENT ON CONSTRAINT chk_agent_wallet_arithmetic_range ON tb_agent_wallet IS '保证现金可用、总可用和欠款金额均可在int64范围内安全计算';
|
||
COMMENT ON CONSTRAINT chk_agent_wallet_available_balance ON tb_agent_wallet IS '保证主钱包总可用金额和分佣钱包现金可用金额不为负数';
|
||
COMMENT ON CONSTRAINT chk_agent_wallet_version_nonnegative ON tb_agent_wallet IS '保证钱包乐观锁版本不为负数';
|
||
COMMENT ON INDEX idx_agent_wallet_main_credit_enabled IS '启用信用额度的有效代理主钱包索引';
|
||
|
||
COMMIT;
|