| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- -- 评估端发票申请:基本信息行级开票金额(手工在目标库执行,仓库无迁移框架)
- -- 目标库:xg_saas
- --
- -- 【部署顺序 —— 必须严格遵守】
- -- 1) 先执行本脚本的 ALTER TABLE
- -- 2) 再执行回填 UPDATE
- -- 3) 然后才部署后端(jeeplus-assess)
- -- 4) 最后部署前端
- --
- -- 原因:FinanceInvoiceBase 实体新增 account 字段后,MyBatis-Plus 的 selectList/selectById
- -- 会按实体字段拼 SELECT 列清单。若先上代码后加列,以下 7 处查询会全部报
- -- Unknown column 'account' in 'field list':
- -- FinanceInvoiceService.java:233 / 257 findList——发票列表按项目名、报告号筛选
- -- FinanceInvoiceService.java:1313 / 1337 findRedList——红冲发票列表
- -- FinanceInvoiceService.java:1963 updateProjectArchiveByInvoiceId——开票后回写归档
- -- is_invoice / invoice_date(外层 try/catch 吞异常,会静默失效)
- -- FinanceInvoiceService.java:2238 batchMatchInvoices——台账导入导出的发票匹配
- -- ProjectListService.java:2513 importProvincialFiling——项目备案导入
- -- 反之,先加列不上代码则完全无影响(列可空,旧代码不读它)。
- -- ----------------------------
- -- 1. 新增列
- -- ----------------------------
- -- 类型对齐会计端 cw_finance_invoice_base.account(varchar(64)),
- -- 实体与 DTO 均为 String,MapStruct 同名自动映射。
- ALTER TABLE `finance_invoice_base`
- ADD COLUMN `account` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
- COMMENT '发票金额(元)——该条项目/报告行的开票金额,各行合计应等于 finance_invoice.account'
- AFTER `report_no`;
- -- ----------------------------
- -- 2. 历史数据回填
- -- ----------------------------
- -- 只回填「仅有一条基本信息行」的历史单据:这类单据不存在金额分配歧义,
- -- 行金额必然等于主表全额,回填后完全对齐新模型。
- --
- -- 一票挂多个项目/报告的历史单据(base 行数 > 1)保持 NULL:
- -- 没有任何数据能推断各项目分别开了多少,只能由业务人工补录。
- -- 后端校验与前端汇总对这类单据均放行(全 NULL 视为历史未拆分单据,
- -- 保留主表 account 原值,不覆盖为 0)。
- --
- -- 用派生表而非同表子查询:MySQL 不允许在 UPDATE 的子查询里引用被更新的同一张表。
- -- WHERE b.account IS NULL 保证脚本可重复执行。
- UPDATE `finance_invoice_base` b
- JOIN (
- SELECT `invoice_id`
- FROM `finance_invoice_base`
- WHERE `del_flag` = 0
- GROUP BY `invoice_id`
- HAVING COUNT(*) = 1
- ) single ON single.`invoice_id` = b.`invoice_id`
- JOIN `finance_invoice` f ON f.`id` = b.`invoice_id` AND f.`del_flag` = 0
- SET b.`account` = f.`account`
- WHERE b.`del_flag` = 0
- AND b.`account` IS NULL
- AND f.`account` IS NOT NULL
- AND TRIM(f.`account`) <> '';
- -- ----------------------------
- -- 3. 执行后核对(只读,不改数据)
- -- ----------------------------
- -- 3.1 回填覆盖情况:按 base 行数分组统计
- -- SELECT
- -- CASE WHEN cnt = 1 THEN '单行单据' ELSE '多行单据(需人工补录)' END AS 类型,
- -- COUNT(*) AS 发票数,
- -- SUM(filled) AS 已填行金额的发票数
- -- FROM (
- -- SELECT b.invoice_id,
- -- COUNT(*) AS cnt,
- -- MAX(CASE WHEN b.account IS NOT NULL AND TRIM(b.account) <> '' THEN 1 ELSE 0 END) AS filled
- -- FROM finance_invoice_base b
- -- WHERE b.del_flag = 0
- -- GROUP BY b.invoice_id
- -- ) t
- -- GROUP BY CASE WHEN cnt = 1 THEN '单行单据' ELSE '多行单据(需人工补录)' END;
- -- 3.2 一致性校验:已填行金额的单据,各行合计是否等于主表金额
- -- 正常应返回 0 行。若有返回,说明历史数据本身主表与明细就不一致,需人工核对。
- -- SELECT b.invoice_id,
- -- f.account AS 主表金额,
- -- SUM(CAST(NULLIF(TRIM(b.account), '') AS DECIMAL(18,2))) AS 行金额合计
- -- FROM finance_invoice_base b
- -- JOIN finance_invoice f ON f.id = b.invoice_id AND f.del_flag = 0
- -- WHERE b.del_flag = 0
- -- AND b.account IS NOT NULL AND TRIM(b.account) <> ''
- -- GROUP BY b.invoice_id, f.account
- -- HAVING ABS(IFNULL(SUM(CAST(NULLIF(TRIM(b.account), '') AS DECIMAL(18,2))), 0)
- -- - CAST(NULLIF(TRIM(f.account), '') AS DECIMAL(18,2))) > 0.005;
- -- 3.3 列出需要人工补录的多行历史单据(供业务排期)
- -- SELECT f.no AS 发票申请编号, f.account AS 发票总金额, COUNT(*) AS 项目行数,
- -- GROUP_CONCAT(b.program_name SEPARATOR ' / ') AS 关联项目
- -- FROM finance_invoice_base b
- -- JOIN finance_invoice f ON f.id = b.invoice_id AND f.del_flag = 0
- -- WHERE b.del_flag = 0
- -- GROUP BY f.no, f.account, b.invoice_id
- -- HAVING COUNT(*) > 1
- -- AND MAX(CASE WHEN b.account IS NOT NULL AND TRIM(b.account) <> '' THEN 1 ELSE 0 END) = 0;
- -- ----------------------------
- -- 4. 回滚(仅在部署失败需要退回旧代码时执行)
- -- ----------------------------
- -- 旧代码不读该列,正常情况下无需回滚;加列本身对旧版本无害。
- -- 若确实要移除:
- -- ALTER TABLE `finance_invoice_base` DROP COLUMN `account`;
|