From 152036a7ab5f9250c874eb8be138f62cfca04a5a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Sep 2026 13:54:55 +0800 Subject: [PATCH] fix(fms): 补齐报表模板及默认公式修正 --- sql/mysql/upgrade/20260926-fms-report-template.sql | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ yudao-module-fms/src/test/java/cn/iocoder/yudao/module/fms/service/report/FmsReportTemplateServiceTest.java | 381 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 523 insertions(+), 0 deletions(-) create mode 100644 sql/mysql/upgrade/20260926-fms-report-template.sql create mode 100644 yudao-module-fms/src/test/java/cn/iocoder/yudao/module/fms/service/report/FmsReportTemplateServiceTest.java diff --git a/sql/mysql/upgrade/20260926-fms-report-template.sql b/sql/mysql/upgrade/20260926-fms-report-template.sql new file mode 100644 index 0000000..0589b8f --- /dev/null +++ b/sql/mysql/upgrade/20260926-fms-report-template.sql @@ -0,0 +1,142 @@ +INSERT IGNORE INTO `fms_report_template` (`id`, `name`, `row_no`, `formula`, `remark`, `editable`, `sort`, `row_id`, `type`, `category`, `create_time`, `level`) VALUES +(1, '流动资产:', 0, '[]', NULL, 0, 0, 0, 1, NULL, '2021-09-18 16:39:40', 1), +(2, '流动负债:', 0, '[]', NULL, 0, 32, 0, 1, NULL, '2021-09-18 16:39:40', 1), +(3, '货币资金', 1, '[{"operator":"+","rules":0,"subjectId":1331,"subjectName":"库存现金","subjectNumber":"1001"},{"operator":"+","rules":0,"subjectId":1332,"subjectName":"银行存款","subjectNumber":"1002"},{"operator":"+","rules":0,"subjectId":1333,"subjectName":"其他货币资金","subjectNumber":"1012"}]', NULL, 1, 1, 1, 1, NULL, '2021-09-18 16:39:40', 2), +(4, '短期借款', 31, '[{"operator":"+","rules":0,"subjectId":1375,"subjectName":"短期借款","subjectNumber":"2001"}]', NULL, 1, 33, 1, 1, NULL, '2021-09-18 16:39:40', 2), +(5, '短期投资', 2, '[{"operator":"+","rules":0,"subjectId":1334,"subjectName":"短期投资","subjectNumber":"1101"}]', NULL, 1, 2, 2, 1, NULL, '2021-09-18 16:39:40', 2), +(6, '应付票据', 32, '[{"operator":"+","rules":0,"subjectId":1376,"subjectName":"应付票据","subjectNumber":"2201"}]', NULL, 1, 34, 2, 1, NULL, '2021-09-18 16:39:40', 2), +(7, '应收票据', 3, '[{"operator":"+","rules":0,"subjectId":1339,"subjectName":"应收票据","subjectNumber":"1121"}]', NULL, 1, 3, 3, 1, NULL, '2021-09-18 16:39:40', 2), +(8, '应付账款', 33, '[{"operator":"+","rules":4,"subjectId":1341,"subjectName":"预付账款","subjectNumber":"1123"},{"operator":"+","rules":4,"subjectId":1377,"subjectName":"应付账款","subjectNumber":"2202"}]', NULL, 1, 35, 3, 1, NULL, '2021-09-18 16:39:40', 2), +(9, '应收账款', 4, '[{"operator":"+","rules":3,"subjectId":1340,"subjectName":"应收账款","subjectNumber":"1122"},{"operator":"+","rules":3,"subjectId":1378,"subjectName":"预收账款","subjectNumber":"2203"}]', NULL, 1, 4, 4, 1, NULL, '2021-09-18 16:39:40', 2), +(10, '预收账款', 34, '[{"operator":"+","rules":4,"subjectId":1340,"subjectName":"应收账款","subjectNumber":"1122"},{"operator":"+","rules":4,"subjectId":1378,"subjectName":"预收账款","subjectNumber":"2203"}]', NULL, 1, 36, 4, 1, NULL, '2021-09-18 16:39:40', 2), +(11, '预付账款', 5, '[{"operator":"+","rules":3,"subjectId":1341,"subjectName":"预付账款","subjectNumber":"1123"},{"operator":"+","rules":3,"subjectId":1377,"subjectName":"应付账款","subjectNumber":"2202"}]', NULL, 1, 5, 5, 1, NULL, '2021-09-18 16:39:40', 2), +(12, '应付职工薪酬', 35, '[{"operator":"+","rules":0,"subjectId":1379,"subjectName":"应付职工薪酬","subjectNumber":"2211"}]', NULL, 1, 37, 5, 1, NULL, '2021-09-18 16:39:40', 2), +(13, '应收股利', 6, '[{"operator":"+","rules":0,"subjectId":1342,"subjectName":"应收股利","subjectNumber":"1131"}]', NULL, 1, 6, 6, 1, NULL, '2021-09-18 16:39:40', 2), +(14, '应交税费', 36, '[{"operator":"+","rules":0,"subjectId":1393,"subjectName":" 应交税费","subjectNumber":"2221"}]', NULL, 1, 38, 6, 1, NULL, '2021-09-18 16:39:40', 2), +(15, '应收利息', 7, '[{"operator":"+","rules":0,"subjectId":1343,"subjectName":"应收利息","subjectNumber":"1132"}]', NULL, 1, 7, 7, 1, NULL, '2021-09-18 16:39:40', 2), +(16, '应付利息', 37, '[{"operator":"+","rules":0,"subjectId":1412,"subjectName":"应付利息","subjectNumber":"2231"}]', NULL, 1, 39, 7, 1, NULL, '2021-09-18 16:39:40', 2), +(17, '其他应收款', 8, '[{"operator":"+","rules":0,"subjectId":1344,"subjectName":"其他应收款","subjectNumber":"1221"}]', NULL, 1, 8, 8, 1, NULL, '2021-09-18 16:39:40', 2), +(18, '应付利润', 38, '[{"operator":"+","rules":0,"subjectId":1413,"subjectName":"应付利润","subjectNumber":"2232"}]', NULL, 1, 40, 8, 1, NULL, '2021-09-18 16:39:41', 2), +(19, '存货', 9, '[{"operator":"+","rules":0,"subjectId":1345,"subjectName":"材料采购","subjectNumber":"1401"},{"operator":"+","rules":0,"subjectId":1346,"subjectName":"在途物资","subjectNumber":"1402"},{"operator":"+","rules":0,"subjectId":1347,"subjectName":"原材料","subjectNumber":"1403"},{"operator":"+","rules":0,"subjectId":1348,"subjectName":"材料成本差异","subjectNumber":"1404"},{"operator":"+","rules":0,"subjectId":1349,"subjectName":"库存商品","subjectNumber":"1405"},{"operator":"-","rules":0,"subjectId":1350,"subjectName":"商品进销差价","subjectNumber":"1407"},{"operator":"+","rules":0,"subjectId":1351,"subjectName":"委托加工物资","subjectNumber":"1408"},{"operator":"+","rules":0,"subjectId":1352,"subjectName":"周转材料","subjectNumber":"1411"},{"operator":"+","rules":0,"subjectId":1353,"subjectName":"消耗性生物资产","subjectNumber":"1421"},{"operator":"+","rules":0,"subjectId":1437,"subjectName":"生产成本","subjectNumber":"4001"},{"operator":"+","rules":0,"subjectId":1440,"subjectName":"制造费用","subjectNumber":"4101"},{"operator":"+","rules":0,"subjectId":1442,"subjectName":"工程施工","subjectNumber":"4401"},{"operator":"+","rules":0,"subjectId":1443,"subjectName":"机械作业","subjectNumber":"4403"}]', NULL, 1, 9, 9, 1, NULL, '2021-09-18 16:39:41', 2),(20, '其他应付款', 39, '[{"operator":"+","rules":0,"subjectId":1414,"subjectName":"其他应付款","subjectNumber":"2241"}]', NULL, 1, 41, 9, 1, NULL, '2021-09-18 16:39:41', 2), +(21, '其中:原材料', 10, '[{"operator":"+","rules":0,"subjectId":1347,"subjectName":"原材料","subjectNumber":"1403"}]', NULL, 1, 10, 10, 1, NULL, '2021-09-18 16:39:41', 2), +(22, '其他流动负债', 40, '[{"operator":"+","rules":0,"subjectId":1396,"subjectName":"待转销项税额","subjectNumber":"222106"}]', NULL, 1, 42, 10, 1, NULL, '2021-09-18 16:39:41', 2), +(23, '在产品', 11, '[{"operator":"+","rules":0,"subjectId":1437,"subjectName":"生产成本","subjectNumber":"4001"},{"operator":"+","rules":0,"subjectId":1440,"subjectName":"制造费用","subjectNumber":"4101"},{"operator":"+","rules":0,"subjectId":1442,"subjectName":"工程施工","subjectNumber":"4401"},{"operator":"+","rules":0,"subjectId":1443,"subjectName":"机械作业","subjectNumber":"4403"}]', NULL, 1, 11, 11, 1, NULL, '2021-09-18 16:39:41', 2), +(24, '流动负债合计', 41, '["L31+L32+L33+L34+L35+L36+L37+L38+L39+L40"]', NULL, 0, 43, 11, 1, NULL, '2021-09-18 16:39:41', 1), +(25, '库存商品', 12, '[{"operator":"+","rules":0,"subjectId":1349,"subjectName":"库存商品","subjectNumber":"1405"}]', NULL, 1, 12, 12, 1, NULL, '2021-09-18 16:39:41', 2), +(26, '非流动负债:', 0, '[]', NULL, 0, 44, 12, 1, NULL, '2021-09-18 16:39:41', 1), +(27, '周转材料', 13, '[{"operator":"+","rules":0,"subjectId":1352,"subjectName":"周转材料","subjectNumber":"1411"}]', NULL, 1, 13, 13, 1, NULL, '2021-09-18 16:39:41', 2), +(28, '长期借款', 42, '[{"operator":"+","rules":0,"subjectId":1416,"subjectName":"长期借款","subjectNumber":"2501"}]', NULL, 1, 45, 13, 1, NULL, '2021-09-18 16:39:41', 2), +(29, '其他流动资产', 14, '[{"operator":"+","rules":0,"subjectId":1394,"subjectName":"待抵扣进项税额","subjectNumber":"222104"},{"operator":"+","rules":0,"subjectId":1395,"subjectName":"待认证进项税额","subjectNumber":"222105"},{"operator":"+","rules":1,"subjectId":1392,"subjectName":"未交增值税","subjectNumber":"222102"},{"operator":"+","rules":0,"subjectId":1397,"subjectName":"增值税留抵税额","subjectNumber":"222107"}]', NULL, 1, 14, 14, 1, NULL, '2021-09-18 16:39:41', 2), +(30, '长期应付款', 43, '[{"operator":"+","rules":0,"subjectId":1417,"subjectName":"长期应付款","subjectNumber":"2701"}]', NULL, 1, 46, 14, 1, NULL, '2021-09-18 16:39:41', 2), +(31, '流动资产合计', 15, '["L1+L2+L3+L4+L5+L6+L7+L8+L9+L14"]', NULL, 0, 15, 15, 1, NULL, '2021-09-18 16:39:41', 1), +(32, '递延收益', 44, '[{"operator":"+","rules":0,"subjectId":1415,"subjectName":"递延收益","subjectNumber":"2401"}]', NULL, 1, 47, 15, 1, NULL, '2021-09-18 16:39:41', 2), +(33, '非流动资产:', 0, '[]', NULL, 0, 16, 16, 1, NULL, '2021-09-18 16:39:41', 1), +(34, '其他非流动负债', 45, '[]', NULL, 0, 48, 16, 1, NULL, '2021-09-18 16:39:41', 2), +(35, '长期债券投资', 16, '[{"operator":"+","rules":0,"subjectId":1354,"subjectName":"长期债券投资","subjectNumber":"1501"}]', NULL, 1, 17, 17, 1, NULL, '2021-09-18 16:39:41', 2), +(36, '非流动负债合计', 46, '["L42+L43+L44+L45"]', NULL, 0, 49, 17, 1, NULL, '2021-09-18 16:39:41', 1), +(37, '长期股权投资', 17, '[{"operator":"+","rules":0,"subjectId":1357,"subjectName":"长期股权投资","subjectNumber":"1511"}]', NULL, 1, 18, 18, 1, NULL, '2021-09-18 16:39:41', 2), +(38, '负债合计', 47, '["L41+L46"]', NULL, 0, 50, 18, 1, NULL, '2021-09-18 16:39:41', 1), +(39, '固定资产原价', 18, '[{"operator":"+","rules":0,"subjectId":1360,"subjectName":"固定资产","subjectNumber":"1601"}]', NULL, 1, 19, 19, 1, NULL, '2021-09-18 16:39:41', 2), +(40, '减:累计折旧', 19, '[{"operator":"+","rules":0,"subjectId":1361,"subjectName":"累计折旧","subjectNumber":"1602"}]', NULL, 1, 20, 20, 1, NULL, '2021-09-18 16:39:41', 2), +(41, '固定资产账面价值', 20, '["L18-L19"]', NULL, 0, 21, 21, 1, NULL, '2021-09-18 16:39:41', 2), +(42, '在建工程', 21, '[{"operator":"+","rules":0,"subjectId":1362,"subjectName":"在建工程","subjectNumber":"1604"}]', NULL, 1, 22, 22, 1, NULL, '2021-09-18 16:39:41', 2), +(43, '工程物资', 22, '[{"operator":"+","rules":0,"subjectId":1367,"subjectName":"工程物资","subjectNumber":"1605"}]', NULL, 1, 23, 23, 1, NULL, '2021-09-18 16:39:41', 2), +(44, '固定资产清理', 23, '[{"operator":"+","rules":0,"subjectId":1368,"subjectName":"固定资产清理","subjectNumber":"1606"}]', NULL, 1, 24, 24, 1, NULL, '2021-09-18 16:39:41', 2), +(45, '生产性生物资产', 24, '[{"operator":"+","rules":0,"subjectId":1369,"subjectName":"生产性生物资产","subjectNumber":"1621"},{"operator":"-","rules":0,"subjectId":1370,"subjectName":"生产性生物资产累计折旧","subjectNumber":"1622"}]', NULL, 1, 25, 25, 1, NULL, '2021-09-18 16:39:41', 2),(46, '所有者权益(或股东权益):', 0, '[]', NULL, 0, 51, 25, 1, NULL, '2021-09-18 16:39:41', 1), +(47, '无形资产', 25, '[{"operator":"+","rules":0,"subjectId":1371,"subjectName":"无形资产","subjectNumber":"1701"},{"operator":"-","rules":0,"subjectId":1372,"subjectName":"累计摊销","subjectNumber":"1702"}]', NULL, 1, 26, 26, 1, NULL, '2021-09-18 16:39:41', 2),(48, '实收资本(或股本)', 48, '[{"operator":"+","rules":0,"subjectId":1418,"subjectName":"实收资本","subjectNumber":"3001"}]', NULL, 1, 52, 26, 1, NULL, '2021-09-18 16:39:41', 2), +(49, '开发支出', 26, '[{"operator":"+","rules":0,"subjectId":1441,"subjectName":"研发支出","subjectNumber":"4301"}]', NULL, 1, 27, 27, 1, NULL, '2021-09-18 16:39:41', 2), +(50, '资本公积', 49, '[{"operator":"+","rules":0,"subjectId":1419,"subjectName":"资本公积","subjectNumber":"3002"}]', NULL, 1, 53, 27, 1, NULL, '2021-09-18 16:39:41', 2), +(51, '长期待摊费用', 27, '[{"operator":"+","rules":0,"subjectId":1373,"subjectName":"长期待摊费用","subjectNumber":"1801"}]', NULL, 1, 28, 28, 1, NULL, '2021-09-18 16:39:41', 2), +(52, '盈余公积', 50, '[{"operator":"+","rules":0,"subjectId":1424,"subjectName":"盈余公积","subjectNumber":"3101"}]', NULL, 1, 54, 28, 1, NULL, '2021-09-18 16:39:41', 2), +(53, '其他非流动资产', 28, '[{"operator":"+","rules":0,"subjectId":1374,"subjectName":"待处理财产损溢","subjectNumber":"1901"}]', NULL, 1, 29, 29, 1, NULL, '2021-09-18 16:39:41', 2), +(54, '未分配利润', 51, '[{"operator":"+","rules":0,"subjectId":1428,"subjectName":"本年利润","subjectNumber":"3103"},{"operator":"+","rules":0,"subjectId":1429,"subjectName":"利润分配","subjectNumber":"3104"}]', NULL, 1, 55, 29, 1, NULL, '2021-09-18 16:39:41', 2), +(55, '非流动资产合计', 29, '["L16+L17+L20+L21+L22+L23+L24+L25+L26+L27+L28"]', NULL, 0, 30, 30, 1, NULL, '2021-09-18 16:39:41', 1), +(56, '所有者权益(或股东权益)合计', 52, '["L48+L49+L50+L51"]', NULL, 0, 56, 30, 1, NULL, '2021-09-18 16:39:41', 1), +(57, '资产总计', 30, '["L15+L29"]', NULL, 0, 31, 31, 1, NULL, '2021-09-18 16:39:41', 1), +(58, '负债和所有者权益(或股东权益)总计', 53, '["L47+L52"]', NULL, 0, 57, 31, 1, NULL, '2021-09-18 16:39:41', 1), +(59, '一、营业收入', 1, '[{"operator":"+","rules":6,"subjectId":1444,"subjectName":"主营业务收入","subjectNumber":"5001"},{"operator":"+","rules":6,"subjectId":1445,"subjectName":"其他业务收入","subjectNumber":"5051"}]', NULL, 1, 0, NULL, 2, NULL, '2021-09-18 16:39:56', 1), +(60, '减:营业成本', 2, '[{"operator":"+","rules":5,"subjectId":1453,"subjectName":"主营业务成本","subjectNumber":"5401"},{"operator":"+","rules":5,"subjectId":1454,"subjectName":"其他业务成本","subjectNumber":"5402"}]', NULL, 1, 1, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(61, '税金及附加', 3, '[{"operator":"+","rules":5,"subjectId":1455,"subjectName":"税金及附加","subjectNumber":"5403"}]', NULL, 1, 2, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(62, '其中:消费税', 4, '[{"operator":"+","rules":5,"subjectId":1456,"subjectName":"消费税","subjectNumber":"540301"}]', NULL, 1, 3, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(63, '城市维护建设税', 6, '[{"operator":"+","rules":5,"subjectId":1457,"subjectName":"城市维护建设税","subjectNumber":"540303"}]', NULL, 1, 4, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(64, '资源税', 7, '[{"operator":"+","rules":5,"subjectId":1458,"subjectName":"资源税","subjectNumber":"540304"}]', NULL, 1, 5, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(65, '土地增值税', 8, '[{"operator":"+","rules":5,"subjectId":1459,"subjectName":"土地增值税","subjectNumber":"540305"}]', NULL, 1, 6, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(66, '城镇土地使用税、房产税、车船税、印花税', 9, '[{"operator":"+","rules":5,"subjectId":1460,"subjectName":"城镇土地使用税","subjectNumber":"540306"},{"operator":"+","rules":5,"subjectId":1462,"subjectName":"车船税","subjectNumber":"540308"},{"operator":"+","rules":5,"subjectId":1461,"subjectName":"房产税","subjectNumber":"540307"},{"operator":"+","rules":5,"subjectId":1463,"subjectName":"印花税","subjectNumber":"540309"}]', NULL, 1, 7, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(67, '教育费附加、矿产资源补偿费、排污费', 10, '[{"operator":"+","rules":5,"subjectId":1466,"subjectName":"排污费","subjectNumber":"540312"},{"operator":"+","rules":5,"subjectId":1465,"subjectName":"矿产资源补偿费","subjectNumber":"540311"},{"operator":"+","rules":5,"subjectId":1464,"subjectName":"教育费附加","subjectNumber":"540310"}]', NULL, 1, 8, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(68, '销售费用', 11, '[{"operator":"+","rules":5,"subjectId":1468,"subjectName":"销售费用","subjectNumber":"5601"}]', NULL, 1, 9, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(69, '其中:商品维修费', 12, '[{"operator":"+","rules":5,"subjectId":1483,"subjectName":"商品维修费","subjectNumber":"560115"}]', NULL, 1, 10, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(70, '广告费和业务宣传费', 13, '[{"operator":"+","rules":5,"subjectId":1484,"subjectName":"广告和业务宣传费","subjectNumber":"560116"}]', NULL, 1, 11, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(71, '管理费用', 14, '[{"operator":"+","rules":5,"subjectId":1486,"subjectName":"管理费用","subjectNumber":"5602"}]', NULL, 1, 12, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(72, '其中:开办费', 15, '[{"operator":"+","rules":5,"subjectId":1499,"subjectName":"开办费","subjectNumber":"560213"}]', NULL, 1, 13, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(73, '业务招待费', 16, '[{"operator":"+","rules":5,"subjectId":1491,"subjectName":"交际应酬费","subjectNumber":"560205"}]', NULL, 1, 14, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(74, '研究费用', 17, '[{"operator":"+","rules":5,"subjectId":1501,"subjectName":"研究费用","subjectNumber":"560215"}]', NULL, 1, 15, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(75, '财务费用', 18, '[{"operator":"+","rules":5,"subjectId":1503,"subjectName":"财务费用","subjectNumber":"5603"}]', NULL, 1, 16, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(76, '其中:利息费用(收入以“-”号填列)', 19, '[{"operator":"+","rules":5,"subjectId":1505,"subjectName":"利息","subjectNumber":"560302"}]', NULL, 1, 17, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(77, '加:投资收益(损失以“-”号填列)', 20, '[{"operator":"+","rules":6,"subjectId":1446,"subjectName":"投资收益","subjectNumber":"5111"}]', NULL, 1, 18, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(78, '二、营业利润(亏损以“-”号填列)', 21, '["L1-L2-L3-L11-L14-L18+L20"]', NULL, 0, 19, NULL, 2, NULL, '2021-09-18 16:39:56', 1),(79, '加:营业外收入', 22, '[{"operator":"+","rules":6,"subjectId":1447,"subjectName":"营业外收入","subjectNumber":"5301"}]', NULL, 1, 20, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(80, '其中:政府补助', 23, '[{"operator":"+","rules":6,"subjectId":1449,"subjectName":"政府补助","subjectNumber":"530102"}]', NULL, 1, 21, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(81, '减:营业外支出', 24, '[{"operator":"+","rules":5,"subjectId":1508,"subjectName":"营业外支出","subjectNumber":"5711"}]', NULL, 1, 22, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(82, '其中:坏账损失', 25, '[{"operator":"+","rules":5,"subjectId":1511,"subjectName":"坏账损失","subjectNumber":"571103"}]', NULL, 1, 23, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(83, '无法收回的长期债券投资损失', 26, '[{"operator":"+","rules":5,"subjectId":1512,"subjectName":"无法收回的长期债券投资损失","subjectNumber":"571104"}]', NULL, 1, 24, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(84, '无法收回的长期股权投资损失', 27, '[{"operator":"+","rules":5,"subjectId":1513,"subjectName":"无法收回的长期股权投资损失","subjectNumber":"571105"}]', NULL, 1, 25, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(85, '自然灾害等不可抗力因素造成的损失', 28, '[{"operator":"+","rules":5,"subjectId":1514,"subjectName":"自然灾害等不可抗力造成的损失","subjectNumber":"571106"}]', NULL, 1, 26, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(86, '税收滞纳金', 29, '[{"operator":"+","rules":5,"subjectId":1515,"subjectName":"税收滞纳金","subjectNumber":"571107"}]', NULL, 1, 27, NULL, 2, NULL, '2021-09-18 16:39:56', 3), +(87, '三、利润总额(亏损总额以“-”号填列)', 30, '["L21+L22-L24"]', NULL, 0, 28, NULL, 2, NULL, '2021-09-18 16:39:56', 1), +(88, '减:所得税费用', 31, '[{"operator":"+","rules":5,"subjectId":1519,"subjectName":"所得税费用","subjectNumber":"5801"}]', NULL, 1, 29, NULL, 2, NULL, '2021-09-18 16:39:56', 2), +(89, '四、净利润(净亏损以“-”号填列)', 32, '["L30-L31"]', NULL, 0, 30, NULL, 2, NULL, '2021-09-18 16:39:56', 1); + +INSERT IGNORE INTO `fms_report_template` (`id`, `name`, `row_no`, `formula`, `remark`, `editable`, `sort`, `row_id`, `type`, `category`, `create_time`, `level`) VALUES +(90, '一、经营活动产生的现金流量:', 0, '[]', NULL, 0, 0, 0, 3, 1, '2021-09-18 16:39:59', 1), +(91, '销售产成品、商品、提供劳务收到的现金', 1, '["IN1-((BA[3,2]-BA[3,1])+(BA[4,2]-BA[4,1])-(BA[34,2]-BA[34,1]))+EX5+EX11"]', NULL, 0, 1, 1, 3, 1, '2021-09-18 16:39:59', 2), +(92, '收到其他与经营活动有关的现金', 2, '["((IN22-(BA[8,2]-BA[8,1])) < 0 ? 0 : (IN22-(BA[8,2]-BA[8,1])))"]', NULL, 0, 2, 2, 3, 1, '2021-09-18 16:39:59', 2), +(93, '购买原材料、商品、接受劳务支付的现金', 3, '["IN2+(BA[9,2]-BA[9,1])-(BA[32,2]-BA[32,1])-(BA[33,2]-BA[33,1])+(BA[5,2]-BA[5,1])+EX6"]', NULL, 0, 3, 3, 3, 1, '2021-09-18 16:39:59', 2), +(94, '支付的职工薪酬', 4, '["EX4"]', NULL, 0, 4, 4, 3, 1, '2021-09-18 16:39:59', 2), +(95, '支付的税费', 5, '["EX12-(BA[36,2]-BA[36,1])"]', NULL, 0, 5, 5, 3, 1, '2021-09-18 16:39:59', 2), +(96, '支付其他与经营活动有关的现金', 6, '["(((IN24+IN14+IN11+IN18+IN3+IN19)-(EX15+EX16+EX4+EX18+EX14+EX17+EX13+EX10+EX9+EX8-EX19)+(BA[14,2]-BA[14,1])-(BA[39,2]-BA[39,1]-(BA[35,2]-BA[35,1])-(BA[40,2]-BA[40,1]))) < 0 ? 0 : ((IN24+IN14+IN11+IN18+IN3+IN19)-(EX15+EX16+EX4+EX18+EX14+EX17+EX13+EX10+EX9+EX8-EX19)+(BA[14,2]-BA[14,1])-(BA[39,2]-BA[39,1]-(BA[35,2]-BA[35,1])-(BA[40,2]-BA[40,1]))))"]', NULL, 0, 6, 6, 3, 1, '2021-09-18 16:39:59', 2), +(97, '经营活动产生的现金流量净额', 7, '["L1+L2-L3-L4-L5-L6"]', NULL, 0, 7, 7, 3, 1, '2021-09-18 16:39:59', 2), +(98, '二、投资活动产生的现金流量:', 0, '[]', NULL, 0, 8, 8, 3, 1, '2021-09-18 16:39:59', 1), +(99, '收回短期投资、长期债券投资和长期股权投资收到的现金', 8, '["((BA[2,2]-BA[2,1])+(BA[16,2]-BA[16,1])+(BA[17,2]-BA[17,1]))*(-1) < 0 ? 0 : ((BA[2,2]-BA[2,1])+(BA[16,2]-BA[16,1])+(BA[17,2]-BA[17,1]))*(-1)"]', NULL, 0, 9, 9, 3, 1, '2021-09-18 16:39:59', 2), +(100, '取得投资收益收到的现金', 9, '["IN20-((BA[7,2]-BA[7,1])+(BA[6,2]-BA[6,1]))"]', NULL, 0, 10, 10, 3, 1, '2021-09-18 16:39:59', 2), +(101, '处置固定资产、无形资产和其他非流动资产收回的现金净额', 10, '[]', NULL, 0, 11, 11, 3, 1, '2021-09-18 16:39:59', 2), +(102, '短期投资、长期债券投资和长期股权投资支付的现金', 11, '["(((BA[2,2]-BA[2,1])+(BA[16,2]-BA[16,1])+(BA[17,2]-BA[17,1]))*(-1)) < 0 ? (((BA[2,2]-BA[2,1])+(BA[16,2]-BA[16,1])+(BA[17,2]-BA[17,1]))*(-1))*(-1) : 0"]', NULL, 0, 12, 12, 3, 1, '2021-09-18 16:39:59', 2), +(103, '购建固定资产、无形资产和其他非流动资产支付的现金', 12, '["((BA[21,2]-BA[21,1])+(BA[20,2]-BA[20,1])+(BA[25,2]-BA[25,1])+(BA[28,2]-BA[28,1])+(BA[23,2]-BA[23,1])+(BA[22,2]-BA[22,1])+(BA[26,2]-BA[26,1])+(BA[27,2]-BA[27,1])+(BA[24,2]-BA[24,1]))+(EX15+EX16+EX18)+(EX13+EX17)"]', NULL, 0, 13, 13, 3, 1, '2021-09-18 16:39:59', 2), +(104, '投资活动产生的现金流量净额', 13, '["L8+L9+L10-L11-L12"]', NULL, 0, 14, 14, 3, 1, '2021-09-18 16:39:59', 2), +(105, '三、筹资活动产生的现金流量:', 0, '[]', NULL, 0, 15, 15, 3, 1, '2021-09-18 16:39:59', 1), +(106, '取得借款收到的现金', 14, '["((BA[31,2]-BA[31,1])+(BA[42,2]-BA[42,1])+(BA[43,2]-BA[43,1])+(BA[44,2]-BA[44,1])+(BA[45,2]-BA[45,1])) < 0 ? 0 : ((BA[31,2]-BA[31,1])+(BA[42,2]-BA[42,1])+(BA[43,2]-BA[43,1])+(BA[44,2]-BA[44,1])+(BA[45,2]-BA[45,1]))"]', NULL, 0, 16, 16, 3, 1, '2021-09-18 16:39:59', 2), +(107, '吸收投资者投资收到的现金', 15, '["(BA[48,2]-BA[48,1])+(BA[49,2]-BA[49,1])+(BA[50,2]-BA[50,1])"]', NULL, 0, 17, 17, 3, 1, '2021-09-18 16:39:59', 2), +(108, '偿还借款本金支付的现金', 16, '["((BA[31,2]-BA[31,1])+(BA[42,2]-BA[42,1])+(BA[43,2]-BA[43,1])+(BA[44,2]-BA[44,1])+(BA[45,2]-BA[45,1])) < 0 ? ((BA[31,2]-BA[31,1])+(BA[42,2]-BA[42,1])+(BA[43,2]-BA[43,1])+(BA[44,2]-BA[44,1])+(BA[45,2]-BA[45,1]))*(-1) : 0"]', NULL, 0, 18, 18, 3, 1, '2021-09-18 16:39:59', 2), +(109, '偿还借款利息支付的现金', 17, '["IN19-(BA[37,2]-BA[37,1])"]', NULL, 0, 19, 19, 3, 1, '2021-09-18 16:39:59', 2), +(110, '分配利润支付的现金', 18, '["IN32-((BA[38,2]-BA[38,1])+(BA[51,2]-BA[51,1]))"]', NULL, 0, 20, 20, 3, 1, '2021-09-18 16:39:59', 2), +(111, '筹资活动产生的现金流量净额', 19, '["L14+L15-L16-L17-L18"]', NULL, 0, 21, 21, 3, 1, '2021-09-18 16:39:59', 2),(112, '四、现金净增加额', 20, '["L7+L13+L19"]', NULL, 0, 22, 22, 3, 1, '2021-09-18 16:39:59', 1), +(113, '加:期初现金余额', 21, '["BA[1,1]"]', NULL, 0, 23, 23, 3, 1, '2021-09-18 16:39:59', 2), +(114, '五、期末现金余额', 22, '["L20+L21"]', NULL, 0, 24, 24, 3, 1, '2021-09-18 16:39:59', 1); + +INSERT IGNORE INTO `fms_report_template` (`id`, `name`, `row_no`, `formula`, `remark`, `editable`, `sort`, `row_id`, `type`, `category`, `create_time`, `level`) VALUES +(115, '支付给职工的工资', 1, '[{"operator":"+","rules":5,"subjectId":1379,"subjectName":"应付职工薪酬","subjectNumber":"2211"}]', NULL, 1, 0, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(116, '支付给职工的四金', 2, '[]', NULL, 1, 1, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(117, '支付给职工的其他福利费', 3, '[]', NULL, 1, 2, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(118, '支付给职工以及为职工支付的现金', 4, '["L1+L2+L3"]', '行 1、2、3 之和,参与现金流量表行 4 计算', 0, 3, NULL, 4, 1, '2021-09-18 16:40:02', 2), +(119, '销项税额(小规模纳税人填本年累计应交增值税)', 5, '[{"operator":"+","rules":6,"subjectId":1388,"subjectName":"销项税额","subjectNumber":"22210107"}]', '参与现金流量表行 1 计算', 1, 4, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(120, '进项税额(小规模纳税人不填此项)', 6, '[{"operator":"+","rules":5,"subjectId":1382,"subjectName":"进项税额","subjectNumber":"22210101"}]', '参与现金流量表行 3 计算', 1, 5, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(121, '应交增值税', 7, '["L5-L6"]', '行 5、6 之差', 0, 6, NULL, 4, 1, '2021-09-18 16:40:02', 2), +(122, '主营业务税金及附加', 8, '[{"operator":"+","rules":7,"subjectId":1455,"subjectName":"税金及附加","subjectNumber":"5403"}]', '参与现金流量表行 6 计算', 1, 7, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(123, '所得税', 9, '[{"operator":"+","rules":7,"subjectId":1519,"subjectName":"所得税费用","subjectNumber":"5801"}]', '参与现金流量表行 6 计算', 1, 8, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(124, '管理费用中列支的税金', 10, '[]', '参与现金流量表行 6 计算', 1, 9, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(125, '在其他业务支出中列支的税金', 11, '[]', '参与现金流量表行 1 计算', 1, 10, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(126, '应缴纳各项税金合计', 12, '["L7+L8+L9+L10+L11"]', '行 7、8、9、10、11 之和,参与现金流量表行 5 计算', 0, 11, NULL, 4, 1, '2021-09-18 16:40:02', 2), +(127, '计提固定资产折旧', 13, '[{"operator":"+","rules":6,"subjectId":1370,"subjectName":"生产性生物资产累计折旧","subjectNumber":"1622"},{"operator":"+","rules":6,"subjectId":1361,"subjectName":"累计折旧","subjectNumber":"1602"}]', '参与现金流量表行 6、12 计算', 1, 12, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(128, '利息支出', 14, '[{"operator":"+","rules":7,"subjectId":1505,"subjectName":"利息","subjectNumber":"560302"}]', '参与现金流量表行 6 计算', 1, 13, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(129, '无形资产摊销', 15, '[]', '参与现金流量表行 6、12 计算', 1, 14, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(130, '长期待摊费用摊销', 16, '[]', '参与现金流量表行 6、12 计算', 1, 15, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(131, '计提的各项减值准备(仅反映本年与上年计提的差额)', 17, '[]', '参与现金流量表行 12 计算', 1, 16, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(132, '处置固定资产、无形资产和其他长期资产的损失(减:收益)', 18, '[]', '参与现金流量表行 6、12 计算', 1, 17, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(133, '汇兑收益(减:汇兑损失)', 19, '[]', '参与现金流量表行 6 计算', 1, 18, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(134, '不涉及现金收支的投资活动', 20, '[]', '参与现金流量表行 8 计算', 1, 19, NULL, 4, 1, '2021-09-18 16:40:02', 1), +(135, '不涉及现金收支的筹资活动', 21, '[]', '参与现金流量表行 15 计算', 1, 20, NULL, 4, 1, '2021-09-18 16:40:02', 1); + +-- 修正旧版默认公式;仅匹配原始公式,保留用户自定义内容 +UPDATE `fms_report_template` SET `formula` = '[{"operator":"+","rules":0,"subjectId":1345,"subjectName":"材料采购","subjectNumber":"1401"},{"operator":"+","rules":0,"subjectId":1346,"subjectName":"在途物资","subjectNumber":"1402"},{"operator":"+","rules":0,"subjectId":1347,"subjectName":"原材料","subjectNumber":"1403"},{"operator":"+","rules":0,"subjectId":1348,"subjectName":"材料成本差异","subjectNumber":"1404"},{"operator":"+","rules":0,"subjectId":1349,"subjectName":"库存商品","subjectNumber":"1405"},{"operator":"-","rules":0,"subjectId":1350,"subjectName":"商品进销差价","subjectNumber":"1407"},{"operator":"+","rules":0,"subjectId":1351,"subjectName":"委托加工物资","subjectNumber":"1408"},{"operator":"+","rules":0,"subjectId":1352,"subjectName":"周转材料","subjectNumber":"1411"},{"operator":"+","rules":0,"subjectId":1353,"subjectName":"消耗性生物资产","subjectNumber":"1421"},{"operator":"+","rules":0,"subjectId":1437,"subjectName":"生产成本","subjectNumber":"4001"},{"operator":"+","rules":0,"subjectId":1440,"subjectName":"制造费用","subjectNumber":"4101"},{"operator":"+","rules":0,"subjectId":1442,"subjectName":"工程施工","subjectNumber":"4401"},{"operator":"+","rules":0,"subjectId":1443,"subjectName":"机械作业","subjectNumber":"4403"}]' WHERE `id` = 19 AND `formula` = '[{"operator":"+","rules":0,"subjectId":1345,"subjectName":"材料采购","subjectNumber":"1401"},{"operator":"+","rules":0,"subjectId":1346,"subjectName":"在途物资","subjectNumber":"1402"},{"operator":"+","rules":0,"subjectId":1347,"subjectName":"原材料","subjectNumber":"1403"},{"operator":"+","rules":0,"subjectId":1348,"subjectName":"材料成本差异","subjectNumber":"1404"},{"operator":"+","rules":0,"subjectId":1349,"subjectName":"库存商品","subjectNumber":"1405"},{"operator":"+","rules":0,"subjectId":1350,"subjectName":"商品进销差价","subjectNumber":"1407"},{"operator":"+","rules":0,"subjectId":1351,"subjectName":"委托加工物资","subjectNumber":"1408"},{"operator":"+","rules":0,"subjectId":1352,"subjectName":"周转材料","subjectNumber":"1411"},{"operator":"+","rules":0,"subjectId":1353,"subjectName":"消耗性生物资产","subjectNumber":"1421"},{"operator":"+","rules":0,"subjectId":1437,"subjectName":"生产成本","subjectNumber":"4001"},{"operator":"+","rules":0,"subjectId":1440,"subjectName":"制造费用","subjectNumber":"4101"},{"operator":"+","rules":0,"subjectId":1442,"subjectName":"工程施工","subjectNumber":"4401"},{"operator":"+","rules":0,"subjectId":1443,"subjectName":"机械作业","subjectNumber":"4403"}]'; +UPDATE `fms_report_template` SET `formula` = '[{"operator":"+","rules":0,"subjectId":1369,"subjectName":"生产性生物资产","subjectNumber":"1621"},{"operator":"-","rules":0,"subjectId":1370,"subjectName":"生产性生物资产累计折旧","subjectNumber":"1622"}]' WHERE `id` = 45 AND `formula` = '[{"operator":"+","rules":0,"subjectId":1369,"subjectName":"生产性生物资产","subjectNumber":"1621"},{"operator":"+","rules":0,"subjectId":1370,"subjectName":"生产性生物资产累计折旧","subjectNumber":"1622"}]'; +UPDATE `fms_report_template` SET `formula` = '[{"operator":"+","rules":0,"subjectId":1371,"subjectName":"无形资产","subjectNumber":"1701"},{"operator":"-","rules":0,"subjectId":1372,"subjectName":"累计摊销","subjectNumber":"1702"}]' WHERE `id` = 47 AND `formula` = '[{"operator":"+","rules":0,"subjectId":1371,"subjectName":"无形资产","subjectNumber":"1701"},{"operator":"+","rules":0,"subjectId":1372,"subjectName":"累计摊销","subjectNumber":"1702"}]'; +UPDATE `fms_report_template` SET `formula` = '["L1-L2-L3-L11-L14-L18+L20"]' WHERE `id` = 78 AND `formula` = '["L1-L2-L3-L11-L14-L18"]'; +UPDATE `fms_report_template` SET `formula` = '["L14+L15-L16-L17-L18"]' WHERE `id` = 111 AND `formula` = '["L14+L15-L17-L18"]'; diff --git a/yudao-module-fms/src/test/java/cn/iocoder/yudao/module/fms/service/report/FmsReportTemplateServiceTest.java b/yudao-module-fms/src/test/java/cn/iocoder/yudao/module/fms/service/report/FmsReportTemplateServiceTest.java new file mode 100644 index 0000000..f5205ed --- /dev/null +++ b/yudao-module-fms/src/test/java/cn/iocoder/yudao/module/fms/service/report/FmsReportTemplateServiceTest.java @@ -0,0 +1,381 @@ +package cn.iocoder.yudao.module.fms.service.report; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.subjectbalance.FmsLedgerSubjectBalanceRespVO; +import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportItemRespVO; +import cn.iocoder.yudao.module.fms.controller.admin.report.vo.FmsReportListReqVO; +import cn.iocoder.yudao.module.fms.controller.admin.report.vo.balance.FmsBalanceSheetRowRespVO; +import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsAccountSetDO; +import cn.iocoder.yudao.module.fms.dal.dataobject.config.FmsSubjectDO; +import cn.iocoder.yudao.module.fms.dal.dataobject.report.FmsReportTemplateDO; +import cn.iocoder.yudao.module.fms.dal.mysql.report.FmsReportTemplateMapper; +import cn.iocoder.yudao.module.fms.enums.report.FmsReportTypeEnum; +import cn.iocoder.yudao.module.fms.service.closing.FmsClosingPeriodService; +import cn.iocoder.yudao.module.fms.service.closing.FmsClosingSchemeService; +import cn.iocoder.yudao.module.fms.service.closing.FmsClosingVoucherService; +import cn.iocoder.yudao.module.fms.service.config.FmsAccountSetService; +import cn.iocoder.yudao.module.fms.service.config.FmsFinanceParameterService; +import cn.iocoder.yudao.module.fms.service.config.FmsInitialBalanceService; +import cn.iocoder.yudao.module.fms.service.config.FmsSubjectService; +import cn.iocoder.yudao.module.fms.service.ledger.FmsLedgerService; +import cn.iocoder.yudao.module.fms.service.voucher.FmsVoucherService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.core.io.FileSystemResource; +import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import javax.sql.DataSource; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +@Import({FmsBalanceSheetServiceImpl.class, FmsIncomeStatementServiceImpl.class, + FmsCashFlowStatementServiceImpl.class, FmsReportCommonServiceImpl.class}) +public class FmsReportTemplateServiceTest extends BaseDbUnitTest { + + @Resource + private DataSource dataSource; + @Resource + private FmsReportTemplateMapper reportTemplateMapper; + @Resource + private FmsBalanceSheetServiceImpl balanceSheetService; + @Resource + private FmsIncomeStatementServiceImpl incomeStatementService; + @Resource + private FmsCashFlowStatementServiceImpl cashFlowStatementService; + + @MockitoBean + private FmsAccountSetService accountSetService; + @MockitoBean + private FmsSubjectService subjectService; + @MockitoBean + private FmsLedgerService ledgerService; + @MockitoBean + private FmsFinanceParameterService financeParameterService; + @MockitoBean + private FmsInitialBalanceService initialBalanceService; + @MockitoBean + private FmsClosingPeriodService closingPeriodService; + @MockitoBean + private FmsClosingSchemeService closingSchemeService; + @MockitoBean + private FmsClosingVoucherService closingVoucherService; + @MockitoBean + private FmsVoucherService voucherService; + + private final List subjects = new ArrayList<>(); + private final List balances = new ArrayList<>(); + + @BeforeEach + public void before() { + // 初始化报表模板 + initializeTemplates(); + // mock 账套、科目和账簿余额 + FmsAccountSetDO accountSet = new FmsAccountSetDO().setId(1L).setInitialized(true) + .setStartTime(LocalDateTime.of(2026, 1, 1, 0, 0)); + when(accountSetService.validateAccountSetReadPermission(1L, 10L)).thenReturn(accountSet); + when(subjectService.getSubjectList(1L, null, 10L)).thenReturn(subjects); + when(ledgerService.getSubjectBalanceList(any(), eq(10L))).thenReturn(balances); + } + + @Test + public void testInitializeTemplates_repeatExecution() { + // mock 数据:模拟用户修改已有报表公式 + FmsReportTemplateDO template = CollUtil.findOne( + reportTemplateMapper.selectListByType(FmsReportTypeEnum.INCOME_STATEMENT.getType()), + item -> Integer.valueOf(21).equals(item.getRowNo())); + reportTemplateMapper.updateById(new FmsReportTemplateDO().setId(template.getId()).setFormula("[\"L1\"]")); + + // 调用 + initializeTemplates(); + + // 断言 + assertEquals(58, reportTemplateMapper.selectListByType(FmsReportTypeEnum.BALANCE_SHEET.getType()).size()); + assertEquals(31, reportTemplateMapper.selectListByType(FmsReportTypeEnum.INCOME_STATEMENT.getType()).size()); + assertEquals(25, reportTemplateMapper.selectListByType(FmsReportTypeEnum.CASH_FLOW_STATEMENT.getType()).size()); + assertEquals(21, reportTemplateMapper.selectListByType(FmsReportTypeEnum.CASH_FLOW_ADJUSTMENT.getType()).size()); + assertEquals(135, reportTemplateMapper.selectCount()); + assertEquals("[\"L1\"]", reportTemplateMapper.selectById(template.getId()).getFormula()); + } + + @Test + public void testInitializeTemplates_preserveExistingFormulas() { + // mock 数据:模拟旧版报表公式 + List templates = new ArrayList<>(); + for (FmsReportTemplateDO template : reportTemplateMapper.selectList()) { + String oldFormula; + if (FmsReportTypeEnum.BALANCE_SHEET.getType().equals(template.getType()) && (template.getRowNo() == 9 + || template.getRowNo() == 24 || template.getRowNo() == 25)) { + oldFormula = template.getFormula().replace("\"operator\":\"-\"", "\"operator\":\"+\""); + } else if (FmsReportTypeEnum.INCOME_STATEMENT.getType().equals(template.getType()) + && template.getRowNo() == 21) { + oldFormula = "[\"L1-L2-L3-L11-L14-L18\"]"; + } else if (FmsReportTypeEnum.CASH_FLOW_STATEMENT.getType().equals(template.getType()) + && template.getRowNo() == 19) { + oldFormula = "[\"L14+L15-L17-L18\"]"; + } else { + continue; + } + templates.add(template); + reportTemplateMapper.updateById(new FmsReportTemplateDO().setId(template.getId()).setFormula(oldFormula)); + } + + // 调用 + initializeTemplates(); + + // 断言 + assertEquals(5, templates.size()); + for (FmsReportTemplateDO template : templates) { + assertEquals(template.getFormula(), reportTemplateMapper.selectById(template.getId()).getFormula()); + } + assertEquals(135, reportTemplateMapper.selectCount()); + } + + @Test + public void testInitializeTemplates_preserveLegacySubjectIds() { + // mock 数据:模拟使用历史科目编号的公式 + FmsReportTemplateDO template = CollUtil.findOne( + reportTemplateMapper.selectListByType(FmsReportTypeEnum.BALANCE_SHEET.getType()), + item -> Integer.valueOf(25).equals(item.getRowNo())); + String oldFormula = "[{\"operator\":\"+\",\"rules\":0,\"subjectId\":1371," + + "\"subjectName\":\"无形资产\",\"subjectNumber\":\"1701\"}," + + "{\"operator\":\"+\",\"rules\":0,\"subjectId\":1372," + + "\"subjectName\":\"累计摊销\",\"subjectNumber\":\"1702\"}]"; + reportTemplateMapper.updateById(new FmsReportTemplateDO().setId(template.getId()).setFormula(oldFormula)); + + // 调用 + initializeTemplates(); + + // 断言 + assertEquals(template.getFormula(), reportTemplateMapper.selectById(template.getId()).getFormula()); + } + + @Test + public void testGetBalanceSheet_capitalContribution() { + // mock 数据:投入资本 100 元 + mockSubjectBalance("1001", 1, 0, 100, 100, 0); + mockSubjectBalance("3001", 2, 0, -100, 0, 100); + + // 准备参数 + FmsReportListReqVO reqVO = buildQueryReqVO(); + + // 调用 + List balanceSheet = balanceSheetService.getBalanceSheet(reqVO, 10L); + List cashFlow = cashFlowStatementService.getCashFlowStatement(reqVO, 10L); + + // 断言 + assertAssetAmount(balanceSheet, 30, 100); + FmsBalanceSheetRowRespVO total = CollUtil.findOne(balanceSheet, + row -> Integer.valueOf(53).equals(row.getLiabilityRowNo())); + assertNotNull(total); + assertAmount(100, total.getLiabilityClosingAmount()); + assertItemAmount(cashFlow, 15, 100); + assertItemAmount(cashFlow, 22, 100); + } + + @Test + public void testGetBalanceSheet_inventoryAndContraAccounts() { + // mock 数据:存货、固定资产、无形资产及其备抵科目 + mockSubjectBalance("1403", 1, 0, 30, 30, 0); + mockSubjectBalance("1407", 2, 0, -5, 0, 5); + mockSubjectBalance("1621", 1, 0, 100, 100, 0); + mockSubjectBalance("1622", 2, 0, -20, 0, 20); + mockSubjectBalance("1701", 1, 0, 100, 100, 0); + mockSubjectBalance("1702", 2, 0, -10, 0, 10); + + // 准备参数 + FmsReportListReqVO reqVO = buildQueryReqVO(); + + // 调用 + List result = balanceSheetService.getBalanceSheet(reqVO, 10L); + + // 断言 + assertAssetAmount(result, 9, 25); + assertAssetAmount(result, 24, 80); + assertAssetAmount(result, 25, 90); + assertAssetAmount(result, 30, 195); + } + + @Test + public void testGetCashFlowStatement_creditSale() { + // mock 数据:赊销 100 元并结转利润,尚未收款 + mockSubjectBalance("1001", 1, 0, 0, 0, 0); + mockSubjectBalance("1122", 1, 0, 100, 100, 0); + mockSubjectBalance("5001", 2, 0, 0, 0, 100); + mockSubjectBalance("3103", 2, 0, -100, 0, 100); + + // 准备参数 + FmsReportListReqVO reqVO = buildQueryReqVO(); + + // 调用 + List incomeItems = incomeStatementService.getIncomeStatement(reqVO, 10L); + List result = cashFlowStatementService.getCashFlowStatement(reqVO, 10L); + + // 断言 + assertItemAmount(incomeItems, 1, 100); + assertItemAmount(result, 1, 0); + assertItemAmount(result, 6, 0); + assertItemAmount(result, 20, 0); + assertItemAmount(result, 22, 0); + } + + @Test + public void testGetCashFlowStatement_purchaseInventory() { + // mock 数据:期初现金 100 元,支付 40 元购入原材料 + mockSubjectBalance("1001", 1, 100, 60, 0, 40); + mockSubjectBalance("1403", 1, 0, 40, 40, 0); + mockSubjectBalance("3001", 2, -100, -100, 0, 0); + + // 准备参数 + FmsReportListReqVO reqVO = buildQueryReqVO(); + + // 调用 + List result = cashFlowStatementService.getCashFlowStatement(reqVO, 10L); + + // 断言 + assertItemAmount(result, 3, 40); + assertItemAmount(result, 6, 0); + assertItemAmount(result, 20, -40); + assertItemAmount(result, 22, 60); + } + + @Test + public void testGetCashFlowStatement_payWagesAndIncomeTax() { + // mock 数据:计提并支付工资 30 元、所得税 10 元,期末应付款为零 + mockSubjectBalance("1001", 1, 100, 60, 0, 40); + mockSubjectBalance("3001", 2, -100, -100, 0, 0); + mockSubjectBalance("3103", 2, 0, 40, 40, 0); + mockSubjectBalance("5602", 1, 0, 0, 30, 0); + mockSubjectBalance("5801", 1, 0, 0, 10, 0); + mockSubjectBalance("2211", 2, 0, 0, 30, 30); + mockSubjectBalance("2221", 2, 0, 0, 10, 10); + + // 准备参数 + FmsReportListReqVO reqVO = buildQueryReqVO(); + + // 调用 + List result = cashFlowStatementService.getCashFlowStatement(reqVO, 10L); + + // 断言 + assertItemAmount(result, 4, 30); + assertItemAmount(result, 5, 10); + assertItemAmount(result, 6, 0); + assertItemAmount(result, 20, -40); + assertItemAmount(result, 22, 60); + } + + @Test + public void testGetCashFlowStatement_repayLoan() { + // mock 数据:期初现金 100 元,偿还借款 30 元 + mockSubjectBalance("1001", 1, 100, 70, 0, 30); + mockSubjectBalance("2001", 2, -100, -70, 30, 0); + + // 准备参数 + FmsReportListReqVO reqVO = buildQueryReqVO(); + + // 调用 + List result = cashFlowStatementService.getCashFlowStatement(reqVO, 10L); + + // 断言 + assertItemAmount(result, 16, 30); + assertItemAmount(result, 19, -30); + assertItemAmount(result, 6, 0); + assertItemAmount(result, 22, 70); + } + + @Test + public void testGetIncomeStatement_investmentIncomeAndNonOperatingExpense() { + // mock 数据:投资收益 20 元,营业外支出 5 元 + mockSubjectBalance("5111", 2, 0, -20, 0, 20); + mockSubjectBalance("5711", 1, 0, 5, 5, 0); + + // 准备参数 + FmsReportListReqVO reqVO = buildQueryReqVO(); + + // 调用 + List result = incomeStatementService.getIncomeStatement(reqVO, 10L); + + // 断言 + assertItemAmount(result, 20, 20); + assertItemAmount(result, 21, 20); + assertItemAmount(result, 24, 5); + assertItemAmount(result, 32, 15); + } + + /** + * 执行报表模板升级脚本 + */ + private void initializeTemplates() { + new ResourceDatabasePopulator(new FileSystemResource("../sql/mysql/upgrade/20260926-fms-report-template.sql")) + .execute(dataSource); + } + + /** + * 模拟科目余额和发生额:余额借方为正、贷方为负,发生额已扣除损益结转数据 + */ + private void mockSubjectBalance(String code, int direction, int opening, int closing, int debit, int credit) { + Long id = Long.valueOf(code); + subjects.add(new FmsSubjectDO().setId(id).setAccountSetId(1L).setCode(code).setName(code) + .setLevel(1).setBalanceDirection(direction)); + balances.add(new FmsLedgerSubjectBalanceRespVO().setSubjectId(id).setSubjectCode(code) + .setOpeningDebitAmount(BigDecimal.valueOf(Math.max(opening, 0))) + .setOpeningCreditAmount(BigDecimal.valueOf(Math.max(-opening, 0))) + .setEndingDebitAmount(BigDecimal.valueOf(Math.max(closing, 0))) + .setEndingCreditAmount(BigDecimal.valueOf(Math.max(-closing, 0))) + .setPeriodDebitAmount(BigDecimal.valueOf(debit)).setPeriodCreditAmount(BigDecimal.valueOf(credit)) + .setYearDebitAmount(BigDecimal.valueOf(debit)).setYearCreditAmount(BigDecimal.valueOf(credit)) + .setChildren(Collections.emptyList())); + } + + /** + * 构造 2026 年 8 月的报表查询参数 + */ + private FmsReportListReqVO buildQueryReqVO() { + FmsReportListReqVO reqVO = new FmsReportListReqVO(); + reqVO.setAccountSetId(1L); + reqVO.setStartMonth("2026-08"); + reqVO.setEndMonth("2026-08"); + return reqVO; + } + + /** + * 断言报表指定行的本期和本年金额 + */ + private void assertItemAmount(List rows, int rowNo, int expected) { + FmsReportItemRespVO item = CollUtil.findOne(rows, row -> Integer.valueOf(rowNo).equals(row.getRowNo())); + assertNotNull(item); + assertAmount(expected, item.getCurrentAmount()); + assertAmount(expected, item.getYearAmount()); + } + + /** + * 断言资产负债表指定行的资产期末余额 + */ + private void assertAssetAmount(List rows, int rowNo, int expected) { + FmsBalanceSheetRowRespVO item = CollUtil.findOne(rows, + row -> Integer.valueOf(rowNo).equals(row.getAssetRowNo())); + assertNotNull(item); + assertAmount(expected, item.getAssetClosingAmount()); + } + + /** + * 按数值比较金额,忽略 BigDecimal 的小数位数差异 + */ + private void assertAmount(int expected, BigDecimal actual) { + assertNotNull(actual); + assertEquals(0, BigDecimal.valueOf(expected).compareTo(actual), "实际金额:" + actual); + } + +} -- libgit2 0.21.4