Files
BMS/bms-back/sql/price/price_set_version.sql
T
2026-09-16 17:14:19 +08:00

153 lines
7.6 KiB
SQL

-- 价格套餐版本中间表 + 版本附加费
-- 关系:
-- prc_price_set
-- -> prc_price_set_version (步骤2: 版本号自动生成, 生效时间)
-- -> prc_price_set_detail (步骤3: 产品价格, 通过 psv_id)
-- -> prc_price_set_version_surcharge (psd_id 关联明细)
-- 可重复执行
SET NAMES utf8mb4;
SET @db := DATABASE();
CREATE TABLE IF NOT EXISTS prc_price_set_version (
psv_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '套餐版本id',
price_set_id BIGINT(20) NOT NULL COMMENT '价格套餐id',
version_no VARCHAR(20) NOT NULL COMMENT '版本号 V1/V2,自动+1',
version_seq INT(11) NOT NULL COMMENT '版本序号,用于自动+1',
effective_time DATETIME DEFAULT NULL COMMENT 'version start time (null until activate)',
expire_time DATETIME DEFAULT NULL COMMENT '失效时间(空=长期;下一版本启动时写入该启动时间)',
status CHAR(1) NOT NULL DEFAULT '0' COMMENT '0草稿 1生效 2失效',
created_by VARCHAR(64) DEFAULT '' COMMENT '创建人',
create_time DATETIME DEFAULT NULL COMMENT '创建时间',
updated_by VARCHAR(64) DEFAULT '' COMMENT '更新人',
update_time DATETIME DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (psv_id),
UNIQUE KEY uk_psv_set_no (price_set_id, version_no),
UNIQUE KEY uk_psv_set_seq (price_set_id, version_seq),
INDEX idx_psv_set_eff (price_set_id, effective_time),
INDEX idx_psv_status (status),
CONSTRAINT fk_psv_set FOREIGN KEY (price_set_id) REFERENCES prc_price_set (price_set_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='价格套餐版本';
CREATE TABLE IF NOT EXISTS prc_price_set_version_surcharge (
psvs_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '版本附加费id',
psv_id BIGINT(20) NOT NULL COMMENT '套餐版本id',
psd_id BIGINT(20) NOT NULL COMMENT '套餐明细id',
sc_id BIGINT(20) DEFAULT NULL COMMENT '来源附加费配置id',
product_code VARCHAR(20) DEFAULT NULL COMMENT '产品代码(与明细一致)',
sc_name VARCHAR(100) NOT NULL COMMENT '附加费名称快照',
fee_type VARCHAR(30) NOT NULL DEFAULT 'SURCHARGE' COMMENT '费用类型(字典bms_fee_type)',
charge_type VARCHAR(20) NOT NULL COMMENT '计费方式 FIXED固定金额/WEIGHT按重量/RATE按比例',
charge_value DECIMAL(18,6) NOT NULL COMMENT '计费数值快照',
currency CHAR(3) NOT NULL DEFAULT 'CNY' COMMENT '币种',
round_mode VARCHAR(20) NOT NULL DEFAULT 'HALF_UP' COMMENT '取值方式(字典bms_round_mode)',
country_code CHAR(2) DEFAULT NULL COMMENT '适用国家ISO2(空=全部)',
sc_note VARCHAR(500) DEFAULT NULL COMMENT '备注',
created_by VARCHAR(64) DEFAULT '' COMMENT '创建人',
create_time DATETIME DEFAULT NULL COMMENT '创建时间',
updated_by VARCHAR(64) DEFAULT '' COMMENT '更新人',
update_time DATETIME DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (psvs_id),
INDEX idx_psvs_psv (psv_id),
INDEX idx_psvs_psd (psd_id),
INDEX idx_psvs_product (psv_id, product_code),
INDEX idx_psvs_sc (sc_id),
CONSTRAINT fk_psvs_psv FOREIGN KEY (psv_id) REFERENCES prc_price_set_version (psv_id) ON DELETE CASCADE,
CONSTRAINT fk_psvs_psd FOREIGN KEY (psd_id) REFERENCES prc_price_set_detail (psd_id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='价格套餐版本附加费快照';
-- expire_time: previous version expire = next version effective_time (start)
SET @has := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'prc_price_set_version' AND COLUMN_NAME = 'expire_time'
);
SET @sql := IF(@has = 0,
'ALTER TABLE prc_price_set_version ADD COLUMN expire_time DATETIME DEFAULT NULL COMMENT ''失效时间(空=长期;下一版本启动时写入该启动时间)'' AFTER effective_time',
'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- backfill: expire_time = next version start time (by version_seq)
UPDATE prc_price_set_version cur
INNER JOIN prc_price_set_version nxt
ON nxt.price_set_id = cur.price_set_id
AND nxt.version_seq = cur.version_seq + 1
SET cur.expire_time = nxt.effective_time;
-- prc_price_set_detail.psv_id
SET @has := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'prc_price_set_detail' AND COLUMN_NAME = 'psv_id'
);
SET @sql := IF(@has = 0,
'ALTER TABLE prc_price_set_detail ADD COLUMN psv_id BIGINT(20) DEFAULT NULL COMMENT ''套餐版本id'' AFTER price_set_id',
'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @has := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'prc_price_set_detail' AND INDEX_NAME = 'idx_psd_psv'
);
SET @sql := IF(@has = 0,
'ALTER TABLE prc_price_set_detail ADD INDEX idx_psd_psv (psv_id)',
'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @has := (
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'prc_price_set_detail' AND CONSTRAINT_NAME = 'fk_psd_psv'
);
SET @sql := IF(@has = 0,
'ALTER TABLE prc_price_set_detail ADD CONSTRAINT fk_psd_psv FOREIGN KEY (psv_id) REFERENCES prc_price_set_version (psv_id) ON DELETE CASCADE',
'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 已建表补关联: 附加费.psd_id -> 套餐明细
DELETE FROM prc_price_set_version_surcharge
WHERE psd_id IS NULL
OR NOT EXISTS (
SELECT 1 FROM prc_price_set_detail d WHERE d.psd_id = prc_price_set_version_surcharge.psd_id
);
SET @sql := CONCAT(
'ALTER TABLE prc_price_set_version_surcharge MODIFY COLUMN psd_id BIGINT(20) NOT NULL COMMENT ''套餐明细id'''
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @has := (
SELECT COUNT(*) FROM information_schema.TABLE_CONSTRAINTS
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 'prc_price_set_version_surcharge' AND CONSTRAINT_NAME = 'fk_psvs_psd'
);
SET @sql := IF(@has = 0,
'ALTER TABLE prc_price_set_version_surcharge ADD CONSTRAINT fk_psvs_psd FOREIGN KEY (psd_id) REFERENCES prc_price_set_detail (psd_id) ON DELETE CASCADE',
'SELECT 1');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 回填: 每个已有套餐生成一条 V1
INSERT INTO prc_price_set_version (
price_set_id, version_no, version_seq, effective_time, status, created_by, create_time
)
SELECT
s.price_set_id,
'V1',
1,
COALESCE(CAST(s.effective_date AS DATETIME), s.create_time, NOW()),
CASE
WHEN s.status = 'S' THEN '2'
WHEN s.expire_date IS NOT NULL AND s.expire_date <= CURDATE() THEN '2'
WHEN s.status = 'E' AND (s.effective_date IS NULL OR s.effective_date <= CURDATE()) THEN '1'
ELSE '0'
END,
IFNULL(s.created_by, ''),
NOW()
FROM prc_price_set s
WHERE NOT EXISTS (
SELECT 1 FROM prc_price_set_version v WHERE v.price_set_id = s.price_set_id
);
-- 将已有明细绑定到同一套餐的 V1
UPDATE prc_price_set_detail d
INNER JOIN prc_price_set_version v
ON v.price_set_id = d.price_set_id AND v.version_seq = 1
SET d.psv_id = v.psv_id
WHERE d.psv_id IS NULL;