From 397ef7f5303ddc12e79ca39f4267f4e7e8108bd3 Mon Sep 17 00:00:00 2001 From: yuance <182865460@qq.com> Date: Fri, 5 Dec 2025 10:33:38 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=8E=A5=E5=8F=A3=E5=AE=A1?= =?UTF-8?q?=E8=AE=A1=E5=86=85=E5=AE=B96-=E5=9B=BD=E8=B5=84=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AuditContent6StateAssetsConstants.java | 154 ++++++++ .../controller/AuditContent6Controller.java | 304 ++++++++++++++++ .../export/StateAssetsAuditExportEntity.java | 58 +++ .../AuditContent6StateAssetsService.java | 15 + .../AuditContent6StateAssetsServiceImpl.java | 336 ++++++++++++++++++ 5 files changed, 867 insertions(+) create mode 100644 src/main/java/com/gxwebsoft/ai/constants/AuditContent6StateAssetsConstants.java create mode 100644 src/main/java/com/gxwebsoft/ai/controller/AuditContent6Controller.java create mode 100644 src/main/java/com/gxwebsoft/ai/dto/export/StateAssetsAuditExportEntity.java create mode 100644 src/main/java/com/gxwebsoft/ai/service/AuditContent6StateAssetsService.java create mode 100644 src/main/java/com/gxwebsoft/ai/service/impl/AuditContent6StateAssetsServiceImpl.java diff --git a/src/main/java/com/gxwebsoft/ai/constants/AuditContent6StateAssetsConstants.java b/src/main/java/com/gxwebsoft/ai/constants/AuditContent6StateAssetsConstants.java new file mode 100644 index 0000000..5c87712 --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/constants/AuditContent6StateAssetsConstants.java @@ -0,0 +1,154 @@ +package com.gxwebsoft.ai.constants; + +import java.util.*; + +/** + * 审计内容6-国资管理情况常量类 + * 审计目标:检查国有资产管理情况和政府采购执行情况 + */ +public class AuditContent6StateAssetsConstants { + + // 分类定义 + public static final String CATEGORY_STATE_ASSETS_MANAGEMENT = "国资管理情况"; + + // 审计框架核心(基于Excel内容) + public static final String AUDIT_FRAMEWORK = + "审计核心:检查国有资产管理情况和政府采购执行情况\n\n" + + "重点关注:\n" + + "(1)资产配置是否按规定报上级主管部门采取政府采购方式。资产登记不及时、不完整,资产台账和会计明细账不符,应报废、核销的资产长期挂账。未经批准出租、出借资产,报废、核销资产未履行审批手续。资产处置收益未纳入\"收支两条线\"管理。被审计单位有房屋出租,制定资产出租必须进入交易平台的制度后,是否还有私自出租、不进入平台交易的现象。前期出租出去的房屋,未经过平台的,审计其租金水平是否合理。\n" + + "(2)国有资产对外投资和收益以及国有资产保值增值的情况。主要关注:是否违规利用国有资产对外投资;是否违规利用国有资产对外提供抵押、担保;国有资产投资收益持续亏损的原因;是否实现国有资产保值增值。\n\n" + + "审计方法及步骤:\n" + + "(1)审阅国有资产采购合同及招投标文件等资料,检查国有资产购置是否按规定实行政府采购。审阅固定资产登记台账与会计明细账,审查账账是否相符。根据固定资产类别或领用单位等进行抽查盘点,审查账实是否相符,已报废固定资产是否及时予以报废、核销。审阅国有资产出租、出借、报废核销的上级主管部门和财政部门的批准文件,检查手续是否完整。审阅国有资产处置收入的评估文件、上级主管部门和财政部门的核准文件,对比市场价格,检查处置收入是否合理,是否具备完整的处置手续。审阅国有资产处置收入的会计处理凭证及上缴财政国库的会计处理凭证,检查处置收益是否已纳入\"收支两条线\"管理。审计房屋出租是否按照规定上平台招租,可调查周边租金水平,来进行对比。\n" + + "(2)审阅国有资产对外投资,提供抵押、担保的上级主管部门和财政部门的审计文件,以及提供抵押、担保的合同,检查审批手续是否齐全,是否真实、合法;计算本单位国有资产保值增值率,检查本单位国有资产保值增值的情况;审计被审计单位划拨、借用给设立企业的资产来源是否清晰。\n\n" + + "政府采购执行情况\n\n" + + "重点关注:\n" + + "是否存在应当报政府采购计划的,未报政府采购计划的情况。包括拆解规避政府采购的情况;是否存在已报政府采购计划,但实际未实施政府采购,而是自行采购的情况,且采购的品类、型号是政府采购目录中具备的,达不到自行采购的条件;是否存在不按政府采购预算的品目,而通过政府采购实施其他品目采购的情况。\n\n" + + "审计方法及步骤:\n" + + "①审查财务支出凭据,和\"固定资产\"科目,检查是否全部固定资产的采购都是通过具备政府采购手续的。②对照政府采购文件和目录,查阅财务支出,审计是否存在应报政府采购而未报的情况,特别注意成批的易耗品、一般资产也要执行政府采购。审计时,必须将有可能是批量采购而拆解采购的线索联系起来,看采购的时间、品目,是否应当同时购置的,采取分散购置,规避政府采购,发现此类情况的,除追究违反政府采购法的责任外,还要追踪至货物、服务的提供方,检查是否存在关联交易,交易价格是否合理,是否存在利益输送。③将年度内所有已执行政府采购的名单列出,与政府采购预算报表核对,审计是否按照预算采购,有无乱采购、无预算采购。凡是发现无预算采购的,都要关注采购价格和关联方交易、利益输送。④对实施单一采购的,核对政府采购目录,检查是否属于单一采购来源的要求。如果不属于单一采购来源的,也要关注采购价格和关联方交易、利益输送。"; + + // 审计目标 + public static final String AUDIT_OBJECTIVE = + "检查国有资产管理情况和政府采购执行情况,确保国有资产安全完整、保值增值,规范政府采购行为。"; + + // 审计工作原则 + public static final String AUDIT_PRINCIPLES = + "审计工作原则:\n" + + "1. 以国有资产管理制度和政府采购法规为依据\n" + + "2. 重点检查资产配置、使用、处置全流程的合规性\n" + + "3. 关注资产出租、投资、担保等高风险环节\n" + + "4. 核实资产账实相符、账账相符情况\n" + + "5. 检查政府采购计划执行的真实性和合规性\n" + + "6. 注重发现规避监管、利益输送等违规行为"; + + // 关键词权重 + public static final Map KEYWORD_WEIGHTS = new HashMap<>(); + static { + // 核心概念 + KEYWORD_WEIGHTS.put("国有资产", 10); + KEYWORD_WEIGHTS.put("政府采购", 10); + KEYWORD_WEIGHTS.put("资产配置", 9); + KEYWORD_WEIGHTS.put("资产出租", 9); + + // 管理流程 + KEYWORD_WEIGHTS.put("台账", 8); + KEYWORD_WEIGHTS.put("会计明细账", 8); + KEYWORD_WEIGHTS.put("报废核销", 8); + KEYWORD_WEIGHTS.put("处置收益", 7); + KEYWORD_WEIGHTS.put("收支两条线", 7); + + // 采购相关 + KEYWORD_WEIGHTS.put("政府采购计划", 9); + KEYWORD_WEIGHTS.put("政府采购目录", 8); + KEYWORD_WEIGHTS.put("单一采购", 7); + KEYWORD_WEIGHTS.put("规避采购", 8); + + // 投资担保 + KEYWORD_WEIGHTS.put("对外投资", 9); + KEYWORD_WEIGHTS.put("抵押担保", 8); + KEYWORD_WEIGHTS.put("保值增值", 8); + + // 合同相关 + KEYWORD_WEIGHTS.put("租赁合同", 7); + KEYWORD_WEIGHTS.put("采购合同", 7); + KEYWORD_WEIGHTS.put("招投标", 7); + } + + // 审计要点提示 + public static final String AUDIT_KEY_POINTS = + "审计要点:\n" + + "1. 检查资产配置是否按规定实施政府采购\n" + + "2. 核实资产登记是否及时完整,账实是否相符\n" + + "3. 审查资产出租是否进入交易平台\n" + + "4. 检查资产处置手续是否完备,收益是否规范管理\n" + + "5. 审计对外投资、抵押担保的审批合规性\n" + + "6. 检查政府采购计划执行情况,是否存在规避行为\n" + + "7. 关注关联交易和利益输送风险"; + + // 数据格式要求 + public static final String OUTPUT_FORMAT = + "输出格式(JSON数组):\n" + + "[\n" + + " {\n" + + " \"index\": 序号,\n" + + " \"assetName\": \"国有资产名称\",\n" + + " \"acquisitionMethod\": \"国有资产取得方式(购置/划拨/接受捐赠/自建等)\",\n" + + " \"assetValue\": \"国有资产价值(原值或评估值)\",\n" + + " \"assetAddress\": \"国有资产地址\",\n" + + " \"area\": \"面积(如适用)\",\n" + + " \"tenant\": \"承租方(如未出租填'未出租')\",\n" + + " \"contractAmount\": \"合同金额(如未出租填'未出租')\",\n" + + " \"leasePeriod\": \"租赁合同起止时间(如未出租填'未出租')\",\n" + + " \"rentPaymentTime\": \"国有资产租金缴纳时间(如未出租填'未出租')\",\n" + + " \"platformLease\": \"国有资产出租是否上平台(是/否/未出租)\",\n" + + " \"approvalDoc\": \"国有资产出租的审批文件(如未出租填'未出租')\",\n" + + " \"inBudget\": \"是否纳入预算(是/否)\",\n" + + " \"remark\": \"备注(包含资产状态、使用情况、审计发现等)\",\n" + + " \"workPaperIndex\": [\"实际存在的完整文件名1\", \"实际存在的完整文件名2\", ...]\n" + + " }\n" + + "]\n\n" + + "重要说明:\n" + + "1. 每个审计记录对应一项具体的国有资产,尽可能全面识别所有资产\n" + + "2. 资产类型包括:房屋建筑物、土地、车辆、机械设备、办公设备、电子设备等\n" + + "3. 对于没有出租的资产,相关出租字段填写\"未出租\"\n" + + "4. workPaperIndex必须填写实际查阅的文件名称\n" + + "5. 备注中应详细描述资产状况、使用情况、合规性评价\n" + + "6. 尽可能多地生成审计记录,覆盖所有可能的国有资产\n" + + "7. 即使信息不完整,也要基于现有信息生成记录"; + + // 审计证据要求 + public static final String AUDIT_EVIDENCE_REQUIREMENTS = + "审计证据要求:\n" + + "1. 查阅文件:国有资产登记台账、会计明细账、采购合同、招投标文件\n" + + "2. 查阅记录:租赁合同、审批文件、处置评估报告、政府采购计划\n" + + "3. 查阅数据:资产价值评估报告、租金缴纳凭证、政府采购目录\n" + + "4. 查阅凭证:会计凭证、银行转账记录、审批手续文件\n" + + "5. 现场核实:资产实地盘点、租赁现场查看、供应商访谈"; + + // 字段映射(用于前端展示) + public static final Map FIELD_DISPLAY_NAMES = new HashMap<>(); + static { + FIELD_DISPLAY_NAMES.put("index", "序号"); + FIELD_DISPLAY_NAMES.put("assetName", "国有资产名称"); + FIELD_DISPLAY_NAMES.put("acquisitionMethod", "国有资产取得方式"); + FIELD_DISPLAY_NAMES.put("assetValue", "国有资产价值"); + FIELD_DISPLAY_NAMES.put("assetAddress", "国有资产地址"); + FIELD_DISPLAY_NAMES.put("area", "面积"); + FIELD_DISPLAY_NAMES.put("tenant", "承租方"); + FIELD_DISPLAY_NAMES.put("contractAmount", "合同金额"); + FIELD_DISPLAY_NAMES.put("leasePeriod", "租赁合同起止时间"); + FIELD_DISPLAY_NAMES.put("rentPaymentTime", "国有资产租金缴纳时间"); + FIELD_DISPLAY_NAMES.put("platformLease", "国有资产出租是否上平台"); + FIELD_DISPLAY_NAMES.put("approvalDoc", "国有资产出租的审批文件"); + FIELD_DISPLAY_NAMES.put("inBudget", "是否纳入预算"); + FIELD_DISPLAY_NAMES.put("remark", "备注"); + FIELD_DISPLAY_NAMES.put("workPaperIndex", "工作底稿索引"); + } + + // 获取分类的简要审计框架概述 + public static String getBriefAuditFrameworkForCategory(String category) { + if (CATEGORY_STATE_ASSETS_MANAGEMENT.equals(category)) { + return "审计国有资产管理和政府采购执行情况,确保资产安全完整和采购规范"; + } + return "审计国资管理情况"; + } +} \ No newline at end of file diff --git a/src/main/java/com/gxwebsoft/ai/controller/AuditContent6Controller.java b/src/main/java/com/gxwebsoft/ai/controller/AuditContent6Controller.java new file mode 100644 index 0000000..12b77b8 --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/controller/AuditContent6Controller.java @@ -0,0 +1,304 @@ +package com.gxwebsoft.ai.controller; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.gxwebsoft.ai.dto.AuditContentRequest; +import com.gxwebsoft.ai.dto.export.StateAssetsAuditExportEntity; +import com.gxwebsoft.ai.entity.AiCloudDoc; +import com.gxwebsoft.ai.entity.AiCloudFile; +import com.gxwebsoft.ai.service.AiHistoryService; +import com.gxwebsoft.ai.utils.ExcelExportTool; +import com.gxwebsoft.common.core.web.ApiResult; +import com.gxwebsoft.common.core.web.BaseController; +import com.gxwebsoft.common.system.entity.User; +import com.gxwebsoft.pwl.entity.PwlProjectLibrary; +import com.gxwebsoft.pwl.service.PwlProjectLibraryService; +import com.gxwebsoft.ai.service.AiCloudDocService; +import com.gxwebsoft.ai.service.AiCloudFileService; +import com.gxwebsoft.ai.service.AuditContent6StateAssetsService; +import com.gxwebsoft.ai.service.KnowledgeBaseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.digest.DigestUtil; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 审计内容6控制器 - 国资管理情况审计 + */ +@Slf4j +@Tag(name = "审计内容6-国资管理情况") +@RestController +@RequestMapping("/api/ai/auditContent6") +public class AuditContent6Controller extends BaseController { + + @Autowired + private AuditContent6StateAssetsService auditContent6StateAssetsService; + + @Autowired + private AiCloudDocService aiCloudDocService; + + @Autowired + private AiCloudFileService aiCloudFileService; + + @Autowired + private KnowledgeBaseService knowledgeBaseService; + + @Autowired + private PwlProjectLibraryService pwlProjectLibraryService; + + @Autowired + private AiHistoryService aiHistoryService; + + // 历史记录有效期(分钟) + private static final int HISTORY_EXPIRE_MINUTES = 10; + + /** + * 生成国有资产管理审计表数据 + */ + @Operation(summary = "生成国有资产管理审计表") + @PostMapping("/generateAssetsTable") + public ApiResult generateAssetsTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) { + return generateTableData(request, servletRequest.getRequestURI(), + (params) -> auditContent6StateAssetsService.generateStateAssetsAuditTableData( + params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary, + params.username, params.history, params.suggestion + )); + } + + /** + * 通用的表格数据生成方法 + */ + private ApiResult generateTableData(AuditContentRequest request, String interfaceName, Function generateFunction) { + final User loginUser = getLoginUser(); + String requestHistory = request.getHistory(); + request.setHistory(""); + + // 检查历史记录 + String requestHash = generateRequestHash(request, interfaceName); + var history = aiHistoryService.getValidHistory(requestHash, interfaceName, HISTORY_EXPIRE_MINUTES); + if (history != null) { + log.info("返回历史数据,请求哈希: {}", requestHash); + return success(JSONObject.parseObject(history.getResponseData())); + } + request.setHistory(requestHistory); + + String kbIdTmp = ""; + String libraryKbIds = ""; + + try { + // 创建临时知识库(如果需要) + if (hasUploadedFiles(request)) { + kbIdTmp = createTempKnowledgeBase(request); + } + + // 查询项目库信息 + libraryKbIds = getLibraryKbIds(request.getLibraryIds()); + + // 生成数据 + String knowledgeBaseId = getKnowledgeBaseId(kbIdTmp, request.getKbIds()); + GenerateParams params = new GenerateParams(knowledgeBaseId, libraryKbIds, request.getProjectLibrary(), loginUser.getUsername(), request.getHistory(), request.getSuggestion()); + + JSONObject result = generateFunction.apply(params); + + if(result.getBoolean("success")) { + // 保存到历史记录 + saveToHistory(request, interfaceName, requestHash, result, loginUser); + } + + return success(result); + } catch (Exception e) { + log.error("生成表格数据失败,接口: {}", interfaceName, e); + return fail("生成表格数据失败: " + e.getMessage()); + } finally { + cleanupTempKnowledgeBase(kbIdTmp); + } + } + + /** + * 生成请求哈希 + */ + private String generateRequestHash(AuditContentRequest request, String interfaceName) { + String requestJson = JSONObject.toJSONString(request); + return DigestUtil.md5Hex(interfaceName + ":" + requestJson); + } + + /** + * 保存到历史记录 + */ + private void saveToHistory(AuditContentRequest request, String interfaceName, String requestHash, JSONObject result, User loginUser) { + try { + aiHistoryService.saveHistory(requestHash, interfaceName, JSONObject.toJSONString(request), result.toJSONString(), loginUser.getUserId(), loginUser.getUsername(), loginUser.getTenantId()); + } catch (Exception e) { + log.warn("保存历史记录失败", e); + } + } + + /** + * 检查是否有上传的文件 + */ + private boolean hasUploadedFiles(AuditContentRequest request) { + return !request.getDocList().isEmpty() || !request.getFileList().isEmpty(); + } + + /** + * 获取知识库ID + */ + private String getKnowledgeBaseId(String tempKbId, String requestKbIds) { + return StrUtil.isNotBlank(tempKbId) ? tempKbId : requestKbIds; + } + + /** + * 获取项目库KB IDs + */ + private String getLibraryKbIds(String libraryIds) { + if (StrUtil.isBlank(libraryIds)) { + return ""; + } + List idList = StrUtil.split(libraryIds, ','); + List ret = pwlProjectLibraryService.list(new LambdaQueryWrapper().in(PwlProjectLibrary::getId, idList)); + return ret.stream().map(PwlProjectLibrary::getKbId).filter(StrUtil::isNotBlank).collect(Collectors.joining(",")); + } + + /** + * 创建临时知识库并提交文档 + */ + private String createTempKnowledgeBase(AuditContentRequest request) { + String kbIdTmp = knowledgeBaseService.createKnowledgeBaseTemp(); + // 收集文档ID + Set docIds = request.getDocList().stream().flatMap(docId -> aiCloudDocService.getSelfAndChildren(docId).stream()).map(AiCloudDoc::getId).collect(Collectors.toSet()); + // 查询相关文件 + List fileList = getRelatedFiles(docIds, request.getFileList()); + // 提取文件ID并提交到知识库 + Set kbFileIds = fileList.stream().map(AiCloudFile::getFileId).collect(Collectors.toSet()); + if (!kbFileIds.isEmpty()) { + knowledgeBaseService.submitDocuments(kbIdTmp, new ArrayList<>(kbFileIds)); + } + return kbIdTmp; + } + + /** + * 获取相关文件列表 + */ + private List getRelatedFiles(Set docIds, List fileList) { + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper() + .in(!docIds.isEmpty(), AiCloudFile::getDocId, docIds) + .or(!fileList.isEmpty()) + .in(!fileList.isEmpty(), AiCloudFile::getId, fileList); + return aiCloudFileService.list(queryWrapper); + } + + /** + * 清理临时知识库 + */ + private void cleanupTempKnowledgeBase(String kbId) { + if (StrUtil.isNotBlank(kbId)) { + try { + knowledgeBaseService.deleteIndex(kbId); + } catch (Exception e) { + log.warn("删除临时知识库失败: {}", kbId, e); + } + } + } + + /** + * 导出国有资产管理审计表到Excel + */ + @Operation(summary = "导出国有资产管理审计表到Excel") + @PostMapping("/exportAssetsTable") + public void exportAssetsTable(@RequestBody Map request, HttpServletResponse response) { + exportToExcel(request, response); + } + + /** + * Excel导出方法 + */ + private void exportToExcel(Map request, HttpServletResponse response) { + List> dataList = (List>) request.get("data"); + String companyName = (String) request.get("companyName"); + + List exportData = convertToExportEntityList(dataList); + + String fileName = "国有资产管理审计表_" + (companyName != null ? companyName : "未知公司"); + String title = companyName != null ? companyName + " - 国有资产管理审计表" : "国有资产管理审计表"; + String sheetName = "国资管理审计"; + + ExcelExportTool.exportExcel(exportData, StateAssetsAuditExportEntity.class, fileName, sheetName, title, response); + } + + /** + * 数据转换 + */ + private List convertToExportEntityList(List> originalData) { + return originalData.stream().map(this::convertToExportEntity).collect(Collectors.toList()); + } + + private StateAssetsAuditExportEntity convertToExportEntity(Map item) { + StateAssetsAuditExportEntity entity = new StateAssetsAuditExportEntity(); + entity.setIndex(getStringValue(item, "index")); + entity.setAssetName(getStringValue(item, "assetName")); + entity.setAcquisitionMethod(getStringValue(item, "acquisitionMethod")); + entity.setAssetValue(getStringValue(item, "assetValue")); + entity.setAssetAddress(getStringValue(item, "assetAddress")); + entity.setArea(getStringValue(item, "area")); + entity.setTenant(getStringValue(item, "tenant")); + entity.setContractAmount(getStringValue(item, "contractAmount")); + entity.setLeasePeriod(getStringValue(item, "leasePeriod")); + entity.setRentPaymentTime(getStringValue(item, "rentPaymentTime")); + entity.setPlatformLease(getStringValue(item, "platformLease")); + entity.setApprovalDoc(getStringValue(item, "approvalDoc")); + entity.setInBudget(getStringValue(item, "inBudget")); + entity.setRemark(getStringValue(item, "remark")); + entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex"))); + return entity; + } + + private String getStringValue(Map map, String key) { + Object value = map.get(key); + return value != null ? value.toString() : ""; + } + + private String formatWorkPaperIndex(Object workPaperIndex) { + if (workPaperIndex == null) { + return ""; + } + + if (workPaperIndex instanceof List) { + List list = (List) workPaperIndex; + return String.join(", ", list.stream() + .map(Object::toString) + .collect(Collectors.toList())); + } + + return workPaperIndex.toString(); + } + + /** + * 参数包装类 + */ + private static class GenerateParams { + final String knowledgeBaseId; + final String libraryKbIds; + final String projectLibrary; + final String username; + final String history; + final String suggestion; + + GenerateParams(String knowledgeBaseId, String libraryKbIds, String projectLibrary, String username, String history, String suggestion) { + this.knowledgeBaseId = knowledgeBaseId; + this.libraryKbIds = libraryKbIds; + this.projectLibrary = projectLibrary; + this.username = username; + this.history = history; + this.suggestion = suggestion; + } + } +} \ No newline at end of file diff --git a/src/main/java/com/gxwebsoft/ai/dto/export/StateAssetsAuditExportEntity.java b/src/main/java/com/gxwebsoft/ai/dto/export/StateAssetsAuditExportEntity.java new file mode 100644 index 0000000..5d85e51 --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/dto/export/StateAssetsAuditExportEntity.java @@ -0,0 +1,58 @@ +package com.gxwebsoft.ai.dto.export; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import cn.afterturn.easypoi.excel.annotation.ExcelTarget; +import lombok.Data; + +/** + * 国有资产管理审计导出实体 + */ +@Data +@ExcelTarget("StateAssetsAuditExportEntity") +public class StateAssetsAuditExportEntity { + + @Excel(name = "序号", orderNum = "0", width = 8) + private String index; + + @Excel(name = "国有资产名称", orderNum = "1", width = 30) + private String assetName; + + @Excel(name = "国有资产取得方式", orderNum = "2", width = 25) + private String acquisitionMethod; + + @Excel(name = "国有资产价值", orderNum = "3", width = 20) + private String assetValue; + + @Excel(name = "国有资产地址", orderNum = "4", width = 30) + private String assetAddress; + + @Excel(name = "面积", orderNum = "5", width = 15) + private String area; + + @Excel(name = "承租方", orderNum = "6", width = 25) + private String tenant; + + @Excel(name = "合同金额", orderNum = "7", width = 20) + private String contractAmount; + + @Excel(name = "租赁合同起止时间", orderNum = "8", width = 25) + private String leasePeriod; + + @Excel(name = "国有资产租金缴纳时间", orderNum = "9", width = 25) + private String rentPaymentTime; + + @Excel(name = "国有资产出租是否上平台", orderNum = "10", width = 25) + private String platformLease; + + @Excel(name = "国有资产出租的审批文件", orderNum = "11", width = 35) + private String approvalDoc; + + @Excel(name = "是否纳入预算", orderNum = "12", width = 15) + private String inBudget; + + @Excel(name = "备注", orderNum = "13", width = 30) + private String remark; + + @Excel(name = "工作底稿索引", orderNum = "14", width = 40) + private String workPaperIndex; +} \ No newline at end of file diff --git a/src/main/java/com/gxwebsoft/ai/service/AuditContent6StateAssetsService.java b/src/main/java/com/gxwebsoft/ai/service/AuditContent6StateAssetsService.java new file mode 100644 index 0000000..875036d --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/service/AuditContent6StateAssetsService.java @@ -0,0 +1,15 @@ +package com.gxwebsoft.ai.service; + +import com.alibaba.fastjson.JSONObject; + +/** + * 审计内容6-国资管理情况服务接口 + */ +public interface AuditContent6StateAssetsService { + + /** + * 生成国有资产管理审计表数据 + */ + JSONObject generateStateAssetsAuditTableData(String kbIds, String libraryKbIds, String projectLibrary, + String userName, String history, String suggestion); +} \ No newline at end of file diff --git a/src/main/java/com/gxwebsoft/ai/service/impl/AuditContent6StateAssetsServiceImpl.java b/src/main/java/com/gxwebsoft/ai/service/impl/AuditContent6StateAssetsServiceImpl.java new file mode 100644 index 0000000..907374f --- /dev/null +++ b/src/main/java/com/gxwebsoft/ai/service/impl/AuditContent6StateAssetsServiceImpl.java @@ -0,0 +1,336 @@ +package com.gxwebsoft.ai.service.impl; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.gxwebsoft.ai.constants.AuditContent6StateAssetsConstants; +import com.gxwebsoft.ai.service.AuditContent6StateAssetsService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import cn.hutool.core.util.StrUtil; + +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@Service +public class AuditContent6StateAssetsServiceImpl extends AbstractAuditContentService implements AuditContent6StateAssetsService { + + // 工作流配置 + private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-lsqVD2hTWYQpA89SDSr9s3dH"; + + @Override + public JSONObject generateStateAssetsAuditTableData(String kbIds, String libraryKbIds, String projectLibrary, + String userName, String history, String suggestion) { + log.info("开始生成国有资产管理审计表数据 - 用户: {}, kbIds: {}, libraryIds: {}, projectLibrary: {}", + userName, kbIds, libraryKbIds, projectLibrary); + + long startTime = System.currentTimeMillis(); + + try { + // 1. 检索相关知识 + Map> knowledgeSources = retrieveKnowledgeForStateAssetsManagement( + kbIds, libraryKbIds, projectLibrary + ); + + // 2. 构建完整的知识上下文 + String knowledgeContext = buildCompleteKnowledgeContext( + knowledgeSources, history, suggestion + ); + + // 3. 调用工作流生成数据 + JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName); + JSONArray auditData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "国资管理审计"); + + // 4. 后处理:确保数据格式正确 + auditData = processAuditData(auditData); + + log.info("国有资产管理审计表生成成功 - 记录数: {}, 处理时间: {}ms", + auditData.size(), (System.currentTimeMillis() - startTime)); + + return buildSuccessResponse(auditData, startTime, "state_assets_audit"); + + } catch (Exception e) { + log.error("生成国有资产管理审计表失败", e); + return buildErrorResponse("生成国有资产管理审计表失败: " + e.getMessage()); + } + } + + /** + * 检索国资管理相关知识 + */ + private Map> retrieveKnowledgeForStateAssetsManagement(String kbIds, String libraryKbIds, String projectLibrary) { + Map> knowledgeSources = new HashMap<>(); + knowledgeSources.put("enterprise", new ArrayList<>()); + knowledgeSources.put("regulation", new ArrayList<>()); + knowledgeSources.put("auditCase", new ArrayList<>()); + + // 构建查询词 - 具体化,提高识别率 + List queries = buildStateAssetsQueries(); + + // 企业单位库检索 - 增加查询深度 + if (StrUtil.isNotBlank(kbIds)) { + Arrays.stream(kbIds.split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .forEach(kbId -> knowledgeSources.get("enterprise") + .addAll(queryKnowledgeBase(kbId, queries, 100))); + } + + // 公共法律法规库检索 + if (StrUtil.isNotBlank(libraryKbIds)) { + Arrays.stream(libraryKbIds.split(",")) + .map(String::trim) + .filter(StrUtil::isNotBlank) + .forEach(libId -> knowledgeSources.get("regulation") + .addAll(queryKnowledgeBase(libId, queries, 100))); + } + + // 审计案例库检索 + if (StrUtil.isNotBlank(projectLibrary)) { + knowledgeSources.get("auditCase").addAll( + queryKnowledgeBase(projectLibrary, queries, 80)); + } + + // 智能去重和排序 + knowledgeSources.forEach((key, list) -> { + List processed = list.stream() + .map(String::trim) // 去除首尾空格 + .filter(str -> !StrUtil.isBlank(str)) // 过滤空字符串 + .distinct() + .sorted(this::stateAssetsManagementComparator) + .limit(getLimitBySourceType(key)) + .collect(Collectors.toList()); + knowledgeSources.put(key, processed); + }); + + log.debug("国资管理知识检索完成 - 企业: {}条, 法规: {}条, 案例: {}条", + knowledgeSources.get("enterprise").size(), + knowledgeSources.get("regulation").size(), + knowledgeSources.get("auditCase").size()); + + return knowledgeSources; + } + + /** + * 构建国资管理查询词 - 具体化 + */ + private List buildStateAssetsQueries() { + return Arrays.asList( + "固定资产 资产台账 资产登记", + "房屋 土地 土地使用权", + "车辆 汽车 运输工具", + "机械设备 生产设备 仪器设备", + "办公设备 电脑 打印机 空调", + "仓库 厂房 办公楼 宿舍楼", + "家具 电器 电子设备", + "无形资产 软件 专利权", + "在建工程 工程项目", + "土地证 房产证 不动产权证", + "资产评估 资产价值 原值 净值", + "资产折旧 累计折旧", + "资产盘点 盘点表 盘点记录", + "资产报废 资产处置", + "资产出租 租赁合同 租金", + "资产转让 资产出售", + "政府采购 采购合同", + "招投标 投标文件", + "资产配置 资产采购", + "资产使用 资产保管" + ); + } + + /** + * 构建完整的知识上下文 + */ + private String buildCompleteKnowledgeContext(Map> knowledgeSources, + String history, String suggestion) { + StringBuilder context = new StringBuilder(); + + // 1. 核心审计任务 + context.append("## 核心审计任务\n"); + context.append("审计分类:").append(AuditContent6StateAssetsConstants.CATEGORY_STATE_ASSETS_MANAGEMENT).append("\n"); + context.append("审计描述:检查国有资产管理情况和政府采购执行情况,确保资产安全完整和采购规范\n\n"); + + // 2. 审计框架(审计规则) + context.append("## 审计框架(审计规则)\n"); + context.append("以下审计框架定义了审计范围和要点,请基于此框架开展工作:\n"); + context.append(AuditContent6StateAssetsConstants.AUDIT_FRAMEWORK).append("\n\n"); + + // 3. 审计目标 + context.append("## 审计目标\n"); + context.append(AuditContent6StateAssetsConstants.AUDIT_OBJECTIVE).append("\n\n"); + + // 4. 审计工作原则 + context.append("## 审计工作原则\n"); + context.append(AuditContent6StateAssetsConstants.AUDIT_PRINCIPLES).append("\n\n"); + + // 5. 企业单位知识(主要考察内容) + if (!knowledgeSources.get("enterprise").isEmpty()) { + context.append("## 企业单位知识(具体考察内容)\n"); + context.append("以下是企业单位的实际资料,请基于审计框架,结合这些具体内容生成审计记录:\n\n"); + knowledgeSources.get("enterprise").forEach(knowledge -> + context.append("• ").append(knowledge).append("\n")); + context.append("\n"); + } + + // 6. 审计要点提示 + context.append("## 审计要点提示\n"); + context.append(AuditContent6StateAssetsConstants.AUDIT_KEY_POINTS).append("\n\n"); + + // 7. 数据格式要求 + context.append("## 数据格式要求\n"); + context.append("请生成JSON数组格式的审计表数据,每个审计条目包含以下字段:\n"); + context.append(AuditContent6StateAssetsConstants.OUTPUT_FORMAT).append("\n\n"); + + // 8. 审计证据要求 + context.append("## 审计证据要求\n"); + context.append(AuditContent6StateAssetsConstants.AUDIT_EVIDENCE_REQUIREMENTS).append("\n\n"); + + // 9. 特别提醒 - 强调全面识别 + context.append("## 特别提醒\n"); + context.append("1. 必须全面识别知识库中所有国有资产,包括:房屋、土地、车辆、机械设备、办公设备、电子设备、家具、无形资产等\n"); + context.append("2. 每个独立的资产都要生成独立的审计记录,不限制数量,尽可能多地生成\n"); + context.append("3. 即使资产信息不完整,也要基于现有信息生成审计记录\n"); + context.append("4. workPaperIndex必须填写实际存在的完整文件名\n"); + context.append("5. 对于未出租资产,承租方、合同金额等字段填写\"未出租\"\n"); + context.append("6. 备注中应详细说明资产状况、使用情况、合规性评价\n"); + context.append("7. 不能填写简单的\"无\",要提供有意义的描述\n\n"); + + // 10. 法规和案例参考 + if (!knowledgeSources.get("regulation").isEmpty()) { + context.append("## 法律法规参考\n"); + knowledgeSources.get("regulation").forEach(knowledge -> + context.append("• ").append(knowledge).append("\n")); + context.append("\n"); + } + + if (!knowledgeSources.get("auditCase").isEmpty()) { + context.append("## 审计案例参考\n"); + knowledgeSources.get("auditCase").forEach(knowledge -> + context.append("• ").append(knowledge).append("\n")); + context.append("\n"); + } + + // 11. 历史内容(如果有) + if (StrUtil.isNotBlank(history)) { + context.append("## 历史生成内容\n"); + context.append(history).append("\n\n"); + } + + // 12. 用户建议(如果有) + if (StrUtil.isNotBlank(suggestion)) { + context.append("## 用户建议\n"); + context.append(suggestion).append("\n\n"); + } + + log.debug("国资管理审计知识上下文长度: {} 字符", context.length()); + + return context.toString(); + } + + /** + * 国资管理审计相关性比较器 + */ + private int stateAssetsManagementComparator(String reg1, String reg2) { + int score1 = calculateStateAssetsRelevanceScore(reg1); + int score2 = calculateStateAssetsRelevanceScore(reg2); + return Integer.compare(score2, score1); // 降序排序 + } + + /** + * 计算国资管理审计相关性分数 + */ + private int calculateStateAssetsRelevanceScore(String content) { + return AuditContent6StateAssetsConstants.KEYWORD_WEIGHTS.entrySet().stream() + .filter(entry -> content.contains(entry.getKey())) + .mapToInt(Map.Entry::getValue) + .sum(); + } + + private int getLimitBySourceType(String sourceType) { + switch (sourceType) { + case "enterprise": return 300; // 增加企业知识数量 + case "regulation": return 60; + case "auditCase": return 40; + default: return 50; + } + } + + /** + * 后处理审计数据 + */ + private JSONArray processAuditData(JSONArray auditData) { + if (auditData == null || auditData.isEmpty()) { + return auditData; + } + + JSONArray processedData = new JSONArray(); + + for (int i = 0; i < auditData.size(); i++) { + JSONObject item = auditData.getJSONObject(i); + + // 确保序号存在 + if (!item.containsKey("index") || item.getInteger("index") == null) { + item.put("index", i + 1); + } + + // 确保国有资产名称存在 + if (!item.containsKey("assetName") || StrUtil.isBlank(item.getString("assetName"))) { + item.put("assetName", "国有资产" + (i + 1)); + } + + // 优化取得方式 + String acquisitionMethod = item.getString("acquisitionMethod"); + if (StrUtil.isBlank(acquisitionMethod) || "无".equals(acquisitionMethod)) { + item.put("acquisitionMethod", "购置"); + } + + // 优化资产价值 + String assetValue = item.getString("assetValue"); + if (StrUtil.isBlank(assetValue) || "无".equals(assetValue)) { + item.put("assetValue", "待评估"); + } + + // 优化面积 + String area = item.getString("area"); + if (StrUtil.isBlank(area) || "无".equals(area)) { + item.put("area", "未提供"); + } + + // 优化出租相关字段 + String platformLease = item.getString("platformLease"); + if (StrUtil.isBlank(platformLease) || "无".equals(platformLease)) { + item.put("platformLease", "否"); + } + + String tenant = item.getString("tenant"); + if (StrUtil.isBlank(tenant) || "无".equals(tenant) || tenant.contains("无")) { + item.put("tenant", "未出租"); + item.put("contractAmount", "未出租"); + item.put("leasePeriod", "未出租"); + item.put("rentPaymentTime", "未出租"); + item.put("approvalDoc", "未出租"); + } + + // 优化是否纳入预算 + String inBudget = item.getString("inBudget"); + if (StrUtil.isBlank(inBudget) || "无".equals(inBudget)) { + item.put("inBudget", "是"); + } + + // 确保工作底稿索引是数组格式 + if (!item.containsKey("workPaperIndex") || !(item.get("workPaperIndex") instanceof JSONArray)) { + JSONArray workPaperIndex = new JSONArray(); + String assetName = item.getString("assetName"); + workPaperIndex.add(assetName + "资产登记台账"); + item.put("workPaperIndex", workPaperIndex); + } + + processedData.add(item); + } + + return processedData; + } + +} \ No newline at end of file