添加审计内容9-福利费超范围支出明细清单

This commit is contained in:
2026-01-14 18:27:16 +08:00
parent 9629c7234d
commit 378d37f590

View File

@@ -19,6 +19,9 @@ public class AuditContent9PersonnelServiceImpl extends AbstractAuditContentServi
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-fmGhYITVQVAHaY3GJYonIGPA";
private static final String DIFY_WORKFLOW_TOKEN_EXT = "Bearer app-olBqOrzi1IQCWyDqthME6SYG";
@Override
public JSONObject generatePersonnelTableData(String kbIds, String libraryKbIds, String projectLibrary,
String userName, String history, String suggestion) {
@@ -179,6 +182,14 @@ public class AuditContent9PersonnelServiceImpl extends AbstractAuditContentServi
keywords.addAll(Arrays.asList("劳务外包", "外包合同", "假外包真派遣"));
} else if (auditContent.contains("人员经费")) {
keywords.addAll(Arrays.asList("工资总额", "福利费", "劳务费"));
keywords.addAll(Arrays.asList(
"工资总额", "福利费", "劳务费",
"补贴", "慰问", "福利",
"节日", "生日", "体检",
"食堂", "交通补贴", "通讯补贴",
"误餐补贴", "职工福利", "员工福利",
"防暑降温", "取暖费", "劳保用品"
));
} else if (auditContent.contains("借用人员")) {
keywords.addAll(Arrays.asList("借调", "借用人员", "借调程序"));
} else if (auditContent.contains("绩效管理")) {
@@ -206,19 +217,29 @@ public class AuditContent9PersonnelServiceImpl extends AbstractAuditContentServi
String userName, String history, String suggestion) {
try {
// 构建上下文
String context = buildSubItemContext(auditContent, subContent, knowledgeSources,
history, suggestion);
JSONArray ext = new JSONArray();
String updatedHistory = history; // 使用新变量避免修改入参
// 检查是否是福利费列支范围检查子项
String extSubContent = AuditContent9PersonnelConstants.AUDIT_SUB_CONTENTS.get(AuditContent9PersonnelConstants.AUDIT_CONTENTS[2]).get(1).getAuditTarget();
if (subContent.getAuditTarget().equals(extSubContent)) {
// 生成扩展数据(福利费明细清单)
String contextExt = buildSubItemContextExt(auditContent, subContent, knowledgeSources, history, suggestion);
JSONObject requestBodyExt = buildWorkflowRequest(contextExt, userName);
ext = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN_EXT, requestBodyExt, auditContent + "-" + subContent.getAuditTarget());
// 更新历史内容(不影响原始入参)
if (StrUtil.isNotBlank(history)) {
updatedHistory = history + "\n《福利费超范围支出明细清单》" + ext.toJSONString();
}
}
// 调用Dify工作流 - 使用正确的请求体格式
// 构建主上下文
String context = buildSubItemContext(auditContent, subContent, knowledgeSources, updatedHistory, suggestion);
// 调用Dify工作流
JSONObject requestBody = buildWorkflowRequest(context, userName);
JSONArray result = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN,
requestBody, auditContent + "-" + subContent.getAuditTarget());
JSONArray result = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, auditContent + "-" + subContent.getAuditTarget());
// 处理返回结果
return processSubItemResult(result, auditContent, subContent);
return processSubItemResult(result, auditContent, subContent, ext);
} catch (Exception e) {
log.error("生成子项数据失败: {} - {}", auditContent, subContent.getAuditTarget(), e);
return new JSONArray();
@@ -329,11 +350,160 @@ public class AuditContent9PersonnelServiceImpl extends AbstractAuditContentServi
return context.toString();
}
/**
* 构建福利费超范围支出明细清单的上下文
*/
private String buildSubItemContextExt(String auditContent,
AuditContent9PersonnelConstants.AuditSubContent subContent,
Map<String, List<String>> knowledgeSources,
String history, String suggestion) {
StringBuilder context = new StringBuilder();
context.append("## 审计任务\n");
context.append("生成福利费支出明细清单数据\n\n");
context.append("## 审计要求\n");
context.append("1. 审计内容:").append(auditContent).append("\n");
context.append("2. 审计目标:").append(subContent.getAuditTarget()).append("\n");
context.append("3. 审计证据:").append(subContent.getAuditEvidence()).append("\n");
context.append("4. 审计方法:").append(subContent.getAiTestContent()).append("\n");
context.append("5. 制度依据:").append(subContent.getRegulationBasis()).append("\n\n");
context.append("## 生成结果要求\n");
context.append("生成福利费支出明细清单,包括所有福利费支出的详细记录\n\n");
context.append("## 重要要求\n");
context.append("1. **积极查找知识库中所有福利费相关支出记录**,包括但不限于:\n");
context.append(" - 福利费支出凭证、报销单\n");
context.append(" - 工资表中的福利费项目\n");
context.append(" - 补贴发放记录、福利发放记录\n");
context.append(" - 节日慰问、职工福利相关支出\n");
context.append(" - 职工食堂、交通补贴、通讯补贴等\n");
context.append("2. **即使信息不完整也要尽可能记录**\n");
context.append(" - 如果凭证号不明确,可以使用'未知'或根据内容推断\n");
context.append(" - 如果日期不明确,可以合理推断或使用'审计期间'\n");
context.append(" - 如果金额不明确,可以根据上下文合理估计\n");
context.append("3. **允许合理推断**\n");
context.append(" - 根据支出用途推断款项性质\n");
context.append(" - 根据文件内容推断归属部门/人员\n");
context.append(" - 根据上下文补充缺失信息\n");
context.append("4. **优先使用实际信息**,只有在确实无法获取时才允许推断\n\n");
context.append("## 审计判断原则\n");
context.append("1. **积极查找原则**:尽可能查找所有可能的福利费相关支出\n");
context.append("2. **信息补充原则**:对不完整信息进行合理补充\n");
context.append("3. **分类识别原则**:识别以下类型的福利费支出:\n");
context.append(" - 职工福利发放(节日福利、生日福利等)\n");
context.append(" - 职工补贴(交通、通讯、餐饮补贴等)\n");
context.append(" - 职工活动支出(文体活动、旅游活动等)\n");
context.append(" - 职工慰问支出(生病慰问、困难补助等)\n");
context.append(" - 其他福利性支出\n");
context.append("4. **合规性初步判断**\n");
context.append(" - 对于明显超出常规福利费范围的项目进行标注\n");
context.append(" - 对于可能违规的支出进行初步分析\n\n");
context.append("## 审计步骤\n");
context.append("1. 第一步:全面搜索知识库中所有福利费相关支出\n");
context.append("2. 第二步:尽可能多地提取福利费支出记录\n");
context.append("3. 第三步:对每条记录进行信息补充和整理\n");
context.append("4. 第四步:初步分析支出合规性\n");
context.append("5. 第五步:生成完整的福利费支出明细清单\n\n");
context.append("## 返回格式\n");
context.append("返回JSON数组每条记录必须包含以下字段严格按照字段名和格式\n");
context.append("- **index**序号数字从1开始自动递增\n");
context.append("- **voucher**:凭证号(字符串,优先使用实际凭证号,如无法获取可用'未知'或合理推断)\n");
context.append("- **expenditureDate**支出日期字符串格式YYYY-MM-DD如无法获取可用'审计期间'\n");
context.append("- **usage**:用途(字符串,详细说明支出用途)\n");
context.append("- **payee**:收款方(字符串,完整收款方名称,如无法获取可用'相关单位/个人'\n");
context.append("- **amount**金额数字单位保留两位小数如无法获取可用0.00\n");
context.append("- **belongTo**:归属部门/人员(字符串,明确责任主体,如无法获取可用'相关部门'\n");
context.append("- **natureDesc**:款项性质说明(字符串,详细说明款项性质和目的)\n");
context.append("- **violationDesc**:违规说明(字符串,如果不明确是否违规,可留空或写'待进一步核实'\n\n");
context.append("## 重点关注福利费支出类型\n");
context.append("1. **常规福利费**:节日慰问品、职工生日福利、职工体检等\n");
context.append("2. **职工补贴**:交通补贴、通讯补贴、误餐补贴、住房补贴等\n");
context.append("3. **职工活动**:文体活动、旅游活动、团建活动等\n");
context.append("4. **职工慰问**:生病慰问、困难补助、婚丧嫁娶慰问等\n");
context.append("5. **职工福利设施**:职工食堂、活动室、休息室等支出\n");
context.append("6. **其他福利**:防暑降温费、取暖费、劳保用品等\n\n");
context.append("## 如何从知识库中提取信息\n");
context.append("1. **搜索关键词**:福利费、补贴、慰问、福利、节日、生日、体检、活动、食堂、交通、通讯、餐饮\n");
context.append("2. **文件类型**:财务凭证、报销单、工资表、发放记录、会议纪要、审批单\n");
context.append("3. **提取策略**\n");
context.append(" - 从财务凭证中提取凭证号、金额、日期\n");
context.append(" - 从报销单中提取用途、收款方\n");
context.append(" - 从审批记录中提取归属部门\n");
context.append(" - 综合分析文件内容推断款项性质\n\n");
context.append("## 特殊处理说明\n");
context.append("1. **如果知识库中没有直接福利费凭证**\n");
context.append(" - 可以查找相关会议纪要中提到的福利费支出\n");
context.append(" - 可以查找工资表中的福利费项目\n");
context.append(" - 可以查找报销单中的福利相关支出\n");
context.append("2. **信息补充方法**\n");
context.append(" - 通过文件名推断凭证号\n");
context.append(" - 通过文件创建日期推断支出日期\n");
context.append(" - 通过上下文推断款项用途\n");
context.append("3. **生成多条记录**\n");
context.append(" - 一条福利费支出凭证可以生成一条记录\n");
context.append(" - 一份工资表中的福利费项目可以生成多条记录\n");
context.append(" - 一份会议纪要中的多项福利费决定可以生成多条记录\n\n");
// 添加历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史内容\n");
context.append(history).append("\n\n");
}
// 添加用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户建议\n");
context.append(suggestion).append("\n\n");
}
// 添加相关知识
if (!knowledgeSources.get("enterprise").isEmpty()) {
context.append("## 企业财务信息\n");
context.append("请仔细查找以下内容中的福利费相关信息:\n");
knowledgeSources.get("enterprise").forEach(info -> {
context.append(info).append("\n");
});
}
// if (!knowledgeSources.get("regulation").isEmpty()) {
// context.append("## 法规信息\n");
// context.append("参考以下福利费管理规定:\n");
// knowledgeSources.get("regulation").forEach(info -> {
// context.append(info).append("\n");
// });
// }
// if (!knowledgeSources.get("auditCase").isEmpty()) {
// context.append("## 审计案例信息\n");
// context.append("参考以下福利费审计案例:\n");
// knowledgeSources.get("auditCase").forEach(info -> {
// context.append(info).append("\n");
// });
// }
context.append("\n## 最终要求\n");
context.append("请基于以上信息和知识库内容,尽可能多地生成福利费支出明细清单数据。\n");
context.append("要求尽可能真实、完整,即使信息不完整也要尽量生成记录。\n");
context.append("如果知识库中没有任何福利费相关信息,请返回空数组。\n");
context.append("如果有福利费相关信息请至少生成3-5条记录尽可能多地提取信息。\n");
return context.toString();
}
/**
* 处理子项返回结果
*/
private JSONArray processSubItemResult(JSONArray result, String auditContent,
AuditContent9PersonnelConstants.AuditSubContent subContent) {
AuditContent9PersonnelConstants.AuditSubContent subContent, JSONArray ext) {
if (result == null || result.isEmpty()) {
JSONArray defaultResult = new JSONArray();
@@ -347,40 +517,47 @@ public class AuditContent9PersonnelServiceImpl extends AbstractAuditContentServi
return defaultResult;
}
// 检查是否是福利费列支范围检查子项
String extSubContent = AuditContent9PersonnelConstants.AUDIT_SUB_CONTENTS.get(AuditContent9PersonnelConstants.AUDIT_CONTENTS[2]).get(1).getAuditTarget();
if (ext.size() > 0 && subContent.getAuditTarget().equals(extSubContent)) {
// 将扩展数据添加到结果中
JSONObject firstItem = result.getJSONObject(0);
firstItem.put("ext", ext);
}
return result;
}
/**
* 关键词相关性比较器
*/
private int keywordRelevanceComparator(String content1, String content2) {
int score1 = calculateKeywordScore(content1);
int score2 = calculateKeywordScore(content2);
return Integer.compare(score2, score1);
}
/**
* 计算关键词得分
*/
private int calculateKeywordScore(String content) {
int score = 0;
for (Map.Entry<String, Integer> entry : AuditContent9PersonnelConstants.KEYWORD_WEIGHTS.entrySet()) {
if (content.contains(entry.getKey())) {
score += entry.getValue();
}
}
return score;
}
/**
* 获取不同来源的限制条数
*/
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "enterprise": return 80;
case "regulation": return 60;
case "auditCase": return 40;
default: return 30;
}
}
// /**
// * 关键词相关性比较器
// */
// private int keywordRelevanceComparator(String content1, String content2) {
// int score1 = calculateKeywordScore(content1);
// int score2 = calculateKeywordScore(content2);
// return Integer.compare(score2, score1);
// }
//
// /**
// * 计算关键词得分
// */
// private int calculateKeywordScore(String content) {
// int score = 0;
// for (Map.Entry<String, Integer> entry : AuditContent9PersonnelConstants.KEYWORD_WEIGHTS.entrySet()) {
// if (content.contains(entry.getKey())) {
// score += entry.getValue();
// }
// }
// return score;
// }
//
// /**
// * 获取不同来源的限制条数
// */
// private int getLimitBySourceType(String sourceType) {
// switch (sourceType) {
// case "enterprise": return 80;
// case "regulation": return 60;
// case "auditCase": return 40;
// default: return 30;
// }
// }
}