Explorar el Código

预警页面-红线指标预警

chenshudong hace 2 días
padre
commit
95d6483070

+ 12 - 0
airport-admin/src/main/java/com/sundot/airport/web/controller/ledger/LedgerWarningController.java

@@ -3,6 +3,7 @@ package com.sundot.airport.web.controller.ledger;
3 3
 import com.sundot.airport.common.core.controller.BaseController;
4 4
 import com.sundot.airport.common.core.domain.AjaxResult;
5 5
 import com.sundot.airport.common.dto.LedgerCommonQueryReqVO;
6
+import com.sundot.airport.ledger.domain.vo.LedgerWarningDetailItemReduceVO;
6 7
 import com.sundot.airport.ledger.domain.vo.LedgerWarningDetailVO;
7 8
 import com.sundot.airport.ledger.domain.vo.LedgerWarningVO;
8 9
 import com.sundot.airport.ledger.service.ILedgerWarningService;
@@ -12,6 +13,8 @@ import org.springframework.web.bind.annotation.RequestBody;
12 13
 import org.springframework.web.bind.annotation.RequestMapping;
13 14
 import org.springframework.web.bind.annotation.RestController;
14 15
 
16
+import java.util.List;
17
+
15 18
 /**
16 19
  * 预警页面控制器
17 20
  */
@@ -40,4 +43,13 @@ public class LedgerWarningController extends BaseController {
40 43
         return AjaxResult.success(result);
41 44
     }
42 45
 
46
+    /**
47
+     * 红线指标预警
48
+     */
49
+    @PostMapping("/ledgerReduceDetail")
50
+    public AjaxResult ledgerReduceDetail(@RequestBody LedgerCommonQueryReqVO queryReq) {
51
+        List<LedgerWarningDetailItemReduceVO> result = ledgerWarningService.ledgerReduceDetail(queryReq);
52
+        return AjaxResult.success(result);
53
+    }
54
+
43 55
 }

+ 43 - 0
airport-common/src/main/java/com/sundot/airport/common/utils/DateMonthUtils.java

@@ -0,0 +1,43 @@
1
+package com.sundot.airport.common.utils;
2
+
3
+import java.time.LocalDate;
4
+import java.time.ZoneId;
5
+import java.util.Date;
6
+
7
+public class DateMonthUtils {
8
+
9
+    /**
10
+     * 根据开始日期和结束日期计算相隔月数
11
+     * 规则:每 30 天 = 1 个月,超出部分四舍五入
12
+     *
13
+     * @param startDate 开始日期
14
+     * @param endDate   结束日期
15
+     * @return 相隔月数(Integer)
16
+     */
17
+    public static Integer calculateMonths(Date startDate, Date endDate) {
18
+        if (startDate == null || endDate == null) {
19
+            return null;
20
+        }
21
+
22
+        // Date → LocalDate
23
+        LocalDate start = startDate.toInstant()
24
+                .atZone(ZoneId.systemDefault())
25
+                .toLocalDate();
26
+        LocalDate end = endDate.toInstant()
27
+                .atZone(ZoneId.systemDefault())
28
+                .toLocalDate();
29
+
30
+        // 防止开始时间晚于结束时间
31
+        if (start.isAfter(end)) {
32
+            LocalDate temp = start;
33
+            start = end;
34
+            end = temp;
35
+        }
36
+
37
+        // 计算天数差
38
+        long days = java.time.temporal.ChronoUnit.DAYS.between(start, end);
39
+
40
+        // 每 30 天为 1 个月,四舍五入
41
+        return (int) Math.round((double) days / 30.0);
42
+    }
43
+}

+ 77 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/domain/vo/LedgerWarningDetailItemReduceVO.java

@@ -0,0 +1,77 @@
1
+package com.sundot.airport.ledger.domain.vo;
2
+
3
+import lombok.Data;
4
+
5
+import java.io.Serializable;
6
+import java.math.BigDecimal;
7
+
8
+/**
9
+ * 预警信息详情配分事项录入明细
10
+ */
11
+@Data
12
+public class LedgerWarningDetailItemReduceVO implements Serializable {
13
+    /**
14
+     * 员工ID
15
+     */
16
+    private Long userId;
17
+    /**
18
+     * 员工账号
19
+     */
20
+    private String userName;
21
+    /**
22
+     * 员工昵称
23
+     */
24
+    private String nickName;
25
+    /**
26
+     * 所属部门ID
27
+     */
28
+    private Long deptId;
29
+    /**
30
+     * 所属部门名称
31
+     */
32
+    private String deptName;
33
+    /**
34
+     * 维度ID
35
+     */
36
+    private Long dimensionId;
37
+    /**
38
+     * 维度名称
39
+     */
40
+    private String dimensionName;
41
+    /**
42
+     * 二级指标ID
43
+     */
44
+    private Long level2Id;
45
+    /**
46
+     * 二级指标名称
47
+     */
48
+    private String level2Name;
49
+    /**
50
+     * 分值合计
51
+     */
52
+    private BigDecimal totalScore;
53
+    /**
54
+     * 发生次数
55
+     */
56
+    private Integer occurrenceCount;
57
+    /**
58
+     * 月份数
59
+     */
60
+    private Integer monthCount;
61
+    /**
62
+     * 平均次数
63
+     */
64
+    private BigDecimal averageCount;
65
+    /**
66
+     * 预警等级
67
+     */
68
+    private String warningLevel;
69
+    /**
70
+     * 状态标签
71
+     */
72
+    private String statusLabel;
73
+    /**
74
+     * 核心风险
75
+     */
76
+    private String coreRisks;
77
+}

+ 5 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/domain/vo/LedgerWarningDetailItemVO.java

@@ -4,6 +4,7 @@ import lombok.Data;
4 4
 
5 5
 import java.io.Serializable;
6 6
 import java.math.BigDecimal;
7
+import java.util.List;
7 8
 
8 9
 /**
9 10
  * 预警信息详情明细
@@ -46,4 +47,8 @@ public class LedgerWarningDetailItemVO implements Serializable {
46 47
      * 核心风险/优秀事迹
47 48
      */
48 49
     private String coreRisksOrOutstandingAchievements;
50
+    /**
51
+     * 预警信息详情配分事项录入明细列表
52
+     */
53
+    private List<LedgerWarningDetailItemReduceVO> ledgerWarningDetailItemDetailList;
49 54
 }

+ 8 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/service/ILedgerWarningService.java

@@ -1,9 +1,12 @@
1 1
 package com.sundot.airport.ledger.service;
2 2
 
3 3
 import com.sundot.airport.common.dto.LedgerCommonQueryReqVO;
4
+import com.sundot.airport.ledger.domain.vo.LedgerWarningDetailItemReduceVO;
4 5
 import com.sundot.airport.ledger.domain.vo.LedgerWarningDetailVO;
5 6
 import com.sundot.airport.ledger.domain.vo.LedgerWarningVO;
6 7
 
8
+import java.util.List;
9
+
7 10
 /**
8 11
  * 预警页面服务
9 12
  */
@@ -19,4 +22,9 @@ public interface ILedgerWarningService {
19 22
      */
20 23
     LedgerWarningDetailVO ledgerDetail(LedgerCommonQueryReqVO queryReq);
21 24
 
25
+    /**
26
+     * 红线指标预警
27
+     */
28
+    List<LedgerWarningDetailItemReduceVO> ledgerReduceDetail(LedgerCommonQueryReqVO queryReq);
29
+
22 30
 }

+ 112 - 0
airport-ledger/src/main/java/com/sundot/airport/ledger/service/impl/LedgerWarningServiceImpl.java

@@ -11,11 +11,13 @@ import com.sundot.airport.common.enums.DeptTypeEnum;
11 11
 import com.sundot.airport.common.enums.LedgerAlertLevelEnum;
12 12
 import com.sundot.airport.common.enums.LedgerStatusLabelEnum;
13 13
 import com.sundot.airport.common.enums.ScoreLevelEnum;
14
+import com.sundot.airport.common.utils.DateMonthUtils;
14 15
 import com.sundot.airport.common.utils.DeptUtils;
15 16
 import com.sundot.airport.common.utils.SecurityUtils;
16 17
 import com.sundot.airport.common.utils.StreamSortUtils;
17 18
 import com.sundot.airport.ledger.domain.ScoreEvent;
18 19
 import com.sundot.airport.ledger.domain.ScoreIndicator;
20
+import com.sundot.airport.ledger.domain.vo.LedgerWarningDetailItemReduceVO;
19 21
 import com.sundot.airport.ledger.domain.vo.LedgerWarningDetailItemVO;
20 22
 import com.sundot.airport.ledger.domain.vo.LedgerWarningDetailVO;
21 23
 import com.sundot.airport.ledger.domain.vo.LedgerWarningVO;
@@ -266,4 +268,114 @@ public class LedgerWarningServiceImpl implements ILedgerWarningService {
266 268
         return null;
267 269
     }
268 270
 
271
+    /**
272
+     * 红线指标预警
273
+     */
274
+    @Override
275
+    public List<LedgerWarningDetailItemReduceVO> ledgerReduceDetail(LedgerCommonQueryReqVO queryReq) {
276
+        List<String> scoreIndicatorNameList = Arrays.asList("员工规范化操作", "后台实时质控拦截", "不安全事件", "安保测试未通过");
277
+        Map<String, String> unitMap = new HashMap<>();
278
+        unitMap.put("员工规范化操作", "项");
279
+        unitMap.put("后台实时质控拦截", "次");
280
+        unitMap.put("不安全事件", "起");
281
+        unitMap.put("安保测试未通过", "项");
282
+
283
+        Long topSiteId = DeptUtils.getTopSiteId(sysDeptService.selectDeptById(SecurityUtils.getDeptId()));
284
+        // 获取所有部门信息
285
+        Map<Long, SysDept> deptMap = getDeptMap();
286
+        // 构建大队到其所有子部门ID的映射
287
+        Map<Long, Set<Long>> brigadeSubDeptsMap = buildBrigadeSubDeptsMap(getDeptMap());
288
+
289
+        ScoreIndicator scoreIndicatorQuery = new ScoreIndicator();
290
+        scoreIndicatorQuery.setStatus("0");
291
+        scoreIndicatorQuery.setOrg(ScoreLevelEnum.PERSON.getCode());
292
+        scoreIndicatorQuery.setLevel(2);
293
+        List<ScoreIndicator> scoreIndicatorList = scoreIndicatorService.selectList(scoreIndicatorQuery);
294
+        scoreIndicatorList = scoreIndicatorList.stream().filter(scoreIndicator -> scoreIndicatorNameList.contains(scoreIndicator.getName())).collect(Collectors.toList());
295
+        List<Long> scoreIndicatorIdList = scoreIndicatorList.stream().map(ScoreIndicator::getId).collect(Collectors.toList());
296
+        List<Long> userIdList = new ArrayList<>();
297
+        List<String> userNameList = new ArrayList<>();
298
+        Map<Long, SysUser> sysUserMap = new HashMap<>();
299
+        if (ObjUtil.isNotNull(queryReq.getUserId())) {
300
+            userIdList.add(queryReq.getUserId());
301
+            SysUser sysUser = sysUserService.selectUserById(queryReq.getUserId());
302
+            userNameList.add(sysUser.getNickName());
303
+            sysUserMap.put(queryReq.getUserId(), sysUser);
304
+        } else {
305
+            Long targetDeptId = ObjUtil.isNotNull(queryReq.getGroupId()) ? queryReq.getGroupId()
306
+                    : ObjUtil.isNotNull(queryReq.getTeamId()) ? queryReq.getTeamId()
307
+                    : ObjUtil.isNotNull(queryReq.getDeptId()) ? queryReq.getDeptId()
308
+                    : topSiteId;
309
+            List<SysUser> sysUserList = sysUserService.selectUserByDeptId(targetDeptId);
310
+            userIdList.addAll(sysUserList.stream().map(SysUser::getUserId).collect(Collectors.toList()));
311
+            userNameList.addAll(sysUserList.stream().map(SysUser::getNickName).collect(Collectors.toList()));
312
+            sysUserMap.putAll(sysUserList.stream().collect(Collectors.toMap(SysUser::getUserId, user -> user)));
313
+        }
314
+        List<ScoreEvent> scoreEventList = ledgerWarningMapper.selectScoreEventList(queryReq.getStartDate(), queryReq.getEndDate(), scoreIndicatorIdList, userIdList);
315
+//        // 由于person_name存在多用户时person_id为空,因此不能根据person_id进行分组处理数据
316
+//        Map<Long, List<ScoreEvent>> scoreEventMap = scoreEventList.stream().collect(Collectors.groupingBy(ScoreEvent::getPersonId));
317
+        List<LedgerWarningDetailItemReduceVO> resultList = new ArrayList<>();
318
+        userIdList.forEach(userId -> {
319
+            SysUser sysUser = sysUserMap.get(userId);
320
+//            // 由于person_name存在多用户时person_id为空,因此不能根据person_id进行分组处理数据
321
+//            List<ScoreEvent> userScoreEventList = scoreEventMap.get(userId);
322
+            List<ScoreEvent> userScoreEventList = scoreEventList.stream()
323
+                    .filter(scoreEvent -> {
324
+                        if (ObjUtil.isNull(scoreEvent.getDimensionId()) || StrUtil.isEmpty(scoreEvent.getPersonName())) {
325
+                            return false;
326
+                        }
327
+                        boolean matched = false;
328
+                        for (String n : scoreEvent.getPersonName().split("[,,]")) {
329
+                            if (sysUser.getNickName().equals(n.trim())) {
330
+                                matched = true;
331
+                                break;
332
+                            }
333
+                        }
334
+                        return matched;
335
+                    })
336
+                    .collect(Collectors.toList());
337
+            if (CollUtil.isNotEmpty(userScoreEventList)) {
338
+                Map<String, List<ScoreEvent>> userScoreEventListMap = userScoreEventList.stream().collect(Collectors.groupingBy(item -> item.getLevel2Id() + "_" + item.getLevel2Name()));
339
+                userScoreEventListMap.forEach((level2IdName, eventList) -> {
340
+                    LedgerWarningDetailItemReduceVO ledgerWarningDetailItemReduce = new LedgerWarningDetailItemReduceVO();
341
+                    ledgerWarningDetailItemReduce.setUserId(sysUser.getUserId());
342
+                    ledgerWarningDetailItemReduce.setUserName(sysUser.getUserName());
343
+                    ledgerWarningDetailItemReduce.setNickName(sysUser.getNickName());
344
+                    ledgerWarningDetailItemReduce.setDeptId(sysUser.getDeptId());
345
+                    SysDept dept = deptMap.get(findUserBrigade(sysUser.getDeptId(), brigadeSubDeptsMap));
346
+                    if (ObjUtil.isNotNull(dept)) {
347
+                        ledgerWarningDetailItemReduce.setDeptName(dept.getDeptName());
348
+                    }
349
+                    ledgerWarningDetailItemReduce.setDimensionId(eventList.get(0).getDimensionId());
350
+                    ledgerWarningDetailItemReduce.setDimensionName(eventList.get(0).getDimensionName());
351
+                    ledgerWarningDetailItemReduce.setLevel2Id(Long.valueOf(level2IdName.split("_")[0]));
352
+                    ledgerWarningDetailItemReduce.setLevel2Name(level2IdName.split("_")[1]);
353
+                    ledgerWarningDetailItemReduce.setTotalScore(eventList.stream().map(ScoreEvent::getTotalScore).reduce(BigDecimal.ZERO, BigDecimal::add));
354
+                    ledgerWarningDetailItemReduce.setOccurrenceCount(eventList.size());
355
+                    ledgerWarningDetailItemReduce.setMonthCount(DateMonthUtils.calculateMonths(queryReq.getStartDate(), queryReq.getEndDate()));
356
+                    ledgerWarningDetailItemReduce.setAverageCount(ObjUtil.isNull(ledgerWarningDetailItemReduce.getMonthCount()) ? BigDecimal.ZERO : BigDecimal.valueOf(ledgerWarningDetailItemReduce.getOccurrenceCount()).divide(BigDecimal.valueOf(ledgerWarningDetailItemReduce.getMonthCount()), 1, RoundingMode.HALF_UP));
357
+                    if (ledgerWarningDetailItemReduce.getAverageCount().compareTo(BigDecimal.valueOf(3)) >= 0) {
358
+                        ledgerWarningDetailItemReduce.setWarningLevel(LedgerAlertLevelEnum.RED_ALERT.getCode());
359
+                        ledgerWarningDetailItemReduce.setStatusLabel(LedgerStatusLabelEnum.EMERGENCY_INTERVENTION.getCode());
360
+                    } else {
361
+                        ledgerWarningDetailItemReduce.setWarningLevel(LedgerAlertLevelEnum.NORMAL_RANGE.getCode());
362
+                        ledgerWarningDetailItemReduce.setStatusLabel(LedgerStatusLabelEnum.REGULAR_COACHING.getCode());
363
+                    }
364
+                    ledgerWarningDetailItemReduce.setCoreRisks(ledgerWarningDetailItemReduce.getLevel2Name() + ledgerWarningDetailItemReduce.getOccurrenceCount() + unitMap.get(ledgerWarningDetailItemReduce.getLevel2Name()));
365
+                    resultList.add(ledgerWarningDetailItemReduce);
366
+                });
367
+            }
368
+        });
369
+
370
+        // 排序
371
+        if (ObjUtil.isNull(queryReq.getSorts())) {
372
+            Map<String, String> sorts = new LinkedHashMap<>();
373
+            sorts.put("userId", "asc");
374
+            sorts.put("dimensionId", "asc");
375
+            queryReq.setSorts(sorts);
376
+        }
377
+        List<LedgerWarningDetailItemReduceVO> result = StreamSortUtils.sort(resultList, queryReq.getSorts());
378
+        return result;
379
+    }
380
+
269 381
 }

+ 2 - 1
airport-ledger/src/main/resources/mapper/ledger/LedgerWarningMapper.xml

@@ -174,7 +174,8 @@
174 174
         dimension_name dimensionName,
175 175
         level2_id level2Id,
176 176
         level2_name level2Name,
177
-        event_time eventTime
177
+        event_time eventTime,
178
+        total_score totalScore
178 179
         from score_event
179 180
         where 1 = 1
180 181
         and org = '4'