20261109.sql 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. -- 评估端发票申请:基本信息行级开票金额(手工在目标库执行,仓库无迁移框架)
  2. -- 目标库:xg_saas
  3. --
  4. -- 【部署顺序 —— 必须严格遵守】
  5. -- 1) 先执行本脚本的 ALTER TABLE
  6. -- 2) 再执行回填 UPDATE
  7. -- 3) 然后才部署后端(jeeplus-assess)
  8. -- 4) 最后部署前端
  9. --
  10. -- 原因:FinanceInvoiceBase 实体新增 account 字段后,MyBatis-Plus 的 selectList/selectById
  11. -- 会按实体字段拼 SELECT 列清单。若先上代码后加列,以下 7 处查询会全部报
  12. -- Unknown column 'account' in 'field list':
  13. -- FinanceInvoiceService.java:233 / 257 findList——发票列表按项目名、报告号筛选
  14. -- FinanceInvoiceService.java:1313 / 1337 findRedList——红冲发票列表
  15. -- FinanceInvoiceService.java:1963 updateProjectArchiveByInvoiceId——开票后回写归档
  16. -- is_invoice / invoice_date(外层 try/catch 吞异常,会静默失效)
  17. -- FinanceInvoiceService.java:2238 batchMatchInvoices——台账导入导出的发票匹配
  18. -- ProjectListService.java:2513 importProvincialFiling——项目备案导入
  19. -- 反之,先加列不上代码则完全无影响(列可空,旧代码不读它)。
  20. -- ----------------------------
  21. -- 1. 新增列
  22. -- ----------------------------
  23. -- 类型对齐会计端 cw_finance_invoice_base.account(varchar(64)),
  24. -- 实体与 DTO 均为 String,MapStruct 同名自动映射。
  25. ALTER TABLE `finance_invoice_base`
  26. ADD COLUMN `account` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
  27. COMMENT '发票金额(元)——该条项目/报告行的开票金额,各行合计应等于 finance_invoice.account'
  28. AFTER `report_no`;
  29. -- ----------------------------
  30. -- 2. 历史数据回填
  31. -- ----------------------------
  32. -- 只回填「仅有一条基本信息行」的历史单据:这类单据不存在金额分配歧义,
  33. -- 行金额必然等于主表全额,回填后完全对齐新模型。
  34. --
  35. -- 一票挂多个项目/报告的历史单据(base 行数 > 1)保持 NULL:
  36. -- 没有任何数据能推断各项目分别开了多少,只能由业务人工补录。
  37. -- 后端校验与前端汇总对这类单据均放行(全 NULL 视为历史未拆分单据,
  38. -- 保留主表 account 原值,不覆盖为 0)。
  39. --
  40. -- 用派生表而非同表子查询:MySQL 不允许在 UPDATE 的子查询里引用被更新的同一张表。
  41. -- WHERE b.account IS NULL 保证脚本可重复执行。
  42. UPDATE `finance_invoice_base` b
  43. JOIN (
  44. SELECT `invoice_id`
  45. FROM `finance_invoice_base`
  46. WHERE `del_flag` = 0
  47. GROUP BY `invoice_id`
  48. HAVING COUNT(*) = 1
  49. ) single ON single.`invoice_id` = b.`invoice_id`
  50. JOIN `finance_invoice` f ON f.`id` = b.`invoice_id` AND f.`del_flag` = 0
  51. SET b.`account` = f.`account`
  52. WHERE b.`del_flag` = 0
  53. AND b.`account` IS NULL
  54. AND f.`account` IS NOT NULL
  55. AND TRIM(f.`account`) <> '';
  56. -- ----------------------------
  57. -- 3. 执行后核对(只读,不改数据)
  58. -- ----------------------------
  59. -- 3.1 回填覆盖情况:按 base 行数分组统计
  60. -- SELECT
  61. -- CASE WHEN cnt = 1 THEN '单行单据' ELSE '多行单据(需人工补录)' END AS 类型,
  62. -- COUNT(*) AS 发票数,
  63. -- SUM(filled) AS 已填行金额的发票数
  64. -- FROM (
  65. -- SELECT b.invoice_id,
  66. -- COUNT(*) AS cnt,
  67. -- MAX(CASE WHEN b.account IS NOT NULL AND TRIM(b.account) <> '' THEN 1 ELSE 0 END) AS filled
  68. -- FROM finance_invoice_base b
  69. -- WHERE b.del_flag = 0
  70. -- GROUP BY b.invoice_id
  71. -- ) t
  72. -- GROUP BY CASE WHEN cnt = 1 THEN '单行单据' ELSE '多行单据(需人工补录)' END;
  73. -- 3.2 一致性校验:已填行金额的单据,各行合计是否等于主表金额
  74. -- 正常应返回 0 行。若有返回,说明历史数据本身主表与明细就不一致,需人工核对。
  75. -- SELECT b.invoice_id,
  76. -- f.account AS 主表金额,
  77. -- SUM(CAST(NULLIF(TRIM(b.account), '') AS DECIMAL(18,2))) AS 行金额合计
  78. -- FROM finance_invoice_base b
  79. -- JOIN finance_invoice f ON f.id = b.invoice_id AND f.del_flag = 0
  80. -- WHERE b.del_flag = 0
  81. -- AND b.account IS NOT NULL AND TRIM(b.account) <> ''
  82. -- GROUP BY b.invoice_id, f.account
  83. -- HAVING ABS(IFNULL(SUM(CAST(NULLIF(TRIM(b.account), '') AS DECIMAL(18,2))), 0)
  84. -- - CAST(NULLIF(TRIM(f.account), '') AS DECIMAL(18,2))) > 0.005;
  85. -- 3.3 列出需要人工补录的多行历史单据(供业务排期)
  86. -- SELECT f.no AS 发票申请编号, f.account AS 发票总金额, COUNT(*) AS 项目行数,
  87. -- GROUP_CONCAT(b.program_name SEPARATOR ' / ') AS 关联项目
  88. -- FROM finance_invoice_base b
  89. -- JOIN finance_invoice f ON f.id = b.invoice_id AND f.del_flag = 0
  90. -- WHERE b.del_flag = 0
  91. -- GROUP BY f.no, f.account, b.invoice_id
  92. -- HAVING COUNT(*) > 1
  93. -- AND MAX(CASE WHEN b.account IS NOT NULL AND TRIM(b.account) <> '' THEN 1 ELSE 0 END) = 0;
  94. -- ----------------------------
  95. -- 4. 回滚(仅在部署失败需要退回旧代码时执行)
  96. -- ----------------------------
  97. -- 旧代码不读该列,正常情况下无需回滚;加列本身对旧版本无害。
  98. -- 若确实要移除:
  99. -- ALTER TABLE `finance_invoice_base` DROP COLUMN `account`;