AsyncMaterialSummaryService.java 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. package com.hotent.project.service;
  2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  3. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  4. import com.hotent.base.util.StringUtil;
  5. import com.hotent.project.manager.*;
  6. import com.hotent.project.model.*;
  7. import com.hotent.surveyinfo.manager.CostSurveyTemplateUploadManager;
  8. import com.hotent.surveyinfo.model.CostSurveyTemplateUpload;
  9. import org.apache.poi.xwpf.usermodel.XWPFDocument;
  10. import org.apache.poi.xwpf.usermodel.XWPFParagraph;
  11. import org.apache.poi.xwpf.usermodel.XWPFRun;
  12. import org.springframework.beans.factory.annotation.Autowired;
  13. import org.springframework.scheduling.annotation.Async;
  14. import org.springframework.stereotype.Service;
  15. import java.io.FileOutputStream;
  16. import java.util.Comparator;
  17. import java.util.List;
  18. import java.util.stream.Collectors;
  19. /**
  20. * 异步资料归纳服务
  21. *
  22. * @company 山西清众科技股份有限公司
  23. * @author 超级管理员
  24. * @since 2025-12-02
  25. */
  26. @Service
  27. public class AsyncMaterialSummaryService {
  28. @Autowired
  29. private CostProjectTaskMaterialSummaryManager costProjectTaskMaterialSummaryManager;
  30. @Autowired
  31. private CostProjectTaskMaterialSummaryDetailManager costProjectTaskMaterialSummaryDetailManager;
  32. @Autowired
  33. private CostProjectDocumentManager costProjectDocumentManager;
  34. @Autowired
  35. private CostProjectTaskManager costProjectTaskManager;
  36. @Autowired
  37. private CostSurveyTemplateUploadManager costSurveyTemplateUploadManager;
  38. @Autowired
  39. private CostProjectTaskMaterialManager costProjectTaskMaterialManager;
  40. @Autowired
  41. private CostProjectDeliberateManager costProjectDeliberateManager;
  42. @Autowired
  43. private CostProjectTaskAdjustmentRecordManager adjustmentRecordManager;
  44. @Autowired
  45. private CostProjectTaskEvidenceManager costProjectTaskEvidenceManager;
  46. @Autowired
  47. private CostProjectTaskPreliminaryOpinionManager preliminaryOpinionManager;
  48. /**
  49. * 生成资料归纳主表(13个基础资料类别)- 核心逻辑
  50. *
  51. * @param mainTask 主任务
  52. * @param childTasks 子任务列表
  53. */
  54. public void generateMaterialSummary(CostProjectTask mainTask, List<CostProjectTask> childTasks) {
  55. try {
  56. // 定义13个基础资料类别
  57. String[] materialNames = {
  58. "成本监审报告(含成本监审报告签发稿、送达回证)",
  59. "被监审单位申请定(调)价报告(复印件)",
  60. "成本监审通知书(含送达回证)",
  61. "经营者需提供成本资料清单",
  62. "《政府定价成本监审调查表》",
  63. "成本监审补充资料通知书(含送达回证)",
  64. "成本审核初步意见告知书(含送达回证)",
  65. "经营者书面反馈的材料",
  66. "成本审核初步意见表(集体审议用)",
  67. "成本监审集体审议记录",
  68. "成本监审工作底稿",
  69. "成本监审提取资料登记表",
  70. "提取的成本资料和会计凭证等复印件"
  71. };
  72. // 为主任务生成13个资料归纳主表记录
  73. for (int i = 0; i < materialNames.length; i++) {
  74. CostProjectTaskMaterialSummary summary = new CostProjectTaskMaterialSummary();
  75. summary.setTaskId(mainTask.getId());
  76. summary.setMaterialName(materialNames[i]);
  77. summary.setMaterialOrderNum(i + 1);
  78. summary.setIsDeleted("0");
  79. costProjectTaskMaterialSummaryManager.createOrUpdate(summary);
  80. // 根据不同的资料类别生成对应的明细记录
  81. generateDetailsByMaterialType(summary, mainTask, childTasks, i + 1);
  82. }
  83. } catch (Exception e) {
  84. // 记录异常日志,但不影响主流程
  85. e.printStackTrace();
  86. }
  87. }
  88. /**
  89. * 根据资料类别生成对应的明细记录
  90. *
  91. * @param summary 资料归纳主表
  92. * @param mainTask 主任务
  93. * @param childTasks 子任务列表
  94. * @param materialType 资料类别序号(1-13)
  95. */
  96. private void generateDetailsByMaterialType(CostProjectTaskMaterialSummary summary,
  97. CostProjectTask mainTask,
  98. List<CostProjectTask> childTasks,
  99. int materialType) {
  100. try {
  101. // 查询项目下的所有文书
  102. List<CostProjectDocument> documents = costProjectDocumentManager.getListByProjectId(mainTask.getProjectId());
  103. if (documents == null) {
  104. documents = new java.util.ArrayList<>();
  105. }
  106. switch (materialType) {
  107. case 1:
  108. // 成本监审报告(含成本监审报告签发稿、送达回证)
  109. generateType1Details(summary, mainTask, documents);
  110. break;
  111. case 2:
  112. // 被监审单位申请定(调)价报告(复印件)
  113. generateType2Details(summary, mainTask, childTasks, documents);
  114. break;
  115. case 3:
  116. // 成本监审通知书(含送达回证)
  117. generateType3Details(summary, mainTask, childTasks, documents);
  118. break;
  119. case 4:
  120. // 经营者需提供成本资料清单
  121. generateType4Details(summary, mainTask, childTasks, documents);
  122. break;
  123. case 5:
  124. // 《政府定价成本监审调查表》
  125. generateType5Details(summary, mainTask, childTasks, documents);
  126. break;
  127. case 6:
  128. // 成本监审补充资料通知书(含送达回证)
  129. generateType6Details(summary, mainTask, childTasks, documents);
  130. break;
  131. case 7:
  132. // 成本审核初步意见告知书(含送达回证)
  133. generateType7Details(summary, mainTask, childTasks, documents);
  134. break;
  135. case 8:
  136. // 经营者书面反馈的材料
  137. generateType8Details(summary, mainTask, childTasks, documents);
  138. break;
  139. case 9:
  140. // 成本审核初步意见表(集体审议用)
  141. generateType9Details(summary, mainTask, childTasks, documents);
  142. break;
  143. case 10:
  144. // 成本监审集体审议记录
  145. generateType10Details(summary, mainTask, documents);
  146. break;
  147. case 11:
  148. // 成本监审工作底稿
  149. generateType11Details(summary, mainTask, childTasks, documents);
  150. break;
  151. case 12:
  152. // 成本监审提取资料登记表
  153. generateType12Details(summary, mainTask, childTasks, documents);
  154. break;
  155. case 13:
  156. // 提取的成本资料和会计凭证等复印件
  157. generateType13Details(summary, mainTask, childTasks, documents);
  158. break;
  159. default:
  160. throw new RuntimeException("未知的资料类型");
  161. }
  162. } catch (Exception e) {
  163. System.err.println("生成资料类型 " + materialType + " 的明细时出错:" + e.getMessage());
  164. e.printStackTrace();
  165. // 继续执行,不中断整个流程
  166. }
  167. }
  168. // ==================== 类型1:成本监审报告(含成本监审报告签发稿、送达回证) ====================
  169. private void generateType1Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectDocument> documents) {
  170. int orderNum = 1;
  171. // 获取"成本监审报告"、"成本监审报告签发稿"、"送达回证"
  172. List<CostProjectDocument> matchedDocuments = documents.stream()
  173. .filter(doc -> "政府定价成本监审结论报告".equals(doc.getDocumentName()))
  174. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  175. .collect(Collectors.toList());
  176. for (CostProjectDocument document : matchedDocuments) {
  177. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  178. detail.setMasterId(summary.getId());
  179. detail.setTaskId(mainTask.getId());
  180. detail.setDocumentName(document.getDocumentName());
  181. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  182. detail.setAuditedUnitName("");
  183. detail.setFileSource("系统生成电子文书");
  184. detail.setPageCount(0);
  185. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  186. detail.setOrderNum(orderNum++);
  187. detail.setIsDeleted("0");
  188. costProjectTaskMaterialSummaryDetailManager.save(detail);
  189. }
  190. }
  191. // ==================== 类型2:被监审单位申请定(调)价报告(复印件) ====================
  192. private void generateType2Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  193. int orderNum = 1;
  194. // 获取"申请定(调)价报告"
  195. List<CostProjectDocument> matchedDocuments = documents.stream()
  196. .filter(doc -> "申请定(调)价报告".equals(doc.getDocumentName()))
  197. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  198. .collect(Collectors.toList());
  199. for (CostProjectDocument document : matchedDocuments) {
  200. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  201. detail.setMasterId(summary.getId());
  202. detail.setTaskId(mainTask.getId());
  203. detail.setDocumentName(document.getDocumentName());
  204. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  205. detail.setAuditedUnitName("");
  206. detail.setFileSource("监审主体上传文件");
  207. detail.setPageCount(0);
  208. detail.setAttachmentUrl(document.getScanDocumentUrl() != null ? document.getScanDocumentUrl() : "");
  209. detail.setOrderNum(orderNum++);
  210. detail.setIsDeleted("0");
  211. costProjectTaskMaterialSummaryDetailManager.save(detail);
  212. }
  213. }
  214. // ==================== 类型3:成本监审通知书(含送达回证) ====================
  215. private void generateType3Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  216. int orderNum = 1;
  217. // "成本监审通知书"和"送达回证"
  218. List<CostProjectDocument> matchedDocuments = documents.stream()
  219. .filter(doc -> "成本监审通知书".equals(doc.getDocumentName())
  220. || "送达回证".equals(doc.getDocumentName()))
  221. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  222. .collect(Collectors.toList());
  223. for (CostProjectDocument document : matchedDocuments) {
  224. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  225. detail.setMasterId(summary.getId());
  226. detail.setTaskId(mainTask.getId());
  227. detail.setDocumentName(document.getDocumentName());
  228. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  229. detail.setAuditedUnitName("");
  230. detail.setFileSource("系统生成电子文书");
  231. detail.setPageCount(0);
  232. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  233. detail.setOrderNum(orderNum++);
  234. detail.setIsDeleted("0");
  235. costProjectTaskMaterialSummaryDetailManager.save(detail);
  236. }
  237. }
  238. // ==================== 类型4:经营者需提供成本资料清单 ====================
  239. private void generateType4Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  240. int orderNum = 1;
  241. // 获取"成本资料清单"
  242. List<CostProjectDocument> matchedDocuments = documents.stream()
  243. .filter(doc -> "成本资料清单".equals(doc.getDocumentName()))
  244. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  245. .collect(Collectors.toList());
  246. for (CostProjectDocument document : matchedDocuments) {
  247. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  248. detail.setMasterId(summary.getId());
  249. detail.setTaskId(mainTask.getId());
  250. detail.setDocumentName(document.getDocumentName());
  251. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  252. detail.setAuditedUnitName("");
  253. detail.setFileSource("系统生成电子文书");
  254. detail.setPageCount(0);
  255. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  256. detail.setOrderNum(orderNum++);
  257. detail.setIsDeleted("0");
  258. costProjectTaskMaterialSummaryDetailManager.save(detail);
  259. }
  260. }
  261. // ==================== 类型5:《政府定价成本监审调查表》 ====================
  262. private void generateType5Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  263. int orderNum = 1;
  264. for (CostProjectTask childTask : childTasks) {
  265. List<CostSurveyTemplateUpload> costSurveyTemplateUploads = costSurveyTemplateUploadManager.listByTaskId(childTask.getId());
  266. for (CostSurveyTemplateUpload upload : costSurveyTemplateUploads) {
  267. if ("1".equals(upload.getIsUpload()) && StringUtil.isNotEmpty(upload.getFileUrl())) {
  268. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  269. detail.setMasterId(summary.getId());
  270. detail.setTaskId(mainTask.getId());
  271. detail.setDocumentName(upload.getSurveyTemplateName() != null ? upload.getSurveyTemplateName() : "政府定价成本监审调查表");
  272. detail.setDocumentNumber("");
  273. detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
  274. detail.setFileSource("监审单位反馈文件");
  275. detail.setPageCount(0);
  276. detail.setAttachmentUrl(upload.getFileUrl());
  277. detail.setOrderNum(orderNum++);
  278. detail.setIsDeleted("0");
  279. costProjectTaskMaterialSummaryDetailManager.save(detail);
  280. }
  281. }
  282. }
  283. }
  284. // ==================== 类型6:成本监审补充资料通知书(含送达回证) ====================
  285. private void generateType6Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  286. int orderNum = 1;
  287. List<CostProjectDocument> matchedDocuments = documents.stream()
  288. .filter(doc -> "成本监审补充资料通知书".equals(doc.getDocumentName())
  289. || "成本监审补充资料通知书-送达回证".equals(doc.getDocumentName()))
  290. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  291. .collect(Collectors.toList());
  292. for (CostProjectDocument document : matchedDocuments) {
  293. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  294. detail.setMasterId(summary.getId());
  295. detail.setTaskId(mainTask.getId());
  296. detail.setDocumentName(document.getDocumentName());
  297. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  298. detail.setAuditedUnitName("");
  299. detail.setFileSource("系统生成电子文书");
  300. detail.setPageCount(0);
  301. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  302. detail.setOrderNum(orderNum++);
  303. detail.setIsDeleted("0");
  304. costProjectTaskMaterialSummaryDetailManager.save(detail);
  305. }
  306. // 获取任务的报送资料要求(被监审单位提交的补充资料)
  307. List<CostProjectTaskMaterial> list = costProjectTaskMaterialManager.list(
  308. new LambdaQueryWrapper<>(CostProjectTaskMaterial.class)
  309. .eq(CostProjectTaskMaterial::getTaskId, mainTask.getId())
  310. );
  311. for (CostProjectTaskMaterial material : list) {
  312. // 只处理已上传的资料
  313. if ("1".equals(material.getIsUpload()) && StringUtil.isNotEmpty(material.getFileUrl())) {
  314. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  315. detail.setMasterId(summary.getId());
  316. detail.setTaskId(mainTask.getId());
  317. detail.setDocumentName(material.getInformationName() != null ? material.getInformationName() : "补充资料");
  318. detail.setDocumentNumber("");
  319. detail.setAuditedUnitName("");
  320. detail.setFileSource("监审单位反馈文件");
  321. detail.setPageCount(0);
  322. detail.setAttachmentUrl(material.getFileUrl());
  323. detail.setOrderNum(orderNum++);
  324. detail.setIsDeleted("0");
  325. costProjectTaskMaterialSummaryDetailManager.save(detail);
  326. }
  327. }
  328. }
  329. // ==================== 类型7:成本审核初步意见告知书(含送达回证) ====================
  330. private void generateType7Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  331. int orderNum = 1;
  332. // 获取"成本审核初步意见告知书"和"送达回证"
  333. List<CostProjectDocument> matchedDocuments = documents.stream()
  334. .filter(doc -> "成本审核初步意见告知书".equals(doc.getDocumentName())
  335. || "送达回证".equals(doc.getDocumentName()))
  336. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  337. .collect(Collectors.toList());
  338. for (CostProjectDocument document : matchedDocuments) {
  339. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  340. detail.setMasterId(summary.getId());
  341. detail.setTaskId(mainTask.getId());
  342. detail.setDocumentName(document.getDocumentName());
  343. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  344. detail.setAuditedUnitName("");
  345. detail.setFileSource("系统生成电子文书");
  346. detail.setPageCount(0);
  347. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  348. detail.setOrderNum(orderNum++);
  349. detail.setIsDeleted("0");
  350. costProjectTaskMaterialSummaryDetailManager.save(detail);
  351. }
  352. }
  353. // ==================== 类型8:经营者书面反馈的材料 ====================
  354. private void generateType8Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  355. int orderNum = 1;
  356. // 获取"书面反馈材料"(来源:监审单位反馈文件)
  357. List<CostProjectDocument> matchedDocuments = documents.stream()
  358. .filter(doc -> "书面反馈材料".equals(doc.getDocumentName()))
  359. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  360. .collect(Collectors.toList());
  361. for (CostProjectDocument document : matchedDocuments) {
  362. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  363. detail.setMasterId(summary.getId());
  364. detail.setTaskId(mainTask.getId());
  365. detail.setDocumentName(document.getDocumentName());
  366. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  367. detail.setAuditedUnitName("");
  368. detail.setFileSource("监审单位反馈文件");
  369. detail.setPageCount(0);
  370. detail.setAttachmentUrl(document.getFeedbackDocumentUrl() != null ? document.getFeedbackDocumentUrl() : "");
  371. detail.setOrderNum(orderNum++);
  372. detail.setIsDeleted("0");
  373. costProjectTaskMaterialSummaryDetailManager.save(detail);
  374. }
  375. // 获取被监审单位的反馈意见和反馈资料
  376. for (CostProjectTask childTask : childTasks) {
  377. List<CostProjectTaskPreliminaryOpinion> list = preliminaryOpinionManager.list(
  378. new LambdaQueryWrapper<>(CostProjectTaskPreliminaryOpinion.class)
  379. .eq(CostProjectTaskPreliminaryOpinion::getTaskId, childTask.getId())
  380. );
  381. for (CostProjectTaskPreliminaryOpinion opinion : list) {
  382. // 只处理有反馈资料的记录
  383. if (StringUtil.isNotEmpty(opinion.getFeedbackMaterials())) {
  384. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  385. detail.setMasterId(summary.getId());
  386. detail.setTaskId(mainTask.getId());
  387. detail.setDocumentName("书面反馈材料");
  388. detail.setDocumentNumber("");
  389. detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
  390. detail.setFileSource("监审单位反馈文件");
  391. detail.setPageCount(0);
  392. detail.setAttachmentUrl(opinion.getFeedbackMaterials());
  393. detail.setOrderNum(orderNum++);
  394. detail.setIsDeleted("0");
  395. costProjectTaskMaterialSummaryDetailManager.save(detail);
  396. }
  397. }
  398. }
  399. }
  400. // ==================== 类型9:成本审核初步意见表(集体审议用) ====================
  401. private void generateType9Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  402. int orderNum = 1;
  403. // 获取"成本审核初步意见表"
  404. List<CostProjectDocument> matchedDocuments = documents.stream()
  405. .filter(doc -> "成本审核初步意见表".equals(doc.getDocumentName()))
  406. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  407. .collect(Collectors.toList());
  408. for (CostProjectDocument document : matchedDocuments) {
  409. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  410. detail.setMasterId(summary.getId());
  411. detail.setTaskId(mainTask.getId());
  412. detail.setDocumentName(document.getDocumentName());
  413. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  414. detail.setAuditedUnitName("");
  415. detail.setFileSource("系统生成电子文书");
  416. detail.setPageCount(0);
  417. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  418. detail.setOrderNum(orderNum++);
  419. detail.setIsDeleted("0");
  420. costProjectTaskMaterialSummaryDetailManager.save(detail);
  421. }
  422. }
  423. // ==================== 类型10:成本监审集体审议记录 ====================
  424. private void generateType10Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectDocument> documents) {
  425. int orderNum = 1;
  426. // 获取"成本监审集体审议记录"
  427. List<CostProjectDocument> matchedDocuments = documents.stream()
  428. .filter(doc -> "成本监审集体审议记录".equals(doc.getDocumentName()))
  429. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  430. .collect(Collectors.toList());
  431. for (CostProjectDocument document : matchedDocuments) {
  432. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  433. detail.setMasterId(summary.getId());
  434. detail.setTaskId(mainTask.getId());
  435. detail.setDocumentName(document.getDocumentName());
  436. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  437. detail.setAuditedUnitName("");
  438. detail.setFileSource("系统生成电子文书");
  439. detail.setPageCount(0);
  440. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  441. detail.setOrderNum(orderNum++);
  442. detail.setIsDeleted("0");
  443. costProjectTaskMaterialSummaryDetailManager.save(detail);
  444. }
  445. // 获取集体审议记录
  446. List<CostProjectDeliberate> list = costProjectDeliberateManager.list(
  447. new LambdaQueryWrapper<CostProjectDeliberate>().eq(CostProjectDeliberate::getTaskId, mainTask.getId())
  448. );
  449. for (CostProjectDeliberate deliberate : list) {
  450. // 只处理有附件的审议记录
  451. if (StringUtil.isNotEmpty(deliberate.getAttachmentIds())) {
  452. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  453. detail.setMasterId(summary.getId());
  454. detail.setTaskId(mainTask.getId());
  455. detail.setDocumentName("成本监审集体审议记录");
  456. detail.setDocumentNumber("");
  457. detail.setAuditedUnitName("");
  458. detail.setFileSource("系统生成电子文书");
  459. detail.setPageCount(0);
  460. detail.setAttachmentUrl(deliberate.getAttachmentIds());
  461. detail.setOrderNum(orderNum++);
  462. detail.setIsDeleted("0");
  463. costProjectTaskMaterialSummaryDetailManager.save(detail);
  464. }
  465. }
  466. }
  467. // ==================== 类型11:成本监审工作底稿 ====================
  468. private void generateType11Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  469. int orderNum = 1;
  470. // 获取"成本监审工作底稿"
  471. List<CostProjectDocument> matchedDocuments = documents.stream()
  472. .filter(doc -> "成本监审工作底稿".equals(doc.getDocumentName()))
  473. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  474. .collect(Collectors.toList());
  475. for (CostProjectDocument document : matchedDocuments) {
  476. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  477. detail.setMasterId(summary.getId());
  478. detail.setTaskId(mainTask.getId());
  479. detail.setDocumentName(document.getDocumentName());
  480. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  481. detail.setAuditedUnitName("");
  482. detail.setFileSource("系统生成电子文书");
  483. detail.setPageCount(0);
  484. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  485. detail.setOrderNum(orderNum++);
  486. detail.setIsDeleted("0");
  487. costProjectTaskMaterialSummaryDetailManager.save(detail);
  488. }
  489. // 获取核增核减记录(工作底稿的一部分)
  490. for (CostProjectTask childTask : childTasks) {
  491. List<CostProjectTaskAdjustmentRecord> costProjectTaskAdjustmentRecords = adjustmentRecordManager.listByTaskId(childTask.getId());
  492. for (CostProjectTaskAdjustmentRecord record : costProjectTaskAdjustmentRecords) {
  493. // 只处理有附件的记录
  494. if (StringUtil.isNotEmpty(record.getAttachmentUrl())) {
  495. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  496. detail.setMasterId(summary.getId());
  497. detail.setTaskId(mainTask.getId());
  498. detail.setDocumentName(record.getSubject() != null ? record.getSubject() + "-工作底稿" : "成本监审工作底稿");
  499. detail.setDocumentNumber("");
  500. detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
  501. detail.setFileSource("系统生成电子文书");
  502. detail.setPageCount(0);
  503. detail.setAttachmentUrl(record.getAttachmentUrl());
  504. detail.setOrderNum(orderNum++);
  505. detail.setIsDeleted("0");
  506. costProjectTaskMaterialSummaryDetailManager.save(detail);
  507. }
  508. }
  509. }
  510. }
  511. // ==================== 类型12:成本监审提取资料登记表 ====================
  512. private void generateType12Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  513. int orderNum = 1;
  514. // 获取"成本监审提取资料登记表"
  515. List<CostProjectDocument> matchedDocuments = documents.stream()
  516. .filter(doc -> "成本监审提取资料登记表".equals(doc.getDocumentName()))
  517. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  518. .collect(Collectors.toList());
  519. for (CostProjectDocument document : matchedDocuments) {
  520. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  521. detail.setMasterId(summary.getId());
  522. detail.setTaskId(mainTask.getId());
  523. detail.setDocumentName(document.getDocumentName());
  524. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  525. detail.setAuditedUnitName("");
  526. detail.setFileSource("系统生成电子文书");
  527. detail.setPageCount(0);
  528. detail.setAttachmentUrl(document.getElectronicDocumentUrl() != null ? document.getElectronicDocumentUrl() : "");
  529. detail.setOrderNum(orderNum++);
  530. detail.setIsDeleted("0");
  531. costProjectTaskMaterialSummaryDetailManager.save(detail);
  532. }
  533. // 获取子任务的资料登记表
  534. for (CostProjectTask childTask : childTasks) {
  535. List<CostProjectTaskEvidence> list = costProjectTaskEvidenceManager.list(
  536. new LambdaQueryWrapper<CostProjectTaskEvidence>().eq(CostProjectTaskEvidence::getTaskId, childTask.getId())
  537. );
  538. for (CostProjectTaskEvidence evidence : list) {
  539. // 只处理有附件的资料登记
  540. if (StringUtil.isNotEmpty(evidence.getAttachmentUrl())) {
  541. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  542. detail.setMasterId(summary.getId());
  543. detail.setTaskId(mainTask.getId());
  544. detail.setDocumentName(evidence.getMaterialName() != null ? evidence.getMaterialName() : "提取资料登记");
  545. detail.setDocumentNumber("");
  546. detail.setAuditedUnitName(childTask.getAuditedUnitName() != null ? childTask.getAuditedUnitName() : "");
  547. detail.setFileSource("系统生成电子文书");
  548. detail.setPageCount(evidence.getPageCount() != null ? evidence.getPageCount() : 0);
  549. detail.setAttachmentUrl(evidence.getAttachmentUrl());
  550. detail.setOrderNum(orderNum++);
  551. detail.setIsDeleted("0");
  552. costProjectTaskMaterialSummaryDetailManager.save(detail);
  553. }
  554. }
  555. }
  556. }
  557. // ==================== 类型13:提取的成本资料和会计凭证等复印件 ====================
  558. private void generateType13Details(CostProjectTaskMaterialSummary summary, CostProjectTask mainTask, List<CostProjectTask> childTasks, List<CostProjectDocument> documents) {
  559. int orderNum = 1;
  560. // 获取"成本资料和会计凭证"(来源:被监审单位提交的资料)
  561. List<CostProjectDocument> matchedDocuments = documents.stream()
  562. .filter(doc -> "成本资料和会计凭证".equals(doc.getDocumentName()))
  563. .sorted(Comparator.comparing(doc -> doc.getOrderNum() != null ? doc.getOrderNum() : 0))
  564. .collect(Collectors.toList());
  565. for (CostProjectDocument document : matchedDocuments) {
  566. CostProjectTaskMaterialSummaryDetail detail = new CostProjectTaskMaterialSummaryDetail();
  567. detail.setMasterId(summary.getId());
  568. detail.setTaskId(mainTask.getId());
  569. detail.setDocumentName(document.getDocumentName());
  570. detail.setDocumentNumber(document.getDocumentNumber() != null ? document.getDocumentNumber() : "");
  571. detail.setAuditedUnitName("");
  572. detail.setFileSource("监审单位反馈文件");
  573. detail.setPageCount(0);
  574. detail.setAttachmentUrl(document.getFeedbackDocumentUrl() != null ? document.getFeedbackDocumentUrl() : "");
  575. detail.setOrderNum(orderNum++);
  576. detail.setIsDeleted("0");
  577. costProjectTaskMaterialSummaryDetailManager.save(detail);
  578. }
  579. }
  580. /**
  581. * 档案校对通过后,异步生成Word卷宗
  582. *
  583. * @param taskId 任务ID
  584. */
  585. @Async
  586. public void generateWordArchiveAsync(String taskId) {
  587. try {
  588. // 1. 查询任务的所有资料归纳主表(按序号排序)
  589. // 2. 遍历每个主表,获取其明细列表(按序号排序)
  590. // 3. 按顺序读取每个明细对应的文件
  591. // 4. 将所有文件合并为一个完整的Word文档
  592. // 5. 保存生成的Word卷宗文件
  593. System.out.println("开始生成Word卷宗,任务ID:" + taskId);
  594. // 示例代码框架(需要根据实际情况实现)
  595. List<CostProjectTaskMaterialSummary> summaryList =
  596. costProjectTaskMaterialSummaryManager.listByTaskId(taskId);
  597. // 按序号排序
  598. summaryList.sort(Comparator.comparing(CostProjectTaskMaterialSummary::getMaterialOrderNum));
  599. // 创建Word文档
  600. XWPFDocument document = new XWPFDocument();
  601. for (CostProjectTaskMaterialSummary summary : summaryList) {
  602. // 获取明细列表
  603. List<CostProjectTaskMaterialSummaryDetail> detailList = summary.getDetailList();
  604. if (detailList != null) {
  605. detailList.sort(Comparator.comparing(CostProjectTaskMaterialSummaryDetail::getOrderNum));
  606. for (CostProjectTaskMaterialSummaryDetail detail : detailList) {
  607. // 读取文件内容并添加到Word文档
  608. if (StringUtil.isNotEmpty(detail.getAttachmentUrl())) {
  609. try {
  610. // 读取Word文件
  611. java.io.FileInputStream fis = new java.io.FileInputStream(detail.getAttachmentUrl());
  612. XWPFDocument sourceDoc = new XWPFDocument(fis);
  613. // 合并段落
  614. for (XWPFParagraph srcPara : sourceDoc.getParagraphs()) {
  615. XWPFParagraph destPara = document.createParagraph();
  616. // 复制段落样式
  617. destPara.setAlignment(srcPara.getAlignment());
  618. destPara.setIndentationLeft(srcPara.getIndentationLeft());
  619. destPara.setIndentationRight(srcPara.getIndentationRight());
  620. destPara.setSpacingBefore(srcPara.getSpacingBefore());
  621. destPara.setSpacingAfter(srcPara.getSpacingAfter());
  622. for (XWPFRun srcRun : srcPara.getRuns()) {
  623. XWPFRun destRun = destPara.createRun();
  624. destRun.setText(srcRun.getText(0));
  625. destRun.setBold(srcRun.isBold());
  626. destRun.setItalic(srcRun.isItalic());
  627. destRun.setUnderline(srcRun.getUnderline());
  628. destRun.setStrikeThrough(srcRun.isStrikeThrough());
  629. destRun.setFontSize(srcRun.getFontSize());
  630. if (srcRun.getFontFamily() != null) {
  631. destRun.setFontFamily(srcRun.getFontFamily());
  632. }
  633. if (srcRun.getColor() != null) {
  634. destRun.setColor(srcRun.getColor());
  635. }
  636. }
  637. }
  638. // 添加分页符(每个文档之间分页)
  639. XWPFParagraph pageBreakPara = document.createParagraph();
  640. XWPFRun pageBreakRun = pageBreakPara.createRun();
  641. pageBreakRun.addBreak(org.apache.poi.xwpf.usermodel.BreakType.PAGE);
  642. sourceDoc.close();
  643. fis.close();
  644. } catch (Exception e) {
  645. System.err.println("合并文件失败:" + detail.getDocumentName() + ",错误:" + e.getMessage());
  646. e.printStackTrace();
  647. }
  648. }
  649. }
  650. }
  651. }
  652. //保存Word文档
  653. String outputPath = "卷宗_" + taskId + ".docx";
  654. FileOutputStream out = new FileOutputStream(outputPath);
  655. document.write(out);
  656. out.close();
  657. document.close();
  658. System.out.println("Word卷宗生成完成,任务ID:" + taskId);
  659. // 更新任务的归档状态
  660. CostProjectTask task = costProjectTaskManager.getById(taskId);
  661. if (task != null) {
  662. task.setIsGd("1");
  663. costProjectTaskManager.updateById(task);
  664. System.out.println("任务归档状态已更新,任务ID:" + taskId);
  665. }
  666. } catch (Exception e) {
  667. e.printStackTrace();
  668. System.err.println("生成Word卷宗失败,任务ID:" + taskId + ",错误:" + e.getMessage());
  669. }
  670. }
  671. /**
  672. * 更新单个资料归纳主表的总页数
  673. *
  674. * @param masterId 主表ID
  675. */
  676. public void updateMasterTotalPageCount(String masterId) {
  677. try {
  678. CostProjectTaskMaterialSummary summary = costProjectTaskMaterialSummaryManager.getById(masterId);
  679. if (summary == null) {
  680. System.err.println("资料归纳主表不存在,ID:" + masterId);
  681. return;
  682. }
  683. int totalPageCount = 0;
  684. // 查询该主表的所有明细
  685. List<CostProjectTaskMaterialSummaryDetail> detailList = costProjectTaskMaterialSummaryDetailManager.list(
  686. new LambdaQueryWrapper<CostProjectTaskMaterialSummaryDetail>()
  687. .eq(CostProjectTaskMaterialSummaryDetail::getMasterId, masterId)
  688. .eq(CostProjectTaskMaterialSummaryDetail::getIsDeleted, "0")
  689. );
  690. // 累加所有明细的页数
  691. for (CostProjectTaskMaterialSummaryDetail detail : detailList) {
  692. if (detail.getPageCount() != null) {
  693. totalPageCount += detail.getPageCount();
  694. }
  695. }
  696. // 更新主表的总页数
  697. summary.setTotalPageCount(String.valueOf(totalPageCount));
  698. costProjectTaskMaterialSummaryManager.updateById(summary);
  699. System.out.println("资料归纳【" + summary.getMaterialName() + "】总页数已更新:" + totalPageCount);
  700. } catch (Exception e) {
  701. e.printStackTrace();
  702. System.err.println("更新主表总页数失败,主表ID:" + masterId + ",错误:" + e.getMessage());
  703. }
  704. }
  705. /**
  706. * 异步统计每个资料归纳主表的总页数(所有明细的页数之和)
  707. *
  708. * @param taskId 任务ID
  709. */
  710. public void calculatePageCountAsync(String taskId) {
  711. try {
  712. System.out.println("开始异步统计页数,任务ID:" + taskId);
  713. // 查询任务的所有资料归纳主表
  714. List<CostProjectTaskMaterialSummary> summaryList = costProjectTaskMaterialSummaryManager.listByTaskId(taskId);
  715. for (CostProjectTaskMaterialSummary summary : summaryList) {
  716. int totalPageCount = 0;
  717. // 获取该主表的所有明细
  718. if (summary.getDetailList() != null && !summary.getDetailList().isEmpty()) {
  719. for (CostProjectTaskMaterialSummaryDetail detail : summary.getDetailList()) {
  720. if (StringUtil.isNotEmpty(detail.getAttachmentUrl())) {
  721. // 统计该明细的页数
  722. int pageCount = calculateFilePageCount(detail.getAttachmentUrl());
  723. detail.setPageCount(pageCount);
  724. costProjectTaskMaterialSummaryDetailManager.updateById(detail);
  725. // 累加到总页数
  726. totalPageCount += pageCount;
  727. }
  728. }
  729. }
  730. // 更新主表的总页数
  731. summary.setTotalPageCount(String.valueOf(totalPageCount));
  732. costProjectTaskMaterialSummaryManager.updateById(summary);
  733. System.out.println("资料归纳【" + summary.getMaterialName() + "】统计完成,总页数:" + totalPageCount);
  734. }
  735. System.out.println("页数统计完成,任务ID:" + taskId);
  736. } catch (Exception e) {
  737. e.printStackTrace();
  738. System.err.println("统计页数失败,任务ID:" + taskId + ",错误:" + e.getMessage());
  739. }
  740. }
  741. /**
  742. * 计算文件页数(公共方法,可被外部调用)
  743. *
  744. * @param fileUrl 文件URL或路径
  745. * @return 页数
  746. */
  747. public int calculateFilePageCount(String fileUrl) {
  748. try {
  749. if (StringUtil.isEmpty(fileUrl)) {
  750. return 0;
  751. }
  752. // 判断文件类型
  753. String lowerCaseUrl = fileUrl.toLowerCase();
  754. if (lowerCaseUrl.endsWith(".xls") || lowerCaseUrl.endsWith(".xlsx")) {
  755. // Excel文件算1页
  756. return 1;
  757. } else if (lowerCaseUrl.endsWith(".doc") || lowerCaseUrl.endsWith(".docx")) {
  758. // Word文件需要读取实际页数
  759. return getWordPageCount(fileUrl);
  760. } else {
  761. // 其他格式默认1页
  762. return 1;
  763. }
  764. } catch (Exception e) {
  765. System.err.println("计算文件页数失败,文件:" + fileUrl + ",错误:" + e.getMessage());
  766. return 0;
  767. }
  768. }
  769. /**
  770. * 获取Word文档的页数
  771. *
  772. * @param fileUrl 文件URL或路径(如:/profile/upload/20251116/xxx.docx)
  773. * @return 页数
  774. */
  775. private int getWordPageCount(String fileUrl) {
  776. java.io.FileInputStream fis = null;
  777. XWPFDocument document = null;
  778. try {
  779. String filePath = fileUrl;
  780. if (filePath.startsWith("/profile")) {
  781. filePath = com.hotent.config.EipConfig.getProfile() + filePath.substring(8);
  782. }
  783. fis = new java.io.FileInputStream(filePath);
  784. document = new XWPFDocument(fis);
  785. // 获取页数
  786. int pageCount = document.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
  787. return pageCount > 0 ? pageCount : 1;
  788. } catch (Exception e) {
  789. System.err.println("读取Word页数失败,文件:" + fileUrl + ",错误:" + e.getMessage());
  790. // 读取失败默认返回1页
  791. return 1;
  792. } finally {
  793. // 关闭资源
  794. try {
  795. if (document != null) {
  796. document.close();
  797. }
  798. if (fis != null) {
  799. fis.close();
  800. }
  801. } catch (Exception e) {
  802. System.err.println("关闭文件流失败:" + e.getMessage());
  803. }
  804. }
  805. }
  806. }