应收账单功能实现
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
-- 公司收款账户配置。账单生成时按币种自动选择默认账户,并将其快照保存到 ar_bill。
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ar_bank_account (
|
||||
bank_account_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '收款账户ID',
|
||||
account_name VARCHAR(100) NOT NULL COMMENT '开户名',
|
||||
account_no VARCHAR(128) NOT NULL COMMENT '银行账号,应用层脱敏展示',
|
||||
bank_name VARCHAR(100) NOT NULL COMMENT '开户行',
|
||||
currency VARCHAR(10) NOT NULL DEFAULT 'CNY' COMMENT '币种',
|
||||
is_default CHAR(1) NOT NULL DEFAULT '0' COMMENT '是否默认账户,1是0否',
|
||||
status CHAR(1) NOT NULL DEFAULT '0' COMMENT '状态,0正常1停用',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
||||
create_by VARCHAR(64) NOT NULL DEFAULT 'admin' COMMENT '创建人',
|
||||
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人',
|
||||
update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||
PRIMARY KEY (bank_account_id),
|
||||
UNIQUE KEY uk_ar_bank_account_no_currency (account_no, currency),
|
||||
KEY idx_ar_bank_account_currency (currency, status, is_default)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='公司收款账户配置';
|
||||
|
||||
-- 图片提供的公司人民币收款账户。账号去除空格保存,展示时按系统安全规则脱敏。
|
||||
INSERT INTO ar_bank_account (
|
||||
account_name, account_no, bank_name, currency, is_default, status, remark
|
||||
)
|
||||
SELECT
|
||||
N'威狮国际供应链(深圳)有限公司', '86011110001370504', N'宁波银行深圳后海支行',
|
||||
'CNY', '1', '0', N'公司人民币默认收款账户'
|
||||
FROM DUAL
|
||||
WHERE NOT EXISTS (
|
||||
SELECT 1 FROM ar_bank_account
|
||||
WHERE account_no = '86011110001370504' AND currency = 'CNY'
|
||||
);
|
||||
@@ -0,0 +1,193 @@
|
||||
-- BMS 应收 V1.0
|
||||
--
|
||||
-- 需求文档中的来源表 prc_bill / prc_bill_fee 在本项目已经由
|
||||
-- sql/price/rename_bill_tables.sql 迁移为 prc_order_bill / prc_income_bill_fee;
|
||||
-- 本脚本只创建正式应收表,不改动来源表及其 VARCHAR(36) 主键。
|
||||
SET NAMES utf8mb4;
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ar_bill (
|
||||
ar_bill_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '应收账单ID',
|
||||
bill_no VARCHAR(50) NOT NULL COMMENT '账单号',
|
||||
bill_name VARCHAR(100) NOT NULL COMMENT '账单名称',
|
||||
customer_id BIGINT(20) NOT NULL COMMENT '客户ID',
|
||||
customer_code VARCHAR(50) NOT NULL COMMENT '客户编码快照',
|
||||
customer_name VARCHAR(100) NOT NULL COMMENT '客户名称快照',
|
||||
bill_period_start DATE NOT NULL COMMENT '账期开始日',
|
||||
bill_period_end DATE NOT NULL COMMENT '账期结束日',
|
||||
bill_date DATE NOT NULL COMMENT '账单出具日期',
|
||||
currency VARCHAR(10) NOT NULL DEFAULT 'CNY' COMMENT '币种',
|
||||
order_count INT(11) NOT NULL DEFAULT 0 COMMENT '订单数量',
|
||||
total_amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '账单应收总额',
|
||||
written_off_amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '已核销金额缓存',
|
||||
unwritten_amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '未核销金额缓存',
|
||||
status VARCHAR(30) NOT NULL COMMENT 'DRAFT/CONFIRMED/PARTIAL_WRITTEN_OFF/WRITTEN_OFF/VOID',
|
||||
bill_version INT(11) NOT NULL DEFAULT 1 COMMENT '账单版本',
|
||||
bank_account_name VARCHAR(100) DEFAULT NULL COMMENT '收款账户名称快照',
|
||||
bank_account_no VARCHAR(128) DEFAULT NULL COMMENT '收款账号快照,应用层脱敏展示',
|
||||
bank_name VARCHAR(100) DEFAULT NULL COMMENT '开户行快照',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '备注或作废原因',
|
||||
confirmed_by VARCHAR(64) DEFAULT NULL COMMENT '确认人',
|
||||
confirmed_time DATETIME DEFAULT NULL COMMENT '确认时间',
|
||||
create_by VARCHAR(64) NOT NULL COMMENT '创建人',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
update_by VARCHAR(64) NOT NULL COMMENT '更新人',
|
||||
update_time DATETIME NOT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (ar_bill_id),
|
||||
UNIQUE KEY uk_ar_bill_no (bill_no),
|
||||
UNIQUE KEY uk_ar_bill_customer_cutoff_version (customer_id, currency, bill_period_end, bill_version),
|
||||
KEY idx_ar_bill_customer_cutoff (customer_id, currency, bill_period_end),
|
||||
KEY idx_ar_bill_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='正式应收账单主表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ar_bill_detail (
|
||||
detail_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '账单订单明细ID',
|
||||
ar_bill_id BIGINT(20) NOT NULL COMMENT '应收账单ID',
|
||||
prc_bill_id VARCHAR(36) NOT NULL COMMENT '来源订单计费ID,保持来源类型',
|
||||
detail_no INT(11) NOT NULL COMMENT '账单内顺序号',
|
||||
order_no VARCHAR(64) NOT NULL COMMENT '订单号快照',
|
||||
tracking_no VARCHAR(64) DEFAULT NULL COMMENT '运单号快照',
|
||||
receive_time DATETIME DEFAULT NULL COMMENT '收件或入库时间',
|
||||
product_code VARCHAR(50) NOT NULL COMMENT '产品代码快照',
|
||||
product_name VARCHAR(100) DEFAULT NULL COMMENT '产品名称快照',
|
||||
goods_description VARCHAR(500) DEFAULT NULL COMMENT '货物描述快照',
|
||||
country_code CHAR(2) DEFAULT NULL COMMENT '目的国家二字码',
|
||||
country_name VARCHAR(50) DEFAULT NULL COMMENT '目的国家名称',
|
||||
dest_postcode VARCHAR(20) DEFAULT NULL COMMENT '目的邮编',
|
||||
actual_weight DECIMAL(12,3) DEFAULT NULL COMMENT '实际重量KG',
|
||||
volume_weight DECIMAL(12,3) DEFAULT NULL COMMENT '材积重量KG',
|
||||
charge_weight DECIMAL(12,3) DEFAULT NULL COMMENT '计费重量KG',
|
||||
pkg_length DECIMAL(10,2) DEFAULT NULL COMMENT '长度CM',
|
||||
pkg_width DECIMAL(10,2) DEFAULT NULL COMMENT '宽度CM',
|
||||
pkg_height DECIMAL(10,2) DEFAULT NULL COMMENT '高度CM',
|
||||
currency VARCHAR(10) NOT NULL COMMENT '币种快照',
|
||||
total_amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '订单费用合计',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '订单账单备注',
|
||||
create_by VARCHAR(64) NOT NULL COMMENT '创建人',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (detail_id),
|
||||
UNIQUE KEY uk_ar_bill_detail_source (ar_bill_id, prc_bill_id),
|
||||
UNIQUE KEY uk_ar_bill_detail_no (ar_bill_id, detail_no),
|
||||
KEY idx_ar_bill_detail_source (prc_bill_id),
|
||||
CONSTRAINT fk_ar_bill_detail_bill FOREIGN KEY (ar_bill_id) REFERENCES ar_bill (ar_bill_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应收账单订单快照';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ar_bill_detail_fee (
|
||||
detail_fee_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '账单费用明细ID',
|
||||
detail_id BIGINT(20) NOT NULL COMMENT '账单订单明细ID',
|
||||
prc_fee_id VARCHAR(36) NOT NULL COMMENT '来源费用ID,保持来源类型',
|
||||
fee_no INT(11) NOT NULL COMMENT '订单内费用顺序号',
|
||||
fee_type VARCHAR(30) NOT NULL COMMENT '费用类型快照',
|
||||
fee_name VARCHAR(100) DEFAULT NULL COMMENT '费用名称快照',
|
||||
sc_id BIGINT(20) DEFAULT NULL COMMENT '附加费配置ID快照',
|
||||
quantity DECIMAL(12,3) DEFAULT NULL COMMENT '计费数量',
|
||||
unit VARCHAR(20) DEFAULT NULL COMMENT '计费单位',
|
||||
unit_price DECIMAL(15,4) DEFAULT NULL COMMENT '费用单价',
|
||||
amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '费用金额',
|
||||
currency VARCHAR(10) NOT NULL COMMENT '币种',
|
||||
calculation_formula VARCHAR(500) DEFAULT NULL COMMENT '计算公式或说明',
|
||||
round_mode VARCHAR(20) DEFAULT NULL COMMENT '取舍规则',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '费用备注',
|
||||
create_by VARCHAR(64) NOT NULL COMMENT '创建人',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (detail_fee_id),
|
||||
UNIQUE KEY uk_ar_detail_prc_fee (detail_id, prc_fee_id),
|
||||
KEY idx_ar_detail_fee_type (fee_type),
|
||||
KEY idx_ar_detail_prc_fee (prc_fee_id),
|
||||
KEY idx_ar_detail_fee_order (detail_id, fee_no, detail_fee_id),
|
||||
CONSTRAINT fk_ar_detail_fee_detail FOREIGN KEY (detail_id) REFERENCES ar_bill_detail (detail_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应收账单费用快照';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ar_receipt (
|
||||
receipt_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '收款ID',
|
||||
receipt_no VARCHAR(50) NOT NULL COMMENT '收款单号',
|
||||
customer_id BIGINT(20) NOT NULL COMMENT '付款客户ID',
|
||||
receipt_date DATE NOT NULL COMMENT '到账日期',
|
||||
currency VARCHAR(10) NOT NULL DEFAULT 'CNY' COMMENT '币种',
|
||||
receipt_amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '到账总额',
|
||||
unallocated_amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '未分配金额缓存',
|
||||
payment_method VARCHAR(30) NOT NULL COMMENT '到账方式',
|
||||
bank_reference VARCHAR(100) DEFAULT NULL COMMENT '银行流水号或第三方交易号',
|
||||
status VARCHAR(30) NOT NULL COMMENT 'REGISTERED/PARTIAL_WRITTEN_OFF/WRITTEN_OFF/CANCELLED',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '收款备注或取消原因',
|
||||
create_by VARCHAR(64) NOT NULL COMMENT '创建人',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
update_by VARCHAR(64) NOT NULL COMMENT '更新人',
|
||||
update_time DATETIME NOT NULL COMMENT '更新时间',
|
||||
PRIMARY KEY (receipt_id),
|
||||
UNIQUE KEY uk_ar_receipt_no (receipt_no),
|
||||
UNIQUE KEY uk_ar_payment_reference (payment_method, bank_reference),
|
||||
KEY idx_ar_receipt_customer_date (customer_id, receipt_date),
|
||||
KEY idx_ar_receipt_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应收收款表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ar_receipt_writeoff (
|
||||
writeoff_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '核销ID',
|
||||
receipt_id BIGINT(20) NOT NULL COMMENT '收款ID',
|
||||
ar_bill_id BIGINT(20) NOT NULL COMMENT '应收账单ID',
|
||||
writeoff_no VARCHAR(50) NOT NULL COMMENT '核销单号',
|
||||
writeoff_amount DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '本次核销金额',
|
||||
currency VARCHAR(10) NOT NULL COMMENT '币种',
|
||||
writeoff_date DATE NOT NULL COMMENT '核销日期',
|
||||
status VARCHAR(30) NOT NULL COMMENT 'EFFECTIVE/CANCELLED',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '核销备注或取消原因',
|
||||
create_by VARCHAR(64) NOT NULL COMMENT '创建人',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
cancel_by VARCHAR(64) DEFAULT NULL COMMENT '取消人',
|
||||
cancel_time DATETIME DEFAULT NULL COMMENT '取消时间',
|
||||
PRIMARY KEY (writeoff_id),
|
||||
UNIQUE KEY uk_ar_writeoff_no (writeoff_no),
|
||||
KEY idx_ar_writeoff_receipt (receipt_id, status),
|
||||
KEY idx_ar_writeoff_bill (ar_bill_id, status),
|
||||
CONSTRAINT fk_ar_writeoff_receipt FOREIGN KEY (receipt_id) REFERENCES ar_receipt (receipt_id),
|
||||
CONSTRAINT fk_ar_writeoff_bill FOREIGN KEY (ar_bill_id) REFERENCES ar_bill (ar_bill_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应收收款核销表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ar_bill_export (
|
||||
export_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '导出ID',
|
||||
ar_bill_id BIGINT(20) NOT NULL COMMENT '应收账单ID',
|
||||
file_name VARCHAR(255) NOT NULL COMMENT '下载展示名称',
|
||||
file_type VARCHAR(20) NOT NULL COMMENT 'XLSX/PDF',
|
||||
template_code VARCHAR(50) NOT NULL COMMENT '导出模板标识',
|
||||
template_version VARCHAR(50) DEFAULT NULL COMMENT '模板版本',
|
||||
storage_key VARCHAR(500) NOT NULL COMMENT '对象存储或本地文件Key',
|
||||
file_size BIGINT(20) DEFAULT NULL COMMENT '文件字节数',
|
||||
file_hash VARCHAR(128) DEFAULT NULL COMMENT 'SHA-256校验值',
|
||||
row_count INT(11) DEFAULT NULL COMMENT '导出订单行数',
|
||||
export_status VARCHAR(30) NOT NULL COMMENT 'PROCESSING/SUCCESS/FAILED',
|
||||
export_by VARCHAR(64) NOT NULL COMMENT '导出人',
|
||||
export_time DATETIME NOT NULL COMMENT '导出时间',
|
||||
remark VARCHAR(500) DEFAULT NULL COMMENT '失败原因或备注',
|
||||
PRIMARY KEY (export_id),
|
||||
KEY idx_ar_bill_export_bill (ar_bill_id, export_time),
|
||||
KEY idx_ar_bill_export_status (export_status),
|
||||
CONSTRAINT fk_ar_bill_export_bill FOREIGN KEY (ar_bill_id) REFERENCES ar_bill (ar_bill_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应收账单导出文件元数据';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ar_bill_log (
|
||||
log_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '日志ID',
|
||||
ar_bill_id BIGINT(20) DEFAULT NULL COMMENT '账单ID',
|
||||
object_type VARCHAR(40) NOT NULL COMMENT 'BILL/RECEIPT/WRITEOFF/EXPORT',
|
||||
object_id VARCHAR(64) NOT NULL COMMENT '通用对象ID',
|
||||
operation_type VARCHAR(40) NOT NULL COMMENT '操作类型',
|
||||
operation_desc VARCHAR(500) DEFAULT NULL COMMENT '操作说明',
|
||||
from_status VARCHAR(30) DEFAULT NULL COMMENT '变更前状态',
|
||||
to_status VARCHAR(30) DEFAULT NULL COMMENT '变更后状态',
|
||||
before_data TEXT COMMENT '变更前安全快照',
|
||||
after_data TEXT COMMENT '变更后安全快照',
|
||||
operator_id VARCHAR(64) NOT NULL COMMENT '操作人ID',
|
||||
operator_name VARCHAR(100) DEFAULT NULL COMMENT '操作人名称',
|
||||
operation_source VARCHAR(30) NOT NULL COMMENT 'WEB/API/JOB/IMPORT',
|
||||
request_id VARCHAR(64) DEFAULT NULL COMMENT '请求幂等标识',
|
||||
trace_id VARCHAR(64) DEFAULT NULL COMMENT '链路标识',
|
||||
result VARCHAR(20) NOT NULL COMMENT 'SUCCESS/FAILED',
|
||||
error_message VARCHAR(1000) DEFAULT NULL COMMENT '失败原因',
|
||||
client_ip VARCHAR(64) DEFAULT NULL COMMENT '来源IP',
|
||||
create_time DATETIME NOT NULL COMMENT '日志时间',
|
||||
PRIMARY KEY (log_id),
|
||||
KEY idx_ar_bill_log_bill (ar_bill_id, create_time),
|
||||
KEY idx_ar_bill_log_object (object_type, object_id, create_time),
|
||||
KEY idx_ar_bill_log_request (request_id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='应收账单操作日志';
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
@@ -0,0 +1,142 @@
|
||||
-- 应收账单:订单占用状态 + 单日期截止日迁移
|
||||
-- 适用于已经执行过 ar/ar_bill.sql、price/bill.sql 的数据库。
|
||||
-- 请在业务低峰期执行;本脚本只做字段、索引和历史状态初始化,不删除账单明细。
|
||||
SET NAMES utf8mb4;
|
||||
SET @db_name := DATABASE();
|
||||
|
||||
-- 1. 给正式账单增加账单名称。历史账单使用账单号生成默认名称。
|
||||
SET @has_bill_name := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'ar_bill'
|
||||
AND COLUMN_NAME = 'bill_name'
|
||||
);
|
||||
SET @sql := IF(@has_bill_name = 0,
|
||||
'ALTER TABLE ar_bill ADD COLUMN bill_name VARCHAR(100) NULL COMMENT ''账单名称'' AFTER bill_no',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
UPDATE ar_bill
|
||||
SET bill_name = CONCAT('应收账单-', bill_no)
|
||||
WHERE bill_name IS NULL OR TRIM(bill_name) = '';
|
||||
|
||||
SET @sql := 'ALTER TABLE ar_bill MODIFY COLUMN bill_name VARCHAR(100) NOT NULL COMMENT ''账单名称''';
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 2. 给来源计费订单增加应收账单占用状态。
|
||||
SET @has_column := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'prc_order_bill'
|
||||
AND COLUMN_NAME = 'ar_bill_status'
|
||||
);
|
||||
SET @sql := IF(@has_column = 0,
|
||||
'ALTER TABLE prc_order_bill ADD COLUMN ar_bill_status VARCHAR(20) NOT NULL DEFAULT ''UNBILLED'' COMMENT ''应收账单占用状态:UNBILLED/BILLED'' AFTER currency',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @has_index := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'prc_order_bill'
|
||||
AND INDEX_NAME = 'idx_bill_ar_status'
|
||||
);
|
||||
SET @sql := IF(@has_index = 0,
|
||||
'ALTER TABLE prc_order_bill ADD INDEX idx_bill_ar_status (customer_id, currency, ar_bill_status, biz_date)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 3. 根据已有账单明细回填历史订单状态。作废账单不占用订单。
|
||||
UPDATE prc_order_bill o
|
||||
JOIN (
|
||||
SELECT DISTINCT d.prc_bill_id
|
||||
FROM ar_bill_detail d
|
||||
JOIN ar_bill b ON b.ar_bill_id = d.ar_bill_id
|
||||
WHERE b.status <> 'VOID'
|
||||
) billed ON billed.prc_bill_id = o.bill_id
|
||||
SET o.ar_bill_status = 'BILLED'
|
||||
WHERE COALESCE(o.ar_bill_status, 'UNBILLED') <> 'BILLED';
|
||||
|
||||
-- 4. 账单唯一性改为“客户 + 币种 + 截止日 + 版本”。
|
||||
-- 同一截止日的作废账单保留历史,新账单使用递增版本号。
|
||||
DROP TEMPORARY TABLE IF EXISTS tmp_ar_bill_versions;
|
||||
CREATE TEMPORARY TABLE tmp_ar_bill_versions AS
|
||||
SELECT ar_bill_id,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY customer_id, currency, bill_period_end
|
||||
ORDER BY create_time, ar_bill_id
|
||||
) AS version_no
|
||||
FROM ar_bill;
|
||||
|
||||
UPDATE ar_bill a
|
||||
JOIN tmp_ar_bill_versions v ON v.ar_bill_id = a.ar_bill_id
|
||||
SET a.bill_version = v.version_no;
|
||||
DROP TEMPORARY TABLE tmp_ar_bill_versions;
|
||||
|
||||
SET @has_old_unique := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'ar_bill'
|
||||
AND INDEX_NAME = 'uk_ar_bill_customer_period'
|
||||
);
|
||||
SET @sql := IF(@has_old_unique > 0,
|
||||
'ALTER TABLE ar_bill DROP INDEX uk_ar_bill_customer_period',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @has_new_unique := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'ar_bill'
|
||||
AND INDEX_NAME = 'uk_ar_bill_customer_cutoff_version'
|
||||
);
|
||||
SET @sql := IF(@has_new_unique = 0,
|
||||
'ALTER TABLE ar_bill ADD UNIQUE KEY uk_ar_bill_customer_cutoff_version (customer_id, currency, bill_period_end, bill_version)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @has_cutoff_index := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'ar_bill'
|
||||
AND INDEX_NAME = 'idx_ar_bill_customer_cutoff'
|
||||
);
|
||||
SET @sql := IF(@has_cutoff_index = 0,
|
||||
'ALTER TABLE ar_bill ADD INDEX idx_ar_bill_customer_cutoff (customer_id, currency, bill_period_end)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 5. 详情页按账单加载费用时使用的排序索引。可重复执行,不会重复创建。
|
||||
SET @has_detail_fee_index := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'ar_bill_detail_fee'
|
||||
AND INDEX_NAME = 'idx_ar_detail_fee_order'
|
||||
);
|
||||
SET @sql := IF(@has_detail_fee_index = 0,
|
||||
'ALTER TABLE ar_bill_detail_fee ADD INDEX idx_ar_detail_fee_order (detail_id, fee_no, detail_fee_id)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -0,0 +1,84 @@
|
||||
-- 应收模块运行期优化脚本(不回填历史数据)
|
||||
--
|
||||
-- 用于已经存在业务表的环境。脚本可重复执行:字段或索引已存在时自动跳过,
|
||||
-- 不会修改历史订单的 ar_bill_status,也不会重算历史账单版本。
|
||||
SET NAMES utf8mb4;
|
||||
SET @db_name := DATABASE();
|
||||
|
||||
-- 1. 账单唯一性调整。
|
||||
-- 旧版本 uk_ar_bill_customer_period 会禁止同一客户同一账期再次生成账单,
|
||||
-- 与 bill_version 版本化方案冲突,必须删除。
|
||||
SET @has_old_bill_unique := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'ar_bill'
|
||||
AND INDEX_NAME = 'uk_ar_bill_customer_period'
|
||||
);
|
||||
SET @sql := IF(@has_old_bill_unique > 0,
|
||||
'ALTER TABLE ar_bill DROP INDEX uk_ar_bill_customer_period',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 新唯一键要求已有数据的 bill_version 已正确区分。
|
||||
-- 如果这里创建失败,请先执行 ar_bill_cutoff_status_migration.sql 回填历史版本。
|
||||
SET @has_bill_version_unique := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'ar_bill'
|
||||
AND INDEX_NAME = 'uk_ar_bill_customer_cutoff_version'
|
||||
);
|
||||
SET @sql := IF(@has_bill_version_unique = 0,
|
||||
'ALTER TABLE ar_bill ADD UNIQUE KEY uk_ar_bill_customer_cutoff_version (customer_id, currency, bill_period_end, bill_version)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 2. 计费订单应收账单占用状态。
|
||||
SET @has_ar_bill_status := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'prc_order_bill'
|
||||
AND COLUMN_NAME = 'ar_bill_status'
|
||||
);
|
||||
SET @sql := IF(@has_ar_bill_status = 0,
|
||||
'ALTER TABLE prc_order_bill ADD COLUMN ar_bill_status VARCHAR(20) NOT NULL DEFAULT ''UNBILLED'' COMMENT ''应收账单占用状态:UNBILLED/BILLED'' AFTER currency',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 3. 订单预览、占用和释放使用的组合索引。
|
||||
SET @has_order_status_index := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'prc_order_bill'
|
||||
AND INDEX_NAME = 'idx_bill_ar_status'
|
||||
);
|
||||
SET @sql := IF(@has_order_status_index = 0,
|
||||
'ALTER TABLE prc_order_bill ADD INDEX idx_bill_ar_status (customer_id, currency, ar_bill_status, biz_date)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- 4. 详情页批量关联费用时使用的排序索引。
|
||||
SET @has_detail_fee_index := (
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.STATISTICS
|
||||
WHERE TABLE_SCHEMA = @db_name
|
||||
AND TABLE_NAME = 'ar_bill_detail_fee'
|
||||
AND INDEX_NAME = 'idx_ar_detail_fee_order'
|
||||
);
|
||||
SET @sql := IF(@has_detail_fee_index = 0,
|
||||
'ALTER TABLE ar_bill_detail_fee ADD INDEX idx_ar_detail_fee_order (detail_id, fee_no, detail_fee_id)',
|
||||
'SELECT 1');
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -0,0 +1,57 @@
|
||||
-- 应收账单菜单和权限
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, query, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2400, N'应收管理', 0, 10, 'ar', NULL, '', '', 1, 0, 'M', '0', '0', '', 'money', 'admin', sysdate(), N'应收账单、收款与核销'
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2400);
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2401, N'应收账单', 2400, 1, 'bill', 'ar/bill/index', 'ArBill', 1, 0, 'C', '0', '0', 'ar:bill:list', 'list', 'admin', sysdate(), N'正式应收账单'
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2401);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2402, N'账单查询', 2401, 1, '', NULL, 1, 0, 'F', '0', '0', 'ar:bill:query', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2402);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2403, N'生成账单', 2401, 2, '', NULL, 1, 0, 'F', '0', '0', 'ar:bill:generate', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2403);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2404, N'确认账单', 2401, 3, '', NULL, 1, 0, 'F', '0', '0', 'ar:bill:confirm', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2404);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2405, N'作废账单', 2401, 4, '', NULL, 1, 0, 'F', '0', '0', 'ar:bill:void', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2405);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2406, N'导出账单', 2401, 5, '', NULL, 1, 0, 'F', '0', '0', 'ar:bill:export', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2406);
|
||||
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, route_name, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, remark)
|
||||
SELECT 2410, N'应收收款', 2400, 2, 'receipt', 'ar/receipt/index', 'ArReceipt', 1, 0, 'C', '0', '0', 'ar:receipt:list', 'money', 'admin', sysdate(), N'收款登记与核销'
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2410);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2411, N'收款登记', 2410, 1, '', NULL, 1, 0, 'F', '0', '0', 'ar:receipt:add', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2411);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2412, N'批量核销', 2410, 2, '', NULL, 1, 0, 'F', '0', '0', 'ar:receipt:writeoff', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2412);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2413, N'取消核销', 2410, 3, '', NULL, 1, 0, 'F', '0', '0', 'ar:receipt:cancel', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2413);
|
||||
INSERT INTO sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time)
|
||||
SELECT 2414, N'取消收款', 2410, 4, '', NULL, 1, 0, 'F', '0', '0', 'ar:receipt:cancel', '#', 'admin', sysdate()
|
||||
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2414);
|
||||
|
||||
INSERT INTO sys_menu (
|
||||
menu_id, menu_name, parent_id, order_num, path, component,
|
||||
is_frame, is_cache, menu_type, visible, status, perms, icon,
|
||||
create_by, create_time
|
||||
)
|
||||
SELECT
|
||||
2420, N'应收日志', 2400, 3, 'log', 'ar/bill/log',
|
||||
1, 0, 'C', '0', '0', 'ar:log:list', 'log',
|
||||
'admin', sysdate()
|
||||
FROM DUAL
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_menu WHERE menu_id = 2420);
|
||||
|
||||
INSERT INTO sys_role_menu (role_id, menu_id)
|
||||
SELECT 1, m.menu_id FROM (SELECT 2400 AS menu_id UNION SELECT 2401 UNION SELECT 2402 UNION SELECT 2403 UNION SELECT 2404 UNION SELECT 2405 UNION SELECT 2406 UNION SELECT 2410 UNION SELECT 2411 UNION SELECT 2412 UNION SELECT 2413 UNION SELECT 2414 UNION SELECT 2420) m
|
||||
WHERE NOT EXISTS (SELECT 1 FROM sys_role_menu rm WHERE rm.role_id = 1 AND rm.menu_id = m.menu_id);
|
||||
@@ -55,6 +55,7 @@ CREATE TABLE IF NOT EXISTS prc_order_bill (
|
||||
income_total DECIMAL(10,2) DEFAULT NULL COMMENT '应收总额',
|
||||
pay_total DECIMAL(10,2) DEFAULT NULL COMMENT '应付总额',
|
||||
currency VARCHAR(10) NOT NULL DEFAULT 'CNY' COMMENT '币种',
|
||||
ar_bill_status VARCHAR(20) NOT NULL DEFAULT 'UNBILLED' COMMENT '应收账单占用状态:UNBILLED/BILLED',
|
||||
round_mode VARCHAR(20) NOT NULL DEFAULT 'HALF_UP' COMMENT '取值方式',
|
||||
created_by VARCHAR(64) DEFAULT '' COMMENT '创建人',
|
||||
create_time DATETIME DEFAULT NULL COMMENT '创建时间',
|
||||
@@ -64,6 +65,7 @@ CREATE TABLE IF NOT EXISTS prc_order_bill (
|
||||
UNIQUE KEY uk_bill_order (order_no),
|
||||
UNIQUE KEY uk_bill_key (bill_key),
|
||||
INDEX idx_bill_customer (customer_code, biz_date),
|
||||
INDEX idx_bill_ar_status (customer_id, currency, ar_bill_status, biz_date),
|
||||
INDEX idx_bill_product (product_code, country_code)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单信息主表';
|
||||
|
||||
|
||||
Reference in New Issue
Block a user