Forráskód Böngészése

feat:审批节点汇总

shc 4 hónapja
szülő
commit
9a438b21c1

+ 192 - 0
hnqz-upms/hnqz-upms-api/src/main/java/com/qunzhixinxi/hnqz/admin/api/model/excel/TaskCheckHistoryMissNodeExcelModel.java

@@ -0,0 +1,192 @@
+package com.qunzhixinxi.hnqz.admin.api.model.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import lombok.Data;
+
+/**
+ * 审核记录缺少节点记录
+ *
+ * @author jimmy
+ * @date 2025-02-27 11:49
+ */
+@Data
+@ColumnWidth(128)
+public class TaskCheckHistoryMissNodeExcelModel {
+
+  @ColumnWidth(32)
+  @ExcelProperty("任务ID")
+  private String taskId;
+
+  @ColumnWidth(32)
+  @ExcelProperty("审核结果")
+  private String approvalStatus;
+
+  @ColumnWidth(32)
+  @ExcelProperty("是否有问题")
+  private String ok;
+
+  @ColumnWidth(32)
+  @ExcelProperty("说明")
+  private String reason;
+
+  // 1 ---------
+  //
+  //  @ExcelProperty("节点1审核ID")
+  //  private String historyId1;
+  //
+  //  @ExcelProperty("节点1期望节点值 -> 节点1实际节点值")
+  //  private String nodeId1;
+  //
+  //  @ExcelProperty("节点1审核人姓名(手机号)")
+  //  private String checkerInfo1;
+  //
+  //  @ExcelProperty("节点1审核人角色(ID)")
+  //  private String CheckerRoleId1;
+  //
+  //  @ExcelProperty("节点1是否正确")
+  //  private String result1;
+
+  @ExcelProperty("节点1(【审核ID】:【节点期望节点值 -> 节点实际节点值】:【审核人姓名(手机号)】:【审核人角色(ID)】:【是否正确】)")
+  private String info1;
+
+  // 2 ---------
+
+  //  @ExcelProperty("节点2审核ID")
+  //  private String historyId2;
+  //
+  //  @ExcelProperty("节点2期望节点值 -> 节点2实际节点值")
+  //  private String nodeId2;
+  //
+  //  @ExcelProperty("节点2审核人姓名(手机号)")
+  //  private String checkerInfo2;
+  //
+  //  @ExcelProperty("节点2审核人角色(ID)")
+  //  private String CheckerRoleId2;
+  //
+  //  @ExcelProperty("节点2是否正确")
+  //  private String result2;
+
+  @ExcelProperty("节点2(【审核ID】:【节点期望节点值 -> 节点实际节点值】:【审核人姓名(手机号)】:【审核人角色(ID)】:【是否正确】)")
+  private String info2;
+
+  // 3 ---------
+
+  //  @ExcelProperty("节点3审核ID")
+  //  private String historyId3;
+  //
+  //  @ExcelProperty("节点3期望节点值 -> 节点3实际节点值")
+  //  private String nodeId3;
+  //
+  //  @ExcelProperty("节点3审核人姓名(手机号)")
+  //  private String checkerInfo3;
+  //
+  //  @ExcelProperty("节点3审核人角色(ID)")
+  //  private String CheckerRoleId3;
+  //
+  //  @ExcelProperty("节点3是否正确")
+  //  private String result3;
+
+  @ExcelProperty("节点3(【审核ID】:【节点期望节点值 -> 节点实际节点值】:【审核人姓名(手机号)】:【审核人角色(ID)】:【是否正确】)")
+  private String info3;
+
+  // 4 ---------
+
+  //  @ExcelProperty("节点4审核ID")
+  //  private String historyId4;
+  //
+  //  @ExcelProperty("节点4期望节点值 -> 节点4实际节点值")
+  //  private String nodeId4;
+  //
+  //  @ExcelProperty("节点4审核人姓名(手机号)")
+  //  private String checkerInfo4;
+  //
+  //  @ExcelProperty("节点4审核人角色(ID)")
+  //  private String CheckerRoleId4;
+  //
+  //  @ExcelProperty("节点4是否正确")
+  //  private String result4;
+
+  @ExcelProperty("节点4(【审核ID】:【节点期望节点值 -> 节点实际节点值】:【审核人姓名(手机号)】:【审核人角色(ID)】:【是否正确】)")
+  private String info4;
+
+  // 8 ---------
+
+  //  @ExcelProperty("节点8审核ID")
+  //  private String historyId8;
+  //
+  //  @ExcelProperty("节点8期望节点值 -> 节点8实际节点值")
+  //  private String nodeId8;
+  //
+  //  @ExcelProperty("节点8审核人姓名(手机号)")
+  //  private String checkerInfo8;
+  //
+  //  @ExcelProperty("节点8审核人角色(ID)")
+  //  private String CheckerRoleId8;
+  //
+  //  @ExcelProperty("节点8是否正确")
+  //  private String result8;
+
+  @ExcelProperty("节点8/9(【审核ID】:【节点期望节点值 -> 节点实际节点值】:【审核人姓名(手机号)】:【审核人角色(ID)】:【是否正确】)")
+  private String info8;
+
+  // 9 ---------
+
+  //  @ExcelProperty("节点9审核ID")
+  //  private String historyId9;
+  //
+  //  @ExcelProperty("节点9期望节点值 -> 节点9实际节点值")
+  //  private String nodeId9;
+  //
+  //  @ExcelProperty("节点9审核人姓名(手机号)")
+  //  private String checkerInfo9;
+  //
+  //  @ExcelProperty("节点9审核人角色(ID)")
+  //  private String CheckerRoleId9;
+  //
+  //  @ExcelProperty("节点9是否正确")
+  //  private String result9;
+
+  @ExcelProperty("节点8/9(【审核ID】:【节点期望节点值 -> 节点实际节点值】:【审核人姓名(手机号)】:【审核人角色(ID)】:【是否正确】)")
+  private String info9;
+
+  // 5 ---------
+  //
+  //  @ExcelProperty("节点5审核ID")
+  //  private String historyId5;
+  //
+  //  @ExcelProperty("节点5期望节点值 -> 节点5实际节点值")
+  //  private String nodeId5;
+  //
+  //  @ExcelProperty("节点5审核人姓名(手机号)")
+  //  private String checkerInfo5;
+  //
+  //  @ExcelProperty("节点5审核人角色(ID)")
+  //  private String CheckerRoleId5;
+  //
+  //  @ExcelProperty("节点5是否正确")
+  //  private String result5;
+
+  @ExcelProperty("节点5(【审核ID】:【节点期望节点值 -> 节点实际节点值】:【审核人姓名(手机号)】:【审核人角色(ID)】:【是否正确】)")
+  private String info5;
+
+  // 6 ---------
+
+  //  @ExcelProperty("节点6审核ID")
+  //  private String historyId6;
+  //
+  //  @ExcelProperty("节点6期望节点值 -> 节点6实际节点值")
+  //  private String nodeId6;
+  //
+  //  @ExcelProperty("节点6审核人姓名(手机号)")
+  //  private String checkerInfo6;
+  //
+  //  @ExcelProperty("节点6审核人角色(ID)")
+  //  private String CheckerRoleId6;
+  //
+  //  @ExcelProperty("节点6是否正确")
+  //  private String result6;
+
+  @ExcelProperty("节点6(【审核ID】:【节点期望节点值 -> 节点实际节点值】:【审核人姓名(手机号)】:【审核人角色(ID)】:【是否正确】)")
+  private String info6;
+}

+ 313 - 5
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/controller/init/InitController.java

@@ -7,6 +7,7 @@ import cn.hutool.core.date.DatePattern;
 import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.core.text.StrPool;
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.extra.spring.SpringUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.google.common.collect.Lists;
@@ -21,8 +22,10 @@ import com.qunzhixinxi.hnqz.admin.api.entity.SysDept;
 import com.qunzhixinxi.hnqz.admin.api.entity.SysDeptRelation;
 import com.qunzhixinxi.hnqz.admin.api.entity.SysFile;
 import com.qunzhixinxi.hnqz.admin.api.entity.SysLog;
+import com.qunzhixinxi.hnqz.admin.api.entity.SysRole;
 import com.qunzhixinxi.hnqz.admin.api.entity.SysUser;
 import com.qunzhixinxi.hnqz.admin.api.entity.SysUserArea;
+import com.qunzhixinxi.hnqz.admin.api.entity.SysUserRole;
 import com.qunzhixinxi.hnqz.admin.api.entity.WmDaAgent;
 import com.qunzhixinxi.hnqz.admin.api.entity.WmDaDrugEnt;
 import com.qunzhixinxi.hnqz.admin.api.entity.WmDaDrugEntDrugtable;
@@ -33,6 +36,7 @@ import com.qunzhixinxi.hnqz.admin.api.entity.WmTaskContent;
 import com.qunzhixinxi.hnqz.admin.api.entity.WmTaskType;
 import com.qunzhixinxi.hnqz.admin.api.model.excel.TaskCheckExcelModel;
 import com.qunzhixinxi.hnqz.admin.api.model.excel.TaskCheckHistoryExcelModel;
+import com.qunzhixinxi.hnqz.admin.api.model.excel.TaskCheckHistoryMissNodeExcelModel;
 import com.qunzhixinxi.hnqz.admin.api.model.excel.WmTaskDupModel;
 import com.qunzhixinxi.hnqz.admin.event.PackageContractEvent;
 import com.qunzhixinxi.hnqz.admin.mapper.InitMapper;
@@ -46,7 +50,9 @@ import com.qunzhixinxi.hnqz.admin.service.SysAreaEntityService;
 import com.qunzhixinxi.hnqz.admin.service.SysCheckChainNodeCheckHistoryService;
 import com.qunzhixinxi.hnqz.admin.service.SysFileService;
 import com.qunzhixinxi.hnqz.admin.service.SysLogService;
+import com.qunzhixinxi.hnqz.admin.service.SysRoleService;
 import com.qunzhixinxi.hnqz.admin.service.SysUserAreaService;
+import com.qunzhixinxi.hnqz.admin.service.SysUserRoleService;
 import com.qunzhixinxi.hnqz.admin.service.SysUserService;
 import com.qunzhixinxi.hnqz.admin.service.WmPackageTaskTypeQtyService;
 import com.qunzhixinxi.hnqz.admin.service.WmScorePackageService;
@@ -65,20 +71,22 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.Objects;
 import java.util.TreeMap;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
 import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import net.coobird.thumbnailator.Thumbnails;
-import org.apache.http.entity.ContentType;
 import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.data.redis.core.ListOperations;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.http.MediaType;
-import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -105,7 +113,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.function.Function;
 import java.util.stream.Collectors;
-import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 初始化控制器
@@ -122,6 +129,20 @@ public class InitController {
   private static final String LOCAL_TEMP_PATH =
       OsEnvUtils.getEachEnvPaths().get(TargetFile.TEMP.getName());
 
+  private static final Map<String, String> ROLE_2_NODE_MAP =
+      new LinkedHashMap<>() {
+        {
+          put("37", "1");
+          put("43", "2");
+          put("4", "3");
+          //    put("42","4");
+          put("41", "5");
+          put("39", "6");
+          put("42", "8");
+          put("40", "9");
+        }
+      };
+
   private final InitMapper initMapper;
   private final WmTaskContentService taskContentService;
   private final WmTaskService taskService;
@@ -143,6 +164,8 @@ public class InitController {
   private final OssProperties ossProperties;
   private final OssTemplate minioTemplate;
   private final SysCheckChainNodeCheckHistoryService checkChainNodeCheckHistoryService;
+  private final SysUserRoleService sysUserRoleService;
+  private final SysRoleService roleService;
 
   @Inner(value = false)
   @GetMapping(value = "/cnbg/task/check/stat")
@@ -1662,7 +1685,6 @@ public class InitController {
       InputStream inputStream1 = heic2jpg(inputStream, newFileName);
       minioTemplate.putObject(ossProperties.getBucketName(), newFileName, inputStream1);
 
-
       inputStream1.close();
       inputStream.close();
 
@@ -1689,4 +1711,290 @@ public class InitController {
     File tempFile = new File(tempFileName);
     return new FileInputStream(tempFile);
   }
+
+  private Map<String, Map<String, Object>> getCheckerInfo() {
+    // 从缓存中获取用户信息
+    List<SysUser> users = redisTemplate.opsForList().range(CacheConstants.USER_KEY, 0, -1);
+    List<Integer> uIds =
+        users.stream()
+            .mapToInt(SysUser::getUserId)
+            .boxed()
+            .distinct()
+            .sorted()
+            .collect(Collectors.toList());
+
+    List<SysUserRole> userRoles =
+        sysUserRoleService.list(
+            Wrappers.<SysUserRole>lambdaQuery().in(SysUserRole::getUserId, uIds));
+
+    Map<Integer, List<Integer>> collect =
+        userRoles.stream()
+            .collect(
+                Collectors.groupingBy(
+                    SysUserRole::getUserId,
+                    Collectors.mapping(SysUserRole::getRoleId, Collectors.toList())));
+
+    Map<Integer, SysRole> roleMap =
+        roleService.list().stream()
+            .collect(Collectors.toMap(SysRole::getRoleId, Function.identity()));
+
+    Map<String, Map<String, Object>> map = new HashMap<>(3);
+
+    users.forEach(
+        u -> {
+          Map<String, Object> temp = new HashMap<>(3);
+          Integer userId = u.getUserId();
+          temp.put("userId", userId.toString());
+          temp.put("realName", u.getRealname());
+
+          // 获取角色ID
+          List<Integer> roleIds = collect.get(userId);
+
+          List<Map<String, String>> roles;
+          if (CollUtil.isNotEmpty(roleIds)) {
+            roles =
+                roleIds.stream()
+                    .map(
+                        rId -> {
+                          Map<String, String> temp2 = new HashMap<>(3);
+                          temp2.put("roleId", rId.toString());
+                          //                          log.info(rId.toString());
+                          SysRole sysRole = roleMap.get(rId);
+                          temp2.put(
+                              "roleName", sysRole == null ? "" : roleMap.get(rId).getRoleName());
+                          String s = ROLE_2_NODE_MAP.get(rId.toString());
+                          temp2.put("nodeId", s);
+                          return temp2;
+                        })
+                    .collect(Collectors.toList());
+
+          } else {
+            roles = Collections.emptyList();
+          }
+
+          temp.put("role", roles);
+
+          map.put(u.getUsername(), temp);
+        });
+
+    return map;
+  }
+
+  @Inner(value = false)
+  @ResponseExcel(
+      name = "taskCheckHistoryMissNodeExcel",
+      sheets = {@Sheet(sheetName = "审核记录缺少节点记录")})
+  @GetMapping(value = "/cnbg/init/task/check/his/node/miss/export")
+  public List<TaskCheckHistoryMissNodeExcelModel> exportTaskCheckHistoryMissNodeExcel(
+      @RequestParam(value = "idx") Integer idx) {
+
+    // 获取审核人信息
+    Map<String, Map<String, Object>> checkerInfo = getCheckerInfo();
+
+    // 每次处理40000
+    int start = idx * 100000;
+
+    // 获取全部的审核信息
+    List<SysCheckChainNodeCheckHistory> his =
+        checkChainNodeCheckHistoryService.list(
+            Wrappers.<SysCheckChainNodeCheckHistory>lambdaQuery()
+                .between(SysCheckChainNodeCheckHistory::getTargetId, start, start + 100000)
+                .orderByAsc(SysCheckChainNodeCheckHistory::getHistoryId));
+
+    if (CollUtil.isEmpty(his)) {
+      return Collections.emptyList();
+    }
+
+    Map<Integer, List<SysCheckChainNodeCheckHistory>> collect1 =
+        his.stream()
+            .collect(
+                Collectors.groupingBy(
+                    SysCheckChainNodeCheckHistory::getTargetId, Collectors.toList()));
+
+    List<TaskCheckHistoryMissNodeExcelModel> models = new ArrayList<>(collect1.size());
+
+    collect1.forEach(
+        (k, v) -> {
+          TaskCheckHistoryMissNodeExcelModel model = new TaskCheckHistoryMissNodeExcelModel();
+          model.setTaskId(k.toString());
+
+          boolean approval = true;
+          StringBuilder ok = new StringBuilder();
+          for (int i = 1; i <= 9; i++) {
+
+            int j = i - 1;
+            // 123456789
+            // 0123456
+            // 1238956
+            // 不存在节点七1238956
+
+            if (v.size() < i) {
+              continue;
+            }
+
+            // 可能是8或者9
+            if (i == 5) {}
+
+            SysCheckChainNodeCheckHistory history = v.get(j);
+
+            approval &= history.getCheckResult();
+
+            log.info(history.toString());
+
+            int currentNodeId = history.getNodeId();
+
+            // 可能是节点4
+            if (i == 4 && currentNodeId == 4) {
+              j = -1;
+            }
+
+            String hisIdStr = history.getHistoryId().toString();
+
+            String createBy = history.getCreateBy();
+            Map<String, Object> checker = checkerInfo.get(createBy);
+            String chk =
+                CollUtil.isEmpty(checker)
+                    ? ""
+                    : String.format("%s(%s)", checker.get("realName").toString(), createBy);
+            Map<String, String> roleMap =
+                CollUtil.isEmpty(checker)
+                    ? Collections.EMPTY_MAP
+                    : (Map<String, String>) (((List<?>) checker.get("role")).get(0));
+            String checkRoleId =
+                CollUtil.isEmpty(roleMap)
+                    ? ""
+                    : String.format("%s(%s)", roleMap.get("roleName"), roleMap.get("roleId"));
+            ;
+            String nodeId =
+                CollUtil.isEmpty(roleMap)
+                    ? ""
+                    : String.format("%s -> %s", roleMap.get("nodeId"), currentNodeId);
+            boolean result =
+                roleMap.get("nodeId") == null
+                    ? false
+                    : String.valueOf(currentNodeId).equals(roleMap.get("nodeId").toString());
+
+            String info =
+                String.format(
+                    "【%s】:【%s】:【%s】:【%s】:【%s】",
+                    hisIdStr, nodeId, chk, checkRoleId, result ? "" : "warn");
+
+            // 服务商
+            if (j == 0) {
+
+              //              model.setHistoryId1(hisIdStr);
+              //              model.setNodeId1(nodeId);
+              //              model.setCheckerInfo1(chk);
+              //              model.setCheckerRoleId1(checkRoleId);
+              //              model.setResult1(result ? "" : "warn");
+              if (!result) {
+                ok.append("1;");
+              }
+              model.setInfo1(info);
+
+            }
+            // 地市
+            else if (j == 1) {
+
+              //              model.setHistoryId2(hisIdStr);
+              //              model.setNodeId2(nodeId);
+              //              model.setCheckerInfo2(chk);
+              //              model.setCheckerRoleId2(checkRoleId);
+              //              model.setResult2(result ? "" : "warn");
+              if (!result) {
+                ok.append("2;");
+              }
+              model.setInfo2(info);
+
+            }
+            // 区域
+            else if (j == 2) {
+              //              model.setHistoryId3(hisIdStr);
+              //              model.setNodeId3(nodeId);
+              //              model.setCheckerInfo3(chk);
+              //              model.setCheckerRoleId3(checkRoleId);
+              //              model.setResult3(result ? "" : "warn");
+              if (!result) {
+                ok.append("3;");
+              }
+              model.setInfo3(info);
+
+            }
+            // 市场/商务
+            else if (j == 3) {
+
+              //              model.setHistoryId8(hisIdStr);
+              //              model.setNodeId8(nodeId);
+              //              model.setCheckerInfo8(chk);
+              //              model.setCheckerRoleId8(checkRoleId);
+              //              model.setResult8(result ? "" : "warn");
+
+              if (!result) {
+                ok.append("8;");
+              }
+              model.setInfo8(info);
+            }
+            // 市场/商务
+            else if (j == 4) {
+
+              //              model.setHistoryId9(hisIdStr);
+              //              model.setNodeId9(nodeId);
+              //              model.setCheckerInfo9(chk);
+              //              model.setCheckerRoleId9(checkRoleId);
+              //              model.setResult9(result ? "" : "warn");
+
+              boolean mkt = checkRoleId.contains("市场");
+
+              if (!result) {
+                ok.append("9;");
+              }
+
+              model.setInfo9(info);
+            }
+            // 分管领导
+            else if (j == 5) {
+              //              model.setHistoryId5(hisIdStr);
+              //              model.setNodeId5(nodeId);
+              //              model.setCheckerInfo5(chk);
+              //              model.setCheckerRoleId5(checkRoleId);
+              //              model.setResult5(result ? "" : "warn");
+              if (!result) {
+                ok.append("5;");
+              }
+              model.setInfo5(info);
+            }
+            // 总经理
+            else if (j == 6) {
+              //              model.setHistoryId6(hisIdStr);
+              //              model.setNodeId6(nodeId);
+              //              model.setCheckerInfo6(chk);
+              //              model.setCheckerRoleId6(checkRoleId);
+              //              model.setResult6(result ? "" : "warn");
+              if (!result) {
+                ok.append("6;");
+              }
+              model.setInfo6(info);
+            }
+            // 节点4
+            else {
+              //              model.setHistoryId4(hisIdStr);
+              //              model.setNodeId4(nodeId);
+              //              model.setCheckerInfo4(chk);
+              //              model.setCheckerRoleId4(checkRoleId);
+              //              model.setResult4(result ? "" : "warn");
+              if (!result) {
+                ok.append("4;");
+              }
+              model.setInfo4(info);
+            }
+
+            model.setOk(ok.toString());
+            model.setApprovalStatus(approval ? "通过" : "拒绝");
+            models.add(model);
+          }
+        });
+    return models.stream()
+        .sorted(Comparator.comparing(TaskCheckHistoryMissNodeExcelModel::getTaskId))
+        .collect(Collectors.toList());
+  }
 }