|
|
@@ -5,23 +5,33 @@ import cn.hutool.core.date.DateTime;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
+import com.xunmei.common.core.constant.CacheConstants;
|
|
|
+import com.xunmei.common.core.domain.safetyindex.domain.CoreSafetyDeductData;
|
|
|
import com.xunmei.common.core.domain.safetyindex.domain.CoreSafetyExceptionData;
|
|
|
+import com.xunmei.common.core.domain.safetyindex.domain.CoreSafetySourceData;
|
|
|
import com.xunmei.common.core.domain.safetyindex.vo.SafeIndexRuleCountVo;
|
|
|
+import com.xunmei.common.redis.utils.RedisUtils;
|
|
|
import com.xunmei.core.question.service.IQuestionService;
|
|
|
import com.xunmei.core.resumption.service.ResumptionService;
|
|
|
import com.xunmei.core.retrieval.service.ICoreMonitoringRetrievalTaskService;
|
|
|
import com.xunmei.core.safetyindex.mapper.CoreSafetyExceptionDataMapper;
|
|
|
+import com.xunmei.core.safetyindex.service.ICoreSafetyDeductDataService;
|
|
|
import com.xunmei.core.safetyindex.service.ICoreSafetyExceptionDataService;
|
|
|
import com.xunmei.core.safetyindex.service.ICoreSafetyIndexCalculateRuleService;
|
|
|
+import com.xunmei.core.safetyindex.service.ICoreSafetySourceDataService;
|
|
|
import com.xunmei.system.api.RemoteOrgService;
|
|
|
+import com.xunmei.system.api.vo.SysOrgVO;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
-import java.util.Date;
|
|
|
-import java.util.List;
|
|
|
-import java.util.TimeZone;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.*;
|
|
|
+import java.util.concurrent.atomic.AtomicReference;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
@@ -48,6 +58,10 @@ public class CoreSafetyExceptionDataServiceImpl extends ServiceImpl<CoreSafetyEx
|
|
|
|
|
|
@Autowired
|
|
|
private ICoreSafetyIndexCalculateRuleService ruleService;
|
|
|
+ @Autowired
|
|
|
+ private ICoreSafetyDeductDataService safetyDeductDataService;
|
|
|
+ @Autowired
|
|
|
+ private ICoreSafetySourceDataService sourceDataService;
|
|
|
|
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
@@ -70,9 +84,12 @@ public class CoreSafetyExceptionDataServiceImpl extends ServiceImpl<CoreSafetyEx
|
|
|
public static final String MONITORING_DICT_CODE = "1006";
|
|
|
|
|
|
@Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
public void calculateSafetyIndex(String date) {
|
|
|
|
|
|
DateTime time = dealTimeParam(date);
|
|
|
+ int year = time.year();
|
|
|
+ int month = time.month();
|
|
|
//获取指标配置
|
|
|
List<SafeIndexRuleCountVo> safeIndexConfigVoList = ruleService.findSafeIndexRuleVoList();
|
|
|
//履职的指标配置
|
|
|
@@ -88,6 +105,253 @@ public class CoreSafetyExceptionDataServiceImpl extends ServiceImpl<CoreSafetyEx
|
|
|
//监控调阅的异常数据
|
|
|
List<CoreSafetyExceptionData> monitoringExceptionDataList = queryExceptionDataList(CORE_MONITORING_RETRIEVAL_TASK, time);
|
|
|
|
|
|
+ //删除已有的计算数据
|
|
|
+ deleteOldData(year, month);
|
|
|
+
|
|
|
+
|
|
|
+ //计算安保履职
|
|
|
+ calculateResumptionData(resumptionIndexList, resumptionExceptionDataList, year, month);
|
|
|
+
|
|
|
+ //计算问题整改
|
|
|
+ calculateQuestionData(questionIndexList, questionExceptionDataList, year, month);
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void calculateQuestionData(List<SafeIndexRuleCountVo> questionIndexList, List<CoreSafetyExceptionData> dataList, int year, int month) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void calculateResumptionData(List<SafeIndexRuleCountVo> resumptionIndexList, List<CoreSafetyExceptionData> resumptionExceptionDataList, int year, int month) {
|
|
|
+ //扩展字段1:计划id 扩展字段2:计划执行时刻 (2,3,4 营业前中后)
|
|
|
+ //将数据按机构分组
|
|
|
+ Map<Long, List<CoreSafetyExceptionData>> safetyExceptionDataMapList = resumptionExceptionDataList.stream().collect(Collectors.groupingBy(CoreSafetyExceptionData::getOrgId));
|
|
|
+
|
|
|
+ List<SysOrgVO> orgList = RedisUtils.getCacheList(CacheConstants.ORG_CACHE_LIST_KEY);
|
|
|
+
|
|
|
+ for (Long orgId : safetyExceptionDataMapList.keySet()) {
|
|
|
+ orgList.parallelStream().filter(o -> ObjectUtil.equal(o.getId(), orgId)).findFirst().ifPresent(org -> {
|
|
|
+ //获取机构的指标配置
|
|
|
+ List<SafeIndexRuleCountVo> orgResumptionIndexList = resumptionIndexList.stream().filter(r -> ObjectUtil.equal(r.getOrgType(), org.getType())).collect(Collectors.toList());
|
|
|
+ if (orgResumptionIndexList.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //获取机构的异常数据
|
|
|
+ List<CoreSafetyExceptionData> resumptionExceptionDataListByOrg = safetyExceptionDataMapList.get(orgId);
|
|
|
+ //构建执行时刻的map,用于存储每个时刻的异常数据
|
|
|
+ Map<Integer, List<CoreSafetyExceptionData>> execTimeMap = buildExecTimeMap(resumptionExceptionDataListByOrg);
|
|
|
+
|
|
|
+
|
|
|
+ //营业前
|
|
|
+ List<SafeIndexRuleCountVo> resumptionBeforeUndoIndexList = resumptionIndexList.stream()
|
|
|
+ .filter(r -> ObjectUtil.equal("10040201", r.getPointCode()))
|
|
|
+ .filter(r -> r.getCalculateType() == 1)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (ObjectUtil.isNotEmpty(resumptionBeforeUndoIndexList)) {
|
|
|
+ List<CoreSafetySourceData> sourceDataList = calculateContinuousCumulativeCount(resumptionBeforeUndoIndexList, execTimeMap.get(2), orgId, year, month);
|
|
|
+ saveSourceData(sourceDataList, resumptionBeforeUndoIndexList.get(0));
|
|
|
+ }
|
|
|
+
|
|
|
+ //营业中
|
|
|
+ List<SafeIndexRuleCountVo> resumptionMiddleIndexList = resumptionIndexList.stream()
|
|
|
+ .filter(r -> ObjectUtil.equal("10040203", r.getPointCode()))
|
|
|
+ .filter(r -> r.getCalculateType() == 1)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (ObjectUtil.isNotEmpty(resumptionMiddleIndexList)) {
|
|
|
+ List<CoreSafetySourceData> sourceDataList = calculateContinuousCumulativeCount(resumptionMiddleIndexList, execTimeMap.get(4), orgId, year, month);
|
|
|
+ saveSourceData(sourceDataList, resumptionMiddleIndexList.get(0));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ //营业后
|
|
|
+ List<SafeIndexRuleCountVo> resumptionAfterUndoIndexList = resumptionIndexList.stream()
|
|
|
+ .filter(r -> ObjectUtil.equal("10040202", r.getPointCode()))
|
|
|
+ .filter(r -> r.getCalculateType() == 1)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (ObjectUtil.isNotEmpty(resumptionAfterUndoIndexList)) {
|
|
|
+ List<CoreSafetySourceData> sourceDataList = calculateContinuousCumulativeCount(resumptionAfterUndoIndexList, execTimeMap.get(4), orgId, year, month);
|
|
|
+ saveSourceData(sourceDataList, resumptionAfterUndoIndexList.get(0));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算连续数与累计数
|
|
|
+ *
|
|
|
+ * @param resumptionUndoIndexList
|
|
|
+ * @param dataList
|
|
|
+ * @param orgId
|
|
|
+ * @param year
|
|
|
+ * @param month
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private List<CoreSafetySourceData> calculateContinuousCumulativeCount(List<SafeIndexRuleCountVo> resumptionUndoIndexList, List<CoreSafetyExceptionData> dataList, Long orgId, int year, int month) {
|
|
|
+ SafeIndexRuleCountVo indexConfigCountVo = resumptionUndoIndexList.get(0);
|
|
|
+
|
|
|
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
|
|
+ List<CoreSafetySourceData> sourceDataList = new ArrayList<>();
|
|
|
+ int count = dataList.size();
|
|
|
+
|
|
|
+ double deductScore = count * indexConfigCountVo.getItemValue();
|
|
|
+
|
|
|
+ //计算累计数
|
|
|
+ if (count != 0) {
|
|
|
+ CoreSafetySourceData safeSourceData = doNewSafetySourceData(indexConfigCountVo, orgId, deductScore, year, month, count);
|
|
|
+ sourceDataList.add(safeSourceData);
|
|
|
+ }
|
|
|
+ //将异常数据的时间进行排序并格式化
|
|
|
+ List<String> dataTimeList = dataList.stream()
|
|
|
+ .sorted(Comparator.comparing(CoreSafetyExceptionData::getDataTime))
|
|
|
+ .map(CoreSafetyExceptionData::getDataTime)
|
|
|
+ .map(sdf::format).distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ //获取连续数的配置,并根据配置的连续数日期进行排序
|
|
|
+ List<SafeIndexRuleCountVo> resumptionContinuousIndexList = resumptionUndoIndexList.stream()
|
|
|
+ .filter(r -> r.getCalculateType() == 2)
|
|
|
+ .sorted(Comparator.comparing(SafeIndexRuleCountVo::getIndicatorDays))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ //连续数 3/5/10 连续出现次数
|
|
|
+ AtomicReference<Integer> atomicContinuousThreeDays = new AtomicReference<>(0);
|
|
|
+ AtomicReference<Integer> atomicContinuousFiveDays = new AtomicReference<>(0);
|
|
|
+ AtomicReference<Integer> atomicContinuousTenDays = new AtomicReference<>(0);
|
|
|
+ List<Map<Integer, List<String>>> mapList = groupContinuousDays(dataTimeList);
|
|
|
+ mapList.stream().flatMap(m -> m.entrySet().stream()).forEach(e -> {
|
|
|
+ Integer key = e.getKey();
|
|
|
+ List<String> value = e.getValue();
|
|
|
+ if (key >= 3) {
|
|
|
+ atomicContinuousThreeDays.getAndSet(atomicContinuousThreeDays.get() + 1);
|
|
|
+ }
|
|
|
+ if (key >= 5) {
|
|
|
+ atomicContinuousFiveDays.getAndSet(atomicContinuousFiveDays.get() + 1);
|
|
|
+ }
|
|
|
+ if (key >= 10) {
|
|
|
+ atomicContinuousTenDays.getAndSet(atomicContinuousTenDays.get() + 1);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ Integer continuousThreeDays = atomicContinuousThreeDays.get();
|
|
|
+ Integer continuousFiveDays = atomicContinuousFiveDays.get();
|
|
|
+ Integer continuousTenDays = atomicContinuousTenDays.get();
|
|
|
+
|
|
|
+ //第一次连续的分数
|
|
|
+ if (continuousThreeDays != 0) {
|
|
|
+ double threeDayDeductScore = continuousThreeDays * resumptionContinuousIndexList.get(0).getItemValue();
|
|
|
+ CoreSafetySourceData sourceData = doNewSafetySourceData(resumptionUndoIndexList.get(0), orgId, threeDayDeductScore, year, month, continuousThreeDays);
|
|
|
+ sourceDataList.add(sourceData);
|
|
|
+ }
|
|
|
+
|
|
|
+ //第二次连续的分数
|
|
|
+ if (continuousFiveDays != 0) {
|
|
|
+ double fiveDaysDeductScore = continuousFiveDays * resumptionContinuousIndexList.get(1).getItemValue();
|
|
|
+ CoreSafetySourceData sourceData = doNewSafetySourceData(resumptionUndoIndexList.get(1), orgId, fiveDaysDeductScore, year, month, continuousFiveDays);
|
|
|
+ sourceDataList.add(sourceData);
|
|
|
+ }
|
|
|
+
|
|
|
+ //第三次连续的分数
|
|
|
+ if (continuousTenDays != 0) {
|
|
|
+ double tenDaysDeductScore = continuousTenDays * resumptionContinuousIndexList.get(2).getItemValue();
|
|
|
+ CoreSafetySourceData sourceData = doNewSafetySourceData(resumptionUndoIndexList.get(2), orgId, tenDaysDeductScore, year, month, continuousTenDays);
|
|
|
+ sourceDataList.add(sourceData);
|
|
|
+ }
|
|
|
+
|
|
|
+ return sourceDataList;
|
|
|
+ }
|
|
|
+//传入一个已做好升序排序的数组,数组中的每个元素都是yyyy-MM-dd格式的时间,判断相邻元素是否是连续的时间,把所有的连续天数分组出来,放在一个map中,key为连续天数,value为连续天数的集合,最终返回一个List<Map<Integer,List<String>>这样的数据
|
|
|
+// 例如:传入参数:["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-06", "2022-01-07", "2022-01-08", "2022-01-09", "2022-01-11"],应该返回一个List<Map<Integer,List<String>>,数组中有两个map:一个map,其中一个key为4,value为["2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04"],另一个map,其中一个key也为4,value为["2022-01-06", "2022-01-07", "2022-01-08", "2022-01-09"],其中"2022-01-11" 这个元素应该被丢弃,因为它不与其他任何元素是相邻时间
|
|
|
+
|
|
|
+ public static List<Map<Integer, List<String>>> groupContinuousDays(List<String> days) {
|
|
|
+ List<Map<Integer, List<String>>> result = new ArrayList<>();
|
|
|
+ if (days == null || days.size() == 0) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ List<String> list = new ArrayList<>();
|
|
|
+ LocalDate preDate = LocalDate.parse(days.get(0), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
|
|
+ for (int i = 1; i < days.size(); i++) {
|
|
|
+ Map<Integer, List<String>> map = new HashMap<>();
|
|
|
+ LocalDate curDate = LocalDate.parse(days.get(i), DateTimeFormatter.ofPattern("yyyy-MM-dd"));
|
|
|
+ if (preDate.plusDays(1).equals(curDate)) {
|
|
|
+ if (!list.contains(days.get(i - 1))) {
|
|
|
+ list.add(days.get(i - 1));
|
|
|
+ }
|
|
|
+ if (!list.contains(days.get(i))) {
|
|
|
+ list.add(days.get(i));
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (list.size() > 0) {
|
|
|
+ map.put(list.size(), new ArrayList<>(list));
|
|
|
+ result.add(map);
|
|
|
+ list.clear();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ preDate = curDate;
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* public static void main(String[] args) {
|
|
|
+ String[] dates = {"2022-01-01", "2022-01-02", "2022-01-03", "2022-01-04", "2022-01-06", "2022-01-07", "2022-01-08", "2022-01-09", "2022-01-11"};
|
|
|
+ List<Map<Integer, List<String>>> result = groupContinuousDays(dates);
|
|
|
+
|
|
|
+ for (Map<Integer, List<String>> group : result) {
|
|
|
+ for (Map.Entry<Integer, List<String>> entry : group.entrySet()) {
|
|
|
+ int count = entry.getKey();
|
|
|
+ List<String> datesList = entry.getValue();
|
|
|
+ System.out.println("连续天数:" + count);
|
|
|
+ System.out.println("日期集合:" + datesList);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+
|
|
|
+
|
|
|
+ private CoreSafetySourceData doNewSafetySourceData(SafeIndexRuleCountVo indexConfigCountVo, Long orgId, double deductScore, int year, int month, int time) {
|
|
|
+ CoreSafetySourceData safeSourceData = new CoreSafetySourceData();
|
|
|
+ safeSourceData.setId(IdWorker.getId());
|
|
|
+ safeSourceData.setRuleId(indexConfigCountVo.getRuleId());
|
|
|
+ safeSourceData.setItemId(indexConfigCountVo.getItemId());
|
|
|
+ safeSourceData.setOrgId(orgId);
|
|
|
+ safeSourceData.setTimes(time);
|
|
|
+ safeSourceData.setScore(deductScore);
|
|
|
+ safeSourceData.setDataYear(year);
|
|
|
+ safeSourceData.setDataMonth(month);
|
|
|
+ safeSourceData.setTypeCode(indexConfigCountVo.getTypeCode());
|
|
|
+ return safeSourceData;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private Map<Integer, List<CoreSafetyExceptionData>> buildExecTimeMap(List<CoreSafetyExceptionData> resumptionExceptionDataListByOrg) {
|
|
|
+ HashMap<Integer, List<CoreSafetyExceptionData>> hashMap = new HashMap<>();
|
|
|
+ //未登营业前
|
|
|
+ List<CoreSafetyExceptionData> undoBeforeList = new ArrayList<>();
|
|
|
+ //未登营业中
|
|
|
+ List<CoreSafetyExceptionData> undoMiddleList = new ArrayList<>();
|
|
|
+ //未登营业后
|
|
|
+ List<CoreSafetyExceptionData> undoAfterList = new ArrayList<>();
|
|
|
+ hashMap.put(2, undoBeforeList);
|
|
|
+ hashMap.put(3, undoMiddleList);
|
|
|
+ hashMap.put(4, undoAfterList);
|
|
|
+ resumptionExceptionDataListByOrg.stream().filter(r -> ObjectUtil.equal(r.getExtraField2(), "2")).forEach(r -> {
|
|
|
+ hashMap.get(2).add(r);
|
|
|
+ });
|
|
|
+ resumptionExceptionDataListByOrg.stream().filter(r -> ObjectUtil.equal(r.getExtraField2(), "3")).forEach(r -> {
|
|
|
+ hashMap.get(3).add(r);
|
|
|
+ });
|
|
|
+ resumptionExceptionDataListByOrg.stream().filter(r -> ObjectUtil.equal(r.getExtraField2(), "4")).forEach(r -> {
|
|
|
+ hashMap.get(4).add(r);
|
|
|
+ });
|
|
|
+
|
|
|
+ return hashMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void deleteOldData(int year, int month) {
|
|
|
+ //删除已有的计算数据
|
|
|
+ safetyDeductDataService.deleteSafeDeductData(year, month);
|
|
|
+ //删除已有的计算数据
|
|
|
+ sourceDataService.deleteSourceData(year, month);
|
|
|
}
|
|
|
|
|
|
private List<CoreSafetyExceptionData> queryExceptionDataList(String dataSource, DateTime time) {
|
|
|
@@ -146,4 +410,36 @@ public class CoreSafetyExceptionDataServiceImpl extends ServiceImpl<CoreSafetyEx
|
|
|
time.setField(DateField.MILLISECOND, 0);
|
|
|
return time;
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存数据到数据源
|
|
|
+ *
|
|
|
+ * @param sourceDataList
|
|
|
+ * @param indexConfigCountVo
|
|
|
+ */
|
|
|
+ public void saveSourceData(List<CoreSafetySourceData> sourceDataList, SafeIndexRuleCountVo indexConfigCountVo) {
|
|
|
+ if (sourceDataList.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //保存数据到数据源表
|
|
|
+ sourceDataService.saveBatch(sourceDataList);
|
|
|
+ CoreSafetySourceData sourceData = sourceDataList.get(0);
|
|
|
+ double total = 0;
|
|
|
+ for (CoreSafetySourceData s : sourceDataList) {
|
|
|
+ total += s.getScore();
|
|
|
+ }
|
|
|
+ CoreSafetyDeductData safeDeductData = new CoreSafetyDeductData();
|
|
|
+ safeDeductData.setDataMonth(sourceData.getDataMonth());
|
|
|
+ safeDeductData.setDataYear(sourceData.getDataYear());
|
|
|
+ safeDeductData.setId(IdWorker.getId());
|
|
|
+ safeDeductData.setRuleId(sourceData.getRuleId());
|
|
|
+ safeDeductData.setOrgId(sourceData.getOrgId());
|
|
|
+ safeDeductData.setScore(total);
|
|
|
+ if (total > indexConfigCountVo.getScore()) {
|
|
|
+ safeDeductData.setScoreReal((double) indexConfigCountVo.getScore());
|
|
|
+ } else {
|
|
|
+ safeDeductData.setScoreReal(total);
|
|
|
+ }
|
|
|
+ safetyDeductDataService.save(safeDeductData);
|
|
|
+ }
|
|
|
}
|