新增生成决策支出表

This commit is contained in:
2025-12-02 15:48:05 +08:00
parent 3c85129f71
commit 610e50ed54
5 changed files with 589 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
package com.gxwebsoft.ai.constants;
import java.util.HashMap;
import java.util.Map;
/**
* 支出情况表常量类
*/
public class AuditContent1ExpenseConstants {
// 支出类型分类
public static final String EXPENSE_TYPE_RECEPTION = "公务接待";
public static final String EXPENSE_TYPE_OVERSEAS = "出国";
public static final String EXPENSE_TYPE_VEHICLE = "公车运行维护";
public static final String EXPENSE_TYPE_MEETING = "会议培训费";
// 年度范围
public static final int[] YEAR_RANGE = {2020, 2021, 2022, 2023};
// 分类描述
public static final Map<String, String> EXPENSE_DESCRIPTIONS = new HashMap<>();
static {
EXPENSE_DESCRIPTIONS.put(EXPENSE_TYPE_RECEPTION, "公务接待费用支出情况");
EXPENSE_DESCRIPTIONS.put(EXPENSE_TYPE_OVERSEAS, "出国(出境)费用支出情况");
EXPENSE_DESCRIPTIONS.put(EXPENSE_TYPE_VEHICLE, "公车运行维护费用支出情况");
EXPENSE_DESCRIPTIONS.put(EXPENSE_TYPE_MEETING, "会议、培训费用支出情况");
}
// 数据格式要求
public static final String DATA_FORMAT_REQUIREMENT =
"每条记录应包含以下字段:\n" +
"- expenseType支出类型公务接待/出国/公车运行维护/会议培训费)\n" +
"- year年份2020-2023\n" +
"- finalStatementAmount决算报表数单位\n" +
"- initialBudgetAmount年初预算数单位\n" +
"- changePercentage增减情况%\n" +
"- budgetRatio占年初预算比例%\n" +
"- remark备注信息\n" +
"- dataSource数据来源文件\n" +
"- workPaperIndex相关文件索引";
// 关键词权重
public static final Map<String, Integer> KEYWORD_WEIGHTS = new HashMap<>();
static {
KEYWORD_WEIGHTS.put("决算", 10);
KEYWORD_WEIGHTS.put("预算", 10);
KEYWORD_WEIGHTS.put("公务接待", 9);
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("财务报表", 9);
KEYWORD_WEIGHTS.put("年度报告", 8);
KEYWORD_WEIGHTS.put("预算执行", 8);
KEYWORD_WEIGHTS.put("财务分析", 7);
}
// 数据来源关键词
public static final String[] DATA_SOURCE_KEYWORDS = {
"决算报表", "预算报表", "财务报告", "年度报告",
"预算执行情况", "经费使用情况", "支出明细", "费用分析"
};
private AuditContent1ExpenseConstants() {
// 防止实例化
}
}

View File

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.ai.dto.AuditContentRequest; import com.gxwebsoft.ai.dto.AuditContentRequest;
import com.gxwebsoft.ai.dto.export.EightRegExportEntity; import com.gxwebsoft.ai.dto.export.EightRegExportEntity;
import com.gxwebsoft.ai.dto.export.ExpenseExportEntity;
import com.gxwebsoft.ai.dto.export.LeaderListExportEntity; import com.gxwebsoft.ai.dto.export.LeaderListExportEntity;
import com.gxwebsoft.ai.entity.AiCloudDoc; import com.gxwebsoft.ai.entity.AiCloudDoc;
import com.gxwebsoft.ai.entity.AiCloudFile; import com.gxwebsoft.ai.entity.AiCloudFile;
@@ -17,6 +18,7 @@ import com.gxwebsoft.pwl.service.PwlProjectLibraryService;
import com.gxwebsoft.ai.service.AiCloudDocService; import com.gxwebsoft.ai.service.AiCloudDocService;
import com.gxwebsoft.ai.service.AiCloudFileService; import com.gxwebsoft.ai.service.AiCloudFileService;
import com.gxwebsoft.ai.service.AuditContent1EightRegService; import com.gxwebsoft.ai.service.AuditContent1EightRegService;
import com.gxwebsoft.ai.service.AuditContent1ExpenseService;
import com.gxwebsoft.ai.service.AuditContent1LeaderListService; import com.gxwebsoft.ai.service.AuditContent1LeaderListService;
import com.gxwebsoft.ai.service.KnowledgeBaseService; import com.gxwebsoft.ai.service.KnowledgeBaseService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@@ -45,6 +47,9 @@ public class AuditContent1Controller extends BaseController {
@Autowired @Autowired
private AuditContent1LeaderListService auditContent1LeaderListService; private AuditContent1LeaderListService auditContent1LeaderListService;
@Autowired
private AuditContent1ExpenseService auditContent1ExpenseService;
@Autowired @Autowired
private AuditContent1EightRegService auditContent1EightRegService; private AuditContent1EightRegService auditContent1EightRegService;
@@ -79,6 +84,19 @@ public class AuditContent1Controller extends BaseController {
)); ));
} }
/**
* 生成支出情况表数据
*/
@Operation(summary = "生成支出情况表")
@PostMapping("/generateExpenseTable")
public ApiResult<?> generateExpenseTable(@RequestBody AuditContentRequest request, HttpServletRequest servletRequest) {
return generateTableData(request, servletRequest.getRequestURI(),
(params) -> auditContent1ExpenseService.generateExpenseTableData(
params.knowledgeBaseId, params.libraryKbIds, params.projectLibrary,
params.username, params.history, params.suggestion
));
}
/** /**
* 生成八项规定对比分析表数据 * 生成八项规定对比分析表数据
*/ */
@@ -339,4 +357,35 @@ public class AuditContent1Controller extends BaseController {
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex"))); entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity; return entity;
} }
/**
* 导出支出情况表到Excel
*/
@Operation(summary = "导出支出情况表到Excel")
@PostMapping("/exportExpenseTable")
public void exportExpenseTable(@RequestBody Map<String, Object> request, HttpServletResponse response) {
exportToExcel(request, response, "支出情况表",
this::convertToExpenseEntityList, ExpenseExportEntity.class);
}
// ========== 数据转换方法 ==========
private List<ExpenseExportEntity> convertToExpenseEntityList(List<Map<String, Object>> originalData) {
return originalData.stream().map(this::convertToExpenseEntity).collect(Collectors.toList());
}
private ExpenseExportEntity convertToExpenseEntity(Map<String, Object> item) {
ExpenseExportEntity entity = new ExpenseExportEntity();
entity.setExpenseType(getStringValue(item, "expenseType"));
entity.setYear(getStringValue(item, "year"));
entity.setFinalStatementAmount(getStringValue(item, "finalStatementAmount"));
entity.setInitialBudgetAmount(getStringValue(item, "initialBudgetAmount"));
entity.setChangePercentage(getStringValue(item, "changePercentage"));
entity.setBudgetRatio(getStringValue(item, "budgetRatio"));
entity.setRemark(getStringValue(item, "remark"));
entity.setDataSource(getStringValue(item, "dataSource"));
entity.setWorkPaperIndex(formatWorkPaperIndex(item.get("workPaperIndex")));
return entity;
}
} }

View File

@@ -0,0 +1,38 @@
package com.gxwebsoft.ai.dto.export;
import cn.afterturn.easypoi.excel.annotation.Excel;
import lombok.Data;
/**
* 支出情况表导出实体类
*/
@Data
public class ExpenseExportEntity {
@Excel(name = "支出类型", orderNum = "0", width = 12)
private String expenseType;
@Excel(name = "年份", orderNum = "1", width = 8)
private String year;
@Excel(name = "决算报表数(元)", orderNum = "2", width = 15)
private String finalStatementAmount;
@Excel(name = "年初预算数(元)", orderNum = "3", width = 15)
private String initialBudgetAmount;
@Excel(name = "增减情况(%", orderNum = "4", width = 12)
private String changePercentage;
@Excel(name = "占年初预算比例(%", orderNum = "5", width = 12)
private String budgetRatio;
@Excel(name = "备注", orderNum = "6", width = 20)
private String remark;
@Excel(name = "数据来源", orderNum = "7", width = 20)
private String dataSource;
@Excel(name = "工作底稿索引", orderNum = "8", width = 25)
private String workPaperIndex;
}

View File

@@ -0,0 +1,21 @@
package com.gxwebsoft.ai.service;
import com.alibaba.fastjson.JSONObject;
/**
* 支出情况表服务接口
*/
public interface AuditContent1ExpenseService {
/**
* 生成支出情况表数据
* @param kbIds 知识库ID
* @param libraryKbIds 项目库KB IDs
* @param projectLibrary 项目库ID
* @param userName 用户名
* @param history 历史记录
* @param suggestion 建议
* @return JSON格式的结果
*/
JSONObject generateExpenseTableData(String kbIds, String libraryKbIds, String projectLibrary, String userName, String history, String suggestion);
}

View File

@@ -0,0 +1,412 @@
package com.gxwebsoft.ai.service.impl;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.ai.constants.AuditContent1ExpenseConstants;
import com.gxwebsoft.ai.service.AuditContent1ExpenseService;
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 AuditContent1ExpenseServiceImpl extends AbstractAuditContentService implements AuditContent1ExpenseService {
// 工作流配置
private static final String DIFY_WORKFLOW_TOKEN = "Bearer app-xwWxGF6hERgdeKB5OPpj9Tq8";
@Override
public JSONObject generateExpenseTableData(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<String, List<String>> knowledgeSources = retrieveKnowledgeForExpense(kbIds, libraryKbIds, projectLibrary);
// 2. 构建完整的知识上下文
String knowledgeContext = buildCompleteKnowledgeContext(knowledgeSources, history, suggestion);
// 3. 调用工作流生成数据
JSONObject requestBody = buildWorkflowRequest(knowledgeContext, userName);
JSONArray expenseData = callWorkflow(DIFY_WORKFLOW_URL, DIFY_WORKFLOW_TOKEN, requestBody, "支出情况表");
// 4. 数据验证和补充
expenseData = validateAndEnhanceExpenseData(expenseData);
log.info("支出情况表生成成功 - 记录数: {}, 处理时间: {}ms",
expenseData.size(), (System.currentTimeMillis() - startTime));
return buildSuccessResponse(expenseData, startTime, "expense_audit");
} catch (Exception e) {
log.error("生成支出情况表失败", e);
return buildErrorResponse("生成支出情况表失败: " + e.getMessage());
}
}
/**
* 验证和增强支出情况表数据
*/
private JSONArray validateAndEnhanceExpenseData(JSONArray originalData) {
if (originalData == null || originalData.isEmpty()) {
log.warn("原始数据为空,返回空数组");
return new JSONArray();
}
JSONArray enhancedData = new JSONArray();
for (int i = 0; i < originalData.size(); i++) {
JSONObject item = originalData.getJSONObject(i);
if (item != null) {
// 确保所有必需字段都存在
enhanceExpenseData(item);
enhancedData.add(item);
}
}
// 确保数据完整性至少16条记录
if (enhancedData.size() < 16) {
enhancedData = supplementMissingExpenseData(enhancedData);
}
log.info("数据增强完成 - 原始记录数: {}, 增强后记录数: {}", originalData.size(), enhancedData.size());
return enhancedData;
}
/**
* 增强单个支出数据
*/
private void enhanceExpenseData(JSONObject expenseData) {
// 确保支出类型正确
String expenseType = expenseData.getString("expenseType");
if (StrUtil.isBlank(expenseType) || !isValidExpenseType(expenseType)) {
expenseData.put("expenseType", AuditContent1ExpenseConstants.EXPENSE_TYPE_RECEPTION);
}
// 确保年份在2020-2023范围内
String year = expenseData.getString("year");
if (StrUtil.isBlank(year) || !isValidYear(year)) {
expenseData.put("year", "2023");
}
// 确保金额格式正确
if (StrUtil.isBlank(expenseData.getString("finalStatementAmount"))) {
expenseData.put("finalStatementAmount", "0.00");
}
if (StrUtil.isBlank(expenseData.getString("initialBudgetAmount"))) {
expenseData.put("initialBudgetAmount", "0.00");
}
// 计算缺失的百分比字段
calculateMissingPercentages(expenseData);
// 确保数据来源
if (StrUtil.isBlank(expenseData.getString("dataSource"))) {
String yearStr = expenseData.getString("year");
expenseData.put("dataSource", yearStr + "年度部门决算报表");
}
// 确保工作底稿索引是数组格式
if (!expenseData.containsKey("workPaperIndex") || expenseData.get("workPaperIndex") == null) {
JSONArray workPaperIndex = new JSONArray();
workPaperIndex.add("" + expenseData.getString("year") + "年度部门决算报表》");
workPaperIndex.add("" + expenseData.getString("year") + "年预算执行情况分析》");
expenseData.put("workPaperIndex", workPaperIndex);
}
}
/**
* 补充缺失的支出数据
*/
private JSONArray supplementMissingExpenseData(JSONArray existingData) {
JSONArray supplementedData = new JSONArray();
supplementedData.addAll(existingData);
// 获取已存在的数据组合
Set<String> existingCombinations = new HashSet<>();
for (int i = 0; i < existingData.size(); i++) {
JSONObject item = existingData.getJSONObject(i);
String key = item.getString("expenseType") + "_" + item.getString("year");
existingCombinations.add(key);
}
// 补充缺失的数据
String[] expenseTypes = {
AuditContent1ExpenseConstants.EXPENSE_TYPE_RECEPTION,
AuditContent1ExpenseConstants.EXPENSE_TYPE_OVERSEAS,
AuditContent1ExpenseConstants.EXPENSE_TYPE_VEHICLE,
AuditContent1ExpenseConstants.EXPENSE_TYPE_MEETING
};
String[] years = {"2020", "2021", "2022", "2023"};
for (String expenseType : expenseTypes) {
for (String year : years) {
String key = expenseType + "_" + year;
if (!existingCombinations.contains(key)) {
JSONObject newItem = createDefaultExpenseRecord(expenseType, year);
supplementedData.add(newItem);
}
}
}
return supplementedData;
}
/**
* 创建默认的支出记录
*/
private JSONObject createDefaultExpenseRecord(String expenseType, String year) {
JSONObject record = new JSONObject();
record.put("expenseType", expenseType);
record.put("year", year);
record.put("finalStatementAmount", "0.00");
record.put("initialBudgetAmount", "0.00");
record.put("changePercentage", "0.0%");
record.put("budgetRatio", "0.0%");
record.put("remark", "根据年度财务报告数据生成");
record.put("dataSource", year + "年度部门决算报表");
JSONArray workPaperIndex = new JSONArray();
workPaperIndex.add("" + year + "年度部门决算报表》");
workPaperIndex.add("" + year + "年预算执行情况分析》");
record.put("workPaperIndex", workPaperIndex);
return record;
}
/**
* 计算缺失的百分比字段
*/
private void calculateMissingPercentages(JSONObject expenseData) {
try {
String finalAmountStr = expenseData.getString("finalStatementAmount").replace(",", "");
String budgetAmountStr = expenseData.getString("initialBudgetAmount").replace(",", "");
double finalAmount = Double.parseDouble(finalAmountStr);
double budgetAmount = Double.parseDouble(budgetAmountStr);
// 计算增减百分比
if (budgetAmount > 0) {
double changePercentage = ((finalAmount - budgetAmount) / budgetAmount) * 100;
if (!expenseData.containsKey("changePercentage") || StrUtil.isBlank(expenseData.getString("changePercentage"))) {
expenseData.put("changePercentage", String.format("%.1f%%", changePercentage));
}
// 计算预算占比
double budgetRatio = (finalAmount / budgetAmount) * 100;
if (!expenseData.containsKey("budgetRatio") || StrUtil.isBlank(expenseData.getString("budgetRatio"))) {
expenseData.put("budgetRatio", String.format("%.1f%%", budgetRatio));
}
}
} catch (Exception e) {
log.warn("计算百分比失败: {}", e.getMessage());
}
}
/**
* 检查支出类型是否有效
*/
private boolean isValidExpenseType(String expenseType) {
return expenseType.equals(AuditContent1ExpenseConstants.EXPENSE_TYPE_RECEPTION) ||
expenseType.equals(AuditContent1ExpenseConstants.EXPENSE_TYPE_OVERSEAS) ||
expenseType.equals(AuditContent1ExpenseConstants.EXPENSE_TYPE_VEHICLE) ||
expenseType.equals(AuditContent1ExpenseConstants.EXPENSE_TYPE_MEETING);
}
/**
* 检查年份是否有效
*/
private boolean isValidYear(String year) {
for (int validYear : AuditContent1ExpenseConstants.YEAR_RANGE) {
if (year.equals(String.valueOf(validYear))) {
return true;
}
}
return false;
}
/**
* 检索支出情况表相关知识 - 优化查询策略
*/
private Map<String, List<String>> retrieveKnowledgeForExpense(String kbIds, String libraryKbIds, String projectLibrary) {
Map<String, List<String>> knowledgeSources = new HashMap<>();
knowledgeSources.put("financial", new ArrayList<>());
knowledgeSources.put("regulation", new ArrayList<>());
knowledgeSources.put("auditCase", new ArrayList<>());
// 构建更全面的查询词
List<String> queries = buildEnhancedExpenseQueries();
// 财务数据库检索
if (StrUtil.isNotBlank(kbIds)) {
Arrays.stream(kbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(kbId -> {
List<String> financialKnowledge = queryKnowledgeBase(kbId, queries, 200);
knowledgeSources.get("financial").addAll(financialKnowledge);
log.debug("财务知识库 {} 检索到 {} 条相关知识", kbId, financialKnowledge.size());
});
}
// 公共法律法规库检索
if (StrUtil.isNotBlank(libraryKbIds)) {
Arrays.stream(libraryKbIds.split(","))
.map(String::trim)
.filter(StrUtil::isNotBlank)
.forEach(libId -> {
List<String> regulationKnowledge = queryKnowledgeBase(libId, queries, 100);
knowledgeSources.get("regulation").addAll(regulationKnowledge);
});
}
// 审计案例库检索
if (StrUtil.isNotBlank(projectLibrary)) {
List<String> auditCaseKnowledge = queryKnowledgeBase(projectLibrary, queries, 50);
knowledgeSources.get("auditCase").addAll(auditCaseKnowledge);
}
// 智能去重和排序
knowledgeSources.forEach((key, list) -> {
List<String> processed = list.stream()
.distinct()
.sorted(this::expenseComparator)
.limit(getLimitBySourceType(key))
.collect(Collectors.toList());
knowledgeSources.put(key, processed);
});
log.info("支出情况表知识检索完成 - 财务: {}条, 法规: {}条, 案例: {}条",
knowledgeSources.get("financial").size(),
knowledgeSources.get("regulation").size(),
knowledgeSources.get("auditCase").size());
return knowledgeSources;
}
/**
* 构建增强的支出情况表查询词
*/
private List<String> buildEnhancedExpenseQueries() {
return Arrays.asList(
"决算报表 预算报表 财务报表 年度报告",
"公务接待费 接待费用 招待费用 餐饮费用",
"出国费用 出境费用 国际差旅 境外考察",
"公车运行维护 车辆费用 汽车费用 交通费用",
"会议费 培训费 会务费 培训费用",
"八项规定 三公经费 公务支出",
"预算执行 预算调整 超预算 预算控制",
"2020年 2021年 2022年 2023年",
"支出明细 费用明细 开支情况",
"财务分析 费用分析 支出分析"
);
}
/**
* 构建完整的知识上下文 - 优化提示
*/
private String buildCompleteKnowledgeContext(Map<String, List<String>> knowledgeSources, String history, String suggestion) {
StringBuilder context = new StringBuilder();
// 1. 支出情况表分析要求 - 增强要求
context.append("## 支出情况表分析要求\n");
context.append("请基于以下知识生成完整详细的公务接待/出国/公车运行维护/会议培训费等支出情况表数据:\n\n");
context.append("1. 必须生成完整的支出情况表数据覆盖2020-2023四个年度\n");
context.append("2. 重点关注四类支出:公务接待、出国(出境)、公车运行维护、会议培训费\n");
context.append("3. 从财务知识库中提取所有实际的支出数据,要求全面完整\n");
context.append("4. 确保信息的准确性和完整性,包括决算数、预算数、增减情况和占比情况\n");
context.append("5. 工作底稿索引必须准确对应实际文件名称,可以包含多个相关文件\n");
context.append("6. 要求生成尽可能多、尽可能完整的支出记录,覆盖所有年份和支出类型\n\n");
// 2. 数据格式要求
context.append("## 数据格式要求\n");
context.append("需要生成完整详细的支出情况表数据:\n\n");
context.append(AuditContent1ExpenseConstants.DATA_FORMAT_REQUIREMENT);
context.append("\n\n重要要求\n");
context.append("1. 必须根据知识库内容生成尽可能多、尽可能完整的支出信息\n");
context.append("2. 工作底稿索引必须准确对应实际文件名称,避免使用附表或章节标题\n");
context.append("3. 金额单位为元,保持两位小数,可以使用逗号分隔千位\n");
context.append("4. 百分比计算要准确,增减情况正数表示增长,负数表示减少\n");
context.append("5. 数据来源要具体2023年度部门决算报表\n");
context.append("6. 备注信息可以包含超支原因、特殊情况说明等\n\n");
// 3. 历史内容
if (StrUtil.isNotBlank(history)) {
context.append("## 历史生成内容\n");
context.append("以下是之前生成的内容,请基于此进行优化和补充:\n");
context.append(history).append("\n\n");
}
// 4. 用户建议
if (StrUtil.isNotBlank(suggestion)) {
context.append("## 用户优化建议\n");
context.append("请根据以下建议对生成内容进行调整:\n");
context.append(suggestion).append("\n\n");
}
// 5. 财务知识
if (!knowledgeSources.get("financial").isEmpty()) {
context.append("## 财务知识\n");
context.append("这是财务相关的报表和文件信息,请仔细分析并提取所有支出数据:\n");
knowledgeSources.get("financial").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 6. 法律法规知识
if (!knowledgeSources.get("regulation").isEmpty()) {
context.append("## 法律法规知识\n");
knowledgeSources.get("regulation").forEach(knowledge ->
context.append(knowledge).append("\n"));
context.append("\n");
}
// 7. 审计案例知识
if (!knowledgeSources.get("auditCase").isEmpty()) {
context.append("## 审计案例知识\n");
knowledgeSources.get("auditCase").forEach(knowledge ->
context.append(knowledge).append("\n"));
}
log.debug("构建的知识上下文长度: {}", context.length());
return context.toString();
}
/**
* 支出情况表相关性比较器
*/
private int expenseComparator(String content1, String content2) {
int score1 = calculateExpenseRelevanceScore(content1);
int score2 = calculateExpenseRelevanceScore(content2);
return Integer.compare(score2, score1);
}
/**
* 计算支出情况表相关性分数
*/
private int calculateExpenseRelevanceScore(String content) {
return AuditContent1ExpenseConstants.KEYWORD_WEIGHTS.entrySet().stream()
.filter(entry -> content.contains(entry.getKey()))
.mapToInt(Map.Entry::getValue)
.sum();
}
private int getLimitBySourceType(String sourceType) {
switch (sourceType) {
case "financial": return 150;
case "regulation": return 80;
case "auditCase": return 40;
default: return 100;
}
}
}