fu-hsi-service/src/main/java/com/supervision/police/service/impl/ModelIndexServiceImpl.java

332 lines
15 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.supervision.police.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.supervision.common.domain.R;
import com.supervision.common.utils.IPages;
import com.supervision.common.utils.StringUtils;
import com.supervision.police.domain.*;
import com.supervision.police.dto.AtomicData;
import com.supervision.police.dto.CaseAtomicIndexDTO;
import com.supervision.police.dto.CaseAtomicResultWrapper;
import com.supervision.police.dto.JudgeLogic;
import com.supervision.police.mapper.CasePersonMapper;
import com.supervision.police.mapper.ModelAtomicResultMapper;
import com.supervision.police.mapper.ModelIndexMapper;
import com.supervision.police.service.ComDictionaryService;
import com.supervision.police.service.ModelAtomicIndexService;
import com.supervision.police.service.ModelCaseService;
import com.supervision.police.service.ModelIndexService;
import com.supervision.utils.SqlParserUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 指标表(ModelIndex)表服务实现类
*
* @author qmy
* @since 2024-07-05 09:20:10
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class ModelIndexServiceImpl extends ServiceImpl<ModelIndexMapper, ModelIndex> implements ModelIndexService {
private final ComDictionaryService comDictionaryService;
private final ModelIndexMapper modelIndexMapper;
private final ModelAtomicIndexService modelAtomicIndexService;
private final ModelCaseService modelCaseService;
private final ModelAtomicResultMapper modelAtomicResultMapper;
private final CasePersonMapper casePersonMapper;
@Value("${case.evidence.table}")
private List<String> allowedTables;
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public R<?> selectAll(ModelIndex modelIndex, Integer page, Integer size) {
IPage<ModelIndex> iPage = new Page<>(page, size);
LambdaQueryWrapper<ModelIndex> wrapper = Wrappers.lambdaQuery();
wrapper.like(modelIndex.getName() != null, ModelIndex::getName, modelIndex.getName())
.like(modelIndex.getShortName() != null, ModelIndex::getShortName, modelIndex.getShortName())
.like(modelIndex.getRemark() != null, ModelIndex::getRemark, modelIndex.getRemark())
.eq(StringUtils.isNotEmpty(modelIndex.getIndexType()), ModelIndex::getIndexType, modelIndex.getIndexType())
.eq(StringUtils.isNotEmpty(modelIndex.getCaseType()), ModelIndex::getCaseType, modelIndex.getCaseType())
.eq(ModelIndex::getDataStatus, "1");
iPage = modelIndexMapper.selectPage(iPage, wrapper);
List<ModelIndex> records = iPage.getRecords();
List<ComDictionary> dicts = comDictionaryService.list();
for (ModelIndex index : records) {
index.setIndexTypeName(comDictionaryService.getName(dicts, "index_type", index.getIndexType()));
index.setCaseTypeName(comDictionaryService.getName(dicts, "case_type", index.getCaseType()));
//原子指标
String judgeLogic = index.getJudgeLogic();
List<String> ids = new ArrayList<>();
if (StringUtils.isNotEmpty(judgeLogic)) {
List<JudgeLogic> logic = JSONUtil.toList(judgeLogic, JudgeLogic.class);
for (JudgeLogic judge : logic) {
List<AtomicData> atomicData = judge.getAtomicData();
for (AtomicData atomic : atomicData) {
ids.add(atomic.getAtomicIndex());
}
}
List<ModelAtomicIndex> atomicIndexList = modelAtomicIndexService.selectBatchIds(ids);
index.setAtomicIndexList(atomicIndexList);
}
index.setAtomicIndexNum(ids.size());
}
iPage.setRecords(records);
return R.ok(IPages.buildDataMap(iPage));
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public R<?> addOrUpd(ModelIndex modelIndex) {
int i = 0;
if (StringUtils.isEmpty(modelIndex.getId())) {
i = modelIndexMapper.insert(modelIndex);
} else {
i = modelIndexMapper.updateById(modelIndex);
}
if (i > 0) {
return R.okMsg("保存成功");
} else {
return R.fail("保存失败");
}
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public R<?> del(String id) {
ModelIndex index = modelIndexMapper.selectById(id);
index.setDataStatus(StringUtils.getUUID());
int i = modelIndexMapper.updateById(index);
if (i > 0) {
return R.okMsg("删除成功");
} else {
return R.fail("删除失败");
}
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public R<?> selectAllAtomic(ModelAtomicIndex modelAtomicIndex, Integer page, Integer size) {
IPage<ModelAtomicIndex> iPage = new Page<>(page, size);
iPage = modelAtomicIndexService.selectAll(iPage, modelAtomicIndex);
List<ModelAtomicIndex> records = iPage.getRecords();
List<ComDictionary> dicts = comDictionaryService.list();
for (ModelAtomicIndex index : records) {
index.setCaseTypeName(comDictionaryService.getName(dicts, "case_type", index.getCaseType()));
index.setIndexSourceName(comDictionaryService.getName(dicts, "index_source", index.getIndexSource()));
index.setRecordTypeName(comDictionaryService.getName(dicts, "record_type", index.getRecordType()));
}
iPage.setRecords(records);
return R.ok(IPages.buildDataMap(iPage));
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public R<?> addOrUpdAtomic(ModelAtomicIndex modelAtomicIndex) {
int i = 0;
if (StringUtils.equals("2", modelAtomicIndex.getIndexSource())){
// 如果查询类型为数据查询,则校验查询语句
Assert.notEmpty(modelAtomicIndex.getQueryLang(), "查询语言不能为空");
Assert.isFalse(checkSql(modelAtomicIndex.getQueryLang()), "查询语句不合法");
}
if (StringUtils.isEmpty(modelAtomicIndex.getId())) {
i = modelAtomicIndexService.getMapper().insert(modelAtomicIndex);
} else {
i = modelAtomicIndexService.getMapper().updateById(modelAtomicIndex);
}
if (i > 0) {
return R.okMsg("保存成功");
} else {
return R.fail("保存失败");
}
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public R<?> delAtomic(String id) {
ModelAtomicIndex index = modelAtomicIndexService.getMapper().selectById(id);
index.setDataStatus(StringUtils.getUUID());
int i = modelAtomicIndexService.getMapper().updateById(index);
if (i > 0) {
return R.okMsg("删除成功");
} else {
return R.fail("删除失败");
}
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public List<CaseAtomicIndexDTO> listCaseAtomicIndex(String caseId, String indexSource) {
Assert.notEmpty(caseId, "案件id不能为空");
ModelCase modelCase = modelCaseService.getById(caseId);
Assert.notNull(modelCase, "案件不存在");
String caseType = modelCase.getCaseType();
Assert.notEmpty(caseType, "案件类型不能为空");
List<CasePerson> casePersonList = casePersonMapper.selectList(Wrappers.lambdaQuery(CasePerson.class)
.eq(CasePerson::getCaseId, caseId).eq(CasePerson::getRoleCode, "1"));
Assert.notEmpty(casePersonList, "案件行为人不能为空!");
String actorId = CollUtil.getFirst(casePersonList).getId();
// 获取案件类型对应的指标
List<ModelIndex> modelIndexList = modelIndexMapper.selectList(
Wrappers.lambdaQuery(ModelIndex.class)
.eq(ModelIndex::getCaseType, caseType)
.eq(ModelIndex::getIndexType, indexSource).eq(ModelIndex::getDataStatus, "1"));
if (CollUtil.isEmpty(modelIndexList)){
return new ArrayList<>(1);
}
// 从指标中计算出所有原子指标id
List<String> automicIndexIds = modelIndexList.stream().filter(modelIndex -> StrUtil.isNotEmpty(modelIndex.getJudgeLogic()))
.map(modelIndex -> pickAtomicIndexIds(modelIndex.getJudgeLogic()))
.flatMap(Collection::stream).distinct().toList();
if (CollUtil.isEmpty(automicIndexIds)){
return new ArrayList<>(1);
}
// 查询原子指标相关信息
List<ModelAtomicIndex> modelAtomicIndexList = modelAtomicIndexService.listCaseAtomicIndex(automicIndexIds, caseType, indexSource);
if (CollUtil.isEmpty(modelAtomicIndexList)){
return new ArrayList<>(1);
}
Map<String, ModelAtomicIndex> modelAtomicIndexMap = modelAtomicIndexList.stream().collect(Collectors.toMap(ModelAtomicIndex::getId, v -> v, (v1, v2) -> v1));
// 查询判定结果数据
List<ModelAtomicResult> modelAtomicResults = modelAtomicResultMapper.selectList(
Wrappers.lambdaQuery(ModelAtomicResult.class).eq(ModelAtomicResult::getCaseId, caseId)
.eq(ModelAtomicResult::getCasePersonId, actorId)
.in(ModelAtomicResult::getAtomicId, automicIndexIds));
Map<String, ModelAtomicResult> modelAtomicResultMap = modelAtomicResults.stream()
.filter(modelAtomicResult -> StrUtil.isNotEmpty(modelAtomicResult.getAtomicId())).collect(Collectors.toMap(ModelAtomicResult::getAtomicId, v -> v, (v1, v2) -> v1));
// 以指标为基础数据,组装原子指标的值。然后把数据进行平铺
return modelIndexList.stream().flatMap(modelIndex -> {
String judgeLogic = modelIndex.getJudgeLogic();
List<String> indexIds = pickAtomicIndexIds(judgeLogic);
return indexIds.stream().map(indexId ->
new CaseAtomicIndexDTO(modelAtomicIndexMap.get(indexId), modelIndex, modelAtomicResultMap.get(indexId))).toList().stream();
}).toList();
}
@Override
@Transactional(transactionManager = "dataSourceTransactionManager",rollbackFor = Exception.class)
public Boolean saveCaseAtomicResult(CaseAtomicResultWrapper caseAtomicResultWrapper) {
Assert.notEmpty(caseAtomicResultWrapper.getCaseId(), "案件id不能为空");
ModelCase modelCase = modelCaseService.getById(caseAtomicResultWrapper.getCaseId());
Assert.notNull(modelCase, "案件不存在!");
// 设置行为人id
List<CasePerson> casePersonList = casePersonMapper.selectList(Wrappers.lambdaQuery(CasePerson.class)
.eq(CasePerson::getCaseId, modelCase.getId()).eq(CasePerson::getRoleCode, "1"));
Assert.notEmpty(casePersonList, "案件行为人不能为空!");
caseAtomicResultWrapper.setActorId(CollUtil.getFirst(casePersonList).getId());
//清空人工评估结果
removeCaseAtomicResult(caseAtomicResultWrapper.getCaseId(),modelCase.getCaseType(),
caseAtomicResultWrapper.getActorId(),"1");
// 保存原子评估结果
caseAtomicResultWrapper.getCaseAtomicIndexList().stream().map(caseAtomicIndexDTO ->
caseAtomicIndexDTO.toModelAtomicResult(
caseAtomicResultWrapper.getCaseId(), caseAtomicResultWrapper.getActorId())).toList()
.forEach(modelAtomicResultMapper::insert);
return true;
}
@Override
public boolean checkSql(String sql) {
if (StringUtils.isEmpty(sql)) {
return false;
}
if (CollUtil.isEmpty(this.allowedTables)){
log.info("checkSql:未配置允许的表");
return false;
}
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement sqlStatement = SqlParserUtil.parseStatement(parser);
if (Objects.isNull(sqlStatement)) {
log.warn("checkSql sql:{}语句解析失败", sql);
return false;
}
String sqlType = SqlParserUtil.detectSQLType(sqlStatement);
if (!"SELECT".equals(sqlType)) {
log.warn("checkSql:只支持查询类型语句");
return false;
}
List<String> tableList = SqlParserUtil.extractTableNames(sqlStatement);
if (CollUtil.isEmpty(tableList)){
log.warn("checkSql:未检测到表");
return false;
}
long count = tableList.stream().filter(table -> !this.allowedTables.contains(table)).count();
if (count > 0){
log.warn("checkSql:表{}不在允许的表列表中",tableList);
return false;
}
return true;
}
/**
* 清空案件下的评估结果
* @param caseId 案件id
* @param caseType 案件类型
* @param actorId 行为人id
* @param indexSource 原子指标来源
*/
private void removeCaseAtomicResult(String caseId,String caseType, String actorId,String indexSource) {
List<ModelAtomicIndex> modelAtomicIndexList = modelAtomicIndexService.listCaseAtomicIndex(null, caseType, indexSource);
List<String> automicIndexIds = modelAtomicIndexList.stream().map(ModelAtomicIndex::getId).distinct().toList();
modelAtomicResultMapper.delete(Wrappers.lambdaQuery(ModelAtomicResult.class)
.eq(ModelAtomicResult::getCaseId, caseId)
.eq(ModelAtomicResult::getCasePersonId, actorId)
.in(CollUtil.isNotEmpty(automicIndexIds),ModelAtomicResult::getAtomicId, automicIndexIds));
}
/**
* 从逻辑中获取原子指标id
* @param judgeLogic 判断逻辑json字符串
* @return 原子指标id(不重复)
*/
private List<String> pickAtomicIndexIds(String judgeLogic) {
List<String> ids = new ArrayList<>();
List<JudgeLogic> logic = JSONUtil.toList(judgeLogic, JudgeLogic.class);
for (JudgeLogic judge : logic) {
List<AtomicData> atomicData = judge.getAtomicData();
for (AtomicData atomic : atomicData) {
if (!ids.contains(atomic.getAtomicIndex())){
ids.add(atomic.getAtomicIndex());
}
}
}
return ids;
}
}