Просмотр исходного кода

first version of batch processing to reduce memory footprint

dengjia 4 месяцев назад
Родитель
Сommit
1e703a1acd

+ 4 - 4
hnqz-upms/hnqz-upms-api/src/main/java/com/qunzhixinxi/hnqz/admin/api/model/excel/WmScorePackageCheckStatusExcelModel.java

@@ -10,7 +10,7 @@ import java.io.Serializable;
  * 积分包审核状态信息模型
  */
 @Data
-@ColumnWidth(20)
+@ColumnWidth(10)
 public class WmScorePackageCheckStatusExcelModel implements Serializable {
     private static final long serialVersionUID = -2712453720764666659L;
 
@@ -23,7 +23,7 @@ public class WmScorePackageCheckStatusExcelModel implements Serializable {
     @ExcelProperty("省份")
     private String province;
 
-    @ColumnWidth(128)
+    @ColumnWidth(50)
     @ExcelProperty("市场服务供应商名称")
     private String csoName;
 
@@ -33,11 +33,11 @@ public class WmScorePackageCheckStatusExcelModel implements Serializable {
     @ExcelProperty("执行包季度")
     private String quarter;
 
-    @ColumnWidth(128)
+    @ColumnWidth(50)
     @ExcelProperty("服务包产品名称")
     private String product;
 
-    @ColumnWidth(128)
+    @ColumnWidth(80)
     @ExcelProperty("省区下发执行包名称")
     private String pkgName;
 

+ 3 - 1
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/controller/pkg/WmScorePackageControllerV2.java

@@ -149,6 +149,8 @@ public class WmScorePackageControllerV2 {
     @RequestParam(value = "quarter", required = true) Integer quarter
     ) {
 
-    return packageManager.exportCheckInfo(year, quarter);
+    LocalDate startDate = LocalDate.of(year, (quarter - 1) * 3 + 1, 1);
+    LocalDate endDate = LocalDate.of(quarter == 4 ? year + 1: year, quarter == 4 ? 1 : quarter * 3 + 1, 1);
+    return packageManager.exportCheckInfo(startDate, endDate);
   }
 }

+ 78 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/manager/WmPackageExportScope.java

@@ -0,0 +1,78 @@
+package com.qunzhixinxi.hnqz.admin.manager;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.qunzhixinxi.hnqz.admin.api.entity.SysDept;
+import com.qunzhixinxi.hnqz.admin.api.entity.WmDaDrugEntDrugtable;
+import com.qunzhixinxi.hnqz.admin.api.entity.WmPackageTaskTypeQty;
+import com.qunzhixinxi.hnqz.admin.api.entity.WmScorePackage;
+
+final class WmPackageExportScope {
+
+    public WmPackageExportScope(Map<Integer, SysDept> dis,
+        Map<Integer, SysDept> service,
+        List<WmScorePackage> pkgs,
+        Map<String, WmDaDrugEntDrugtable> drugtableMap,
+        Set<Integer> operatorRoleIds,
+        List<WmScorePackage> childrenPkgs,
+        List<String> cPkgIds,
+        Map<String, List<String>> parentId2PkgMap,
+        Map<Integer, List<WmPackageTaskTypeQty>> pttMap
+        ) {
+        this.dis = dis;
+        this.service = service;
+        this.pkgs = pkgs;
+        this.drugtableMap = drugtableMap;
+        this.operatorRoleIds = operatorRoleIds;
+        this.childrenPkgs = childrenPkgs;
+        this.cPkgIds = cPkgIds;
+        this.parentId2PkgMap = parentId2PkgMap;
+        this.pttMap = pttMap;
+    }
+
+    /*
+     * level 3 dept
+     */
+    Map<Integer, SysDept> dis;
+
+    /*
+     * level 4 dept
+     */
+    Map<Integer, SysDept> service;
+
+    /*
+     * 区域包
+     */
+    List<WmScorePackage> pkgs;
+
+    /*
+     * 产品
+     */
+    Map<String, WmDaDrugEntDrugtable> drugtableMap;
+
+    /*
+     * 角色集合
+     */
+    Set<Integer> operatorRoleIds;
+
+    /*
+     * 子包
+     */
+    List<WmScorePackage> childrenPkgs;
+
+    /*
+     * 子包IDs
+     */
+    List<String> cPkgIds;
+    /*
+     * 父子包ID mapping
+     */
+    Map<String, List<String>> parentId2PkgMap;
+
+    /*
+     * 下发任务数map
+     */
+    Map<Integer, List<WmPackageTaskTypeQty>> pttMap;
+}

+ 310 - 133
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/manager/WmPackageManager.java

@@ -30,6 +30,7 @@ import com.qunzhixinxi.hnqz.admin.api.entity.WmTask;
 import com.qunzhixinxi.hnqz.admin.api.entity.WmTaskType;
 import com.qunzhixinxi.hnqz.admin.api.model.excel.WmScorePackageCheckStatusExcelModel;
 import com.qunzhixinxi.hnqz.admin.api.model.excel.WmScorePackageInfoExcelModel;
+import com.qunzhixinxi.hnqz.admin.mapper.SysCheckChainNodeCheckHistoryMapper;
 import com.qunzhixinxi.hnqz.admin.mapper.SysDeptRelationMapper;
 import com.qunzhixinxi.hnqz.admin.mapper.WmDaDrugEntDrugtableMapper;
 import com.qunzhixinxi.hnqz.admin.mapper.WmScorePackageMapper;
@@ -111,6 +112,7 @@ public class WmPackageManager {
   private final WmDaDrugEntDrugtableMapper wmDaDrugEntDrugtableMapper;
   private final WmPackageTaskTypeQtyService packageTaskTypeQtyService;
   private final SysDeptRelationMapper sysDeptRelationMapper;
+  private final SysCheckChainNodeCheckHistoryMapper sysCheckChainNodeCheckHistoryMapper;
 
   /**
    * 创建执行包兑付通知
@@ -547,86 +549,14 @@ public class WmPackageManager {
   // 获取需要导出的积分包信息
   public List<WmScorePackageInfoExcelModel> exportPkgInfo(LocalDate startDate, LocalDate endDate) {
 
-    Set<Integer> ignoreIds = new HashSet<>();
-    ignoreIds.add(1716964676);
-    ignoreIds.add(-1020826);
-    ignoreIds.add(-1019986);
-
-    Set<Integer> operatorRoleIds = new HashSet<>(SecurityUtils.getRoles());
-
-    // 获取所有的企业
-    List<SysDept> depts =
-        deptService
-            .list(
-                Wrappers.<SysDept>lambdaQuery()
-                    .eq(SysDept::getDelFlag, CommonConstants.STATUS_NORMAL))
-            .stream()
-            .filter(d -> !ignoreIds.contains(d.getDeptId()))
-            .collect(Collectors.toList());
-
-    if (CollUtil.isEmpty(depts)) {
-      throw new BizException("不存在生效的企业信息,无法获取导出数据");
-    }
-
-    // 分别过滤区域和服务商
-    List<Integer> parentDeptIds = operatorRoleIds.contains(37) ? //服务商的区域ID
-        sysDeptRelationMapper.selectList(
-            Wrappers.<SysDeptRelation>lambdaQuery()
-                .ne(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId())
-                .eq(SysDeptRelation::getDescendant, SecurityUtils.getUser().getDeptId()))
-            .stream().map(SysDeptRelation::getAncestor).collect(Collectors.toList())
-        : new ArrayList<>();
-    if (operatorRoleIds.contains(37) && CollUtil.isEmpty(parentDeptIds)) {
-      throw new RuntimeException("没有找到对应的区域");
-    }
-    List<Integer> childDeptIds = operatorRoleIds.contains(4) ? //区域的服务商ID
-        sysDeptRelationMapper.selectList(
-            Wrappers.<SysDeptRelation>lambdaQuery()
-                .eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId())
-                .ne(SysDeptRelation::getDescendant, SecurityUtils.getUser().getDeptId()))
-            .stream().map(SysDeptRelation::getDescendant).collect(Collectors.toList())
-        : new ArrayList<>();
-    if (operatorRoleIds.contains(4) && CollUtil.isEmpty(childDeptIds)) {
-      throw new RuntimeException("没有找到对应的服务商");
-    }
-
-    Map<Integer, SysDept> dis =
-        depts.stream()
-            .filter(d -> d.getLevel() == 3)
-            .filter(d -> !operatorRoleIds.contains(4) || operatorRoleIds.contains(4) && d.getDeptId().equals(SecurityUtils.getUser().getDeptId())) //区域管理员
-            .filter(d -> !operatorRoleIds.contains(37) || operatorRoleIds.contains(37) && parentDeptIds.contains(d.getDeptId())) //服务商管理员
-            .collect(Collectors.toMap(SysDept::getDeptId, Function.identity()));
-    Map<Integer, SysDept> service =
-        depts.stream()
-            .filter(d -> d.getLevel() == 4)
-            .filter(d -> !operatorRoleIds.contains(4) || operatorRoleIds.contains(4) && childDeptIds.contains(d.getDeptId())) //区域管理员
-            .filter(d -> !operatorRoleIds.contains(37) || operatorRoleIds.contains(37) && d.getDeptId().equals(SecurityUtils.getUser().getDeptId())) //服务商管理员
-            .collect(Collectors.toMap(SysDept::getDeptId, Function.identity()));
-
-    if (CollUtil.isEmpty(dis) || CollUtil.isEmpty(service)) {
-      throw new BizException("不存在生效的区域或服务商,无法获取导出数据");
-    }
-
-    // 获取区域发的包
-    List<WmScorePackage> pkgs =
-        scorePackageService.list(
-            Wrappers.<WmScorePackage>lambdaQuery()
-                .eq(WmScorePackage::getEnableFlag, EnableEnum.ENABLE.val())
-                .between(WmScorePackage::getCreateTime, startDate, endDate)
-                .in(
-                    WmScorePackage::getSendPackageDeptId,
-                    dis.keySet().stream()
-                        .map(String::valueOf)
-                        .sorted()
-                        .collect(Collectors.toList())));
-
-    if (CollUtil.isEmpty(pkgs)) {
-      throw new BizException(
-          String.format(
-              "%s至%s没有区域发包记录,不支持导出",
-              DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN).format(startDate),
-              DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN).format(endDate)));
-    }
+    WmPackageExportScope scope = getWmPackageExportScope(startDate, endDate);
+    Map<Integer, SysDept> service = scope.service;
+    List<WmScorePackage> pkgs = scope.pkgs;
+    Map<String, WmDaDrugEntDrugtable> drugtableMap = scope.drugtableMap;
+    Set<Integer> operatorRoleIds = scope.operatorRoleIds;
+    List<String> cPkgIds = scope.cPkgIds;
+    Map<String, List<String>> parentId2PkgMap = scope.parentId2PkgMap;
+    Map<Integer, List<WmPackageTaskTypeQty>>pttMap = scope.pttMap;
 
     // 获取区域的上级包
     List<String> ppid =
@@ -647,20 +577,6 @@ public class WmPackageManager {
     List<String> pkgIds =
         pkgs.stream().map(WmScorePackage::getId).distinct().sorted().collect(Collectors.toList());
 
-    // 获取包所关联的产品
-    List<String> drugIds =
-        pkgs.stream()
-            .flatMap(p -> Arrays.stream(p.getDrugtable()))
-            .distinct()
-            .sorted()
-            .collect(Collectors.toList());
-
-    Map<String, WmDaDrugEntDrugtable> drugtableMap =
-        CollUtil.isEmpty(drugIds)
-            ? Collections.emptyMap()
-            : wmDaDrugEntDrugtableMapper.selectBatchIds(drugIds).stream()
-                .collect(Collectors.toMap(WmDaDrugEntDrugtable::getId, Function.identity()));
-
     // 获得包所管理计划
     Map<Integer, Integer> pkg2PlanMap =
         planPkgService
@@ -683,28 +599,7 @@ public class WmPackageManager {
         implementPlanService.listByIds(planIds).stream()
             .collect(Collectors.toMap(SysImplementPlan::getPlanId, Function.identity()));
 
-    // 获取子集包
-    List<WmScorePackage> childrenPkgs =
-        scorePackageService.list(
-            Wrappers.<WmScorePackage>lambdaQuery()
-                .eq(WmScorePackage::getEnableFlag, EnableEnum.ENABLE.val())
-                .in(WmScorePackage::getRelationScoreId, pkgIds));
-    List<String> cPkgIds =
-        childrenPkgs.stream()
-            .map(WmScorePackage::getId)
-            .distinct()
-            .sorted()
-            .collect(Collectors.toList());
-    // 父级下的所有子集
-    Map<String, List<String>> parentId2PkgMap =
-        CollUtil.isEmpty(childrenPkgs)
-            ? Collections.emptyMap()
-            : childrenPkgs.stream()
-                .collect(
-                    Collectors.groupingBy(
-                        WmScorePackage::getRelationScoreId,
-                        Collectors.mapping(WmScorePackage::getId, Collectors.toList())));
-
+    
     // 获取全部的任务
     List<WmTask> tasks =
         taskService.list(
@@ -720,18 +615,7 @@ public class WmPackageManager {
     Map<String, List<WmTask>> pkg2TaskListMap =
         tasks.stream().collect(Collectors.groupingBy(WmTask::getScorePackageId));
 
-    // 获取下发的
-    List<WmPackageTaskTypeQty> taskTypeQties =
-        packageTaskTypeQtyService.listPkgTaskTypeQtyByPkgIds(
-            cPkgIds.stream()
-                .mapToInt(Integer::parseInt)
-                .boxed()
-                .distinct()
-                .sorted()
-                .collect(Collectors.toList()));
-    Map<Integer, List<WmPackageTaskTypeQty>> pttMap =
-        taskTypeQties.stream().collect(Collectors.groupingBy(WmPackageTaskTypeQty::getPackageId));
-
+    
     List<WmScorePackageInfoExcelModel> result =
         pkgs.parallelStream()
             .map(
@@ -1244,12 +1128,305 @@ public class WmPackageManager {
     return Boolean.TRUE;
   }
 
-  public List<WmScorePackageCheckStatusExcelModel> exportCheckInfo(Integer year, Integer quarter) {
-    WmScorePackageCheckStatusExcelModel model = new WmScorePackageCheckStatusExcelModel();
-    model.setYear(Integer.toString(year));
-    model.setQuarter(Integer.toString(quarter));
+  public List<WmScorePackageCheckStatusExcelModel> exportCheckInfo(LocalDate startDate, LocalDate endDate) {
+    if(new HashSet<>(SecurityUtils.getRoles()).contains(37)) {
+      throw new RuntimeException("服务商管理员没有权限查看");
+    }
+    WmPackageExportScope scope = getWmPackageExportScope(startDate, endDate);
+    
     List<WmScorePackageCheckStatusExcelModel> result = new ArrayList<>();
-    result.add(model);
+    Map<Integer, String> quarterMap = 
+      Map.ofEntries(Map.entry(1, "一季度"), Map.entry(2, "二季度"), Map.entry(3, "三季度"),  Map.entry(4, "四季度"));
+
+    int batch = 20;
+    for(int i = 0; i < scope.pkgs.size(); i = i + batch) {
+      List<WmScorePackage> pkgBatch = scope.pkgs.subList(i, Math.min(i + batch, scope.pkgs.size()));
+      List<String> pkgIds = pkgBatch.stream()
+        .map(p -> p.getId())
+        .sorted()
+        .collect(Collectors.toList());
+
+      List<String> cPkgIdBatch = pkgIds.stream()
+        .map(id -> scope.parentId2PkgMap.getOrDefault(id, new ArrayList<>()))
+        .flatMap(list -> list.stream())
+        .sorted()
+        .collect(Collectors.toList());
+      List<WmTask> tasks =
+        taskService.list(
+            Wrappers.<WmTask>lambdaQuery()
+                .in(
+                    WmTask::getScorePackageId,
+                    cPkgIdBatch));
+      Map<String, List<WmTask>> cPkg2TaskListMap =
+          tasks.stream().collect(Collectors.groupingBy(WmTask::getScorePackageId));          
+
+      List<Map<String, Object>> checkBatch = sysCheckChainNodeCheckHistoryMapper.getTaskCheckHisForDivisionPkgs(pkgIds);
+      Map<String, List<Map<String, Object>>> pkg2CheckListMap =
+          checkBatch.stream().collect(Collectors.groupingBy((row) -> row.get("pkg_id").toString()));          
+
+      pkgBatch.parallelStream()
+            .map(
+                pkg -> {
+                  WmScorePackageCheckStatusExcelModel model = new WmScorePackageCheckStatusExcelModel();
+
+                  model.setDivision(scope.dis.getOrDefault(Integer.valueOf(pkg.getSendPackageDeptId()), new SysDept()).getName());
+                  model.setProvince(pkg.getProvAbbr());
+                  model.setCsoName(scope.service.getOrDefault(Integer.valueOf(pkg.getDeptId()), new SysDept()).getName());
+                  model.setYear(String.format("%d年", pkg.getCreateTime().getYear()));
+                  model.setQuarter(quarterMap.get(pkg.getCreateTime().getMonthValue() / 3 + 1));
+                  model.setProduct(scope.drugtableMap.getOrDefault(pkg.getDrugtable()[0], new WmDaDrugEntDrugtable()).getDrugnameTy());
+                  model.setPkgName(pkg.getScorePackageName());
+                  int plannedQty = scope.parentId2PkgMap.getOrDefault(pkg.getId(), new ArrayList<>())
+                    .stream().mapToInt(Integer::parseInt).reduce(0, (cnt, cPkgId) -> {
+                      cnt += scope.pttMap.getOrDefault(cPkgId, new ArrayList<>())
+                        .stream().mapToInt(WmPackageTaskTypeQty::getQty).sum();
+                      return cnt;
+                    });
+                  model.setTaskNumPlanned(Integer.toString(plannedQty));
+                  int actualQty = scope.parentId2PkgMap.getOrDefault(pkg.getId(), new ArrayList<>())
+                    .stream().mapToInt(Integer::parseInt).reduce(0, (cnt, cPkgId) -> {
+                      cnt += cPkg2TaskListMap.getOrDefault(Integer.toString(cPkgId), new ArrayList<>()).size();
+                      return cnt;
+                    });
+                  model.setTaskNumSubmitted(Integer.toString(actualQty));
+                  
+                  List<Map<String, Object>> checkList = pkg2CheckListMap.getOrDefault(pkg.getId(), new ArrayList<>());
+                  checkList.sort((a, b) -> {
+                      int ret = Integer.compare(toInteger(a.get("task_id")), toInteger(b.get("task_id")));
+                      if(ret == 0) {
+                        ret = Integer.compare(toInteger(a.get("seq")), toInteger(b.get("seq")));
+                      }
+                      return ret;
+                    });
+                  int[] passed = new int[10];
+                  int[] rejected = new int[10];
+                  int[] todos = new int[10];
+                  int lastTaskId = -1;
+                  int lastSeq = -1;
+                  int lastSeq4Num = 1;
+                  boolean lastRejected = true;
+                  for(Map<String, Object> record: checkList) {
+                    int taskId = toInteger(record.get("task_id"));
+                    int nodeId = toInteger(record.get("node_id"));
+                    int seq = toInteger(record.get("seq"));
+                    int checkResult = toInteger(record.get("check_result"));
+                    
+                    if(checkResult == 1) {
+                      passed[nodeId] += 1;
+                    } else {
+                      rejected[nodeId] += 1;
+                    }
+
+                    if(lastTaskId != taskId) { // handle todo of last task
+                      if(!lastRejected) {
+                        if(lastSeq == 4) {
+                          if(lastSeq4Num % 8 == 0 && lastSeq4Num % 9 == 0) {
+                            todos[5] += 1;
+                          } else if(lastSeq4Num % 9 == 0) {
+                            todos[8] += 1;
+                          } else {
+                            todos[9] += 1;
+                          }
+                        } else if(lastSeq == 3) {
+                          todos[8] += 1;
+                          todos[9] += 1;
+                        } else if(lastSeq != 6) {
+                          todos[lastSeq+1] += 1;
+                        }
+                      }
+                      lastTaskId = taskId;
+                      lastRejected = false;
+                      lastSeq4Num = 1;
+                    }
+
+                    if(checkResult == 0) {
+                      lastRejected = true;
+                    }
+                    lastSeq = seq;
+                    lastSeq4Num *= nodeId > 7 && checkResult == 1 ? nodeId : 1;
+                  }
+
+                  model.setNode2PassedNum(Integer.toString(passed[2]));
+                  model.setNode2RejectNum(Integer.toString(rejected[2]));
+                  model.setNode2TodoNum(Integer.toString(todos[2]));
+                  if(!scope.operatorRoleIds.contains(43)) { // 非地市
+                    model.setNode3PassedNum(Integer.toString(passed[3]));
+                    model.setNode3RejectNum(Integer.toString(rejected[3]));
+                    model.setNode3TodoNum(Integer.toString(todos[3]));
+                    if(!scope.operatorRoleIds.contains(4)) { // 非区域
+                      if(!scope.operatorRoleIds.contains(40)) { // 非商务
+                        model.setNode8PassedNum(Integer.toString(passed[8]));
+                        model.setNode8RejectNum(Integer.toString(rejected[8]));
+                        model.setNode8TodoNum(Integer.toString(todos[8]));
+                      }
+                      if(!scope.operatorRoleIds.contains(42)) { // 非市场
+                        model.setNode9PassedNum(Integer.toString(passed[9]));
+                        model.setNode9RejectNum(Integer.toString(rejected[9]));
+                        model.setNode9TodoNum(Integer.toString(todos[9]));
+                      }
+                      if(scope.operatorRoleIds.contains(41) || scope.operatorRoleIds.contains(39)) { // 分管领导 & 总经理
+                        model.setNode5PassedNum(Integer.toString(passed[5]));
+                        model.setNode5RejectNum(Integer.toString(rejected[5]));
+                        model.setNode5TodoNum(Integer.toString(todos[5]));
+                        if(scope.operatorRoleIds.contains(39)) { // 总经理
+                          model.setNode6PassedNum(Integer.toString(passed[6]));
+                          model.setNode6RejectNum(Integer.toString(rejected[6]));
+                          model.setNode6TodoNum(Integer.toString(todos[6]));
+                        }
+                      }
+                    }
+                  }
+                  model.setAllRejectNum(Integer.toString(rejected[2]+rejected[3]+rejected[8]+rejected[9]+rejected[5]+rejected[6]));
+                  model.setAlllTodoNum(Integer.toString(todos[2]+todos[3]+todos[8]+todos[9]+todos[5]+todos[6]));
+                  return model;
+                }
+            ).forEach(model -> {result.add(model); });
+    }
+
     return result;
   }
+
+  private WmPackageExportScope getWmPackageExportScope(LocalDate startDate, LocalDate endDate) {
+    Set<Integer> ignoreIds = new HashSet<>();
+    ignoreIds.add(1716964676);
+    ignoreIds.add(-1020826);
+    ignoreIds.add(-1019986);
+
+    Set<Integer> operatorRoleIds = new HashSet<>(SecurityUtils.getRoles());
+
+    // 获取所有的企业
+    List<SysDept> depts =
+        deptService
+            .list(
+                Wrappers.<SysDept>lambdaQuery()
+                    .eq(SysDept::getDelFlag, CommonConstants.STATUS_NORMAL))
+            .stream()
+            .filter(d -> !ignoreIds.contains(d.getDeptId()))
+            .collect(Collectors.toList());
+
+    if (CollUtil.isEmpty(depts)) {
+      throw new BizException("不存在生效的企业信息,无法获取导出数据");
+    }
+
+    // 分别过滤区域和服务商
+    List<Integer> parentDeptIds = operatorRoleIds.contains(37) ? //服务商的区域ID
+        sysDeptRelationMapper.selectList(
+            Wrappers.<SysDeptRelation>lambdaQuery()
+                .ne(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId())
+                .eq(SysDeptRelation::getDescendant, SecurityUtils.getUser().getDeptId()))
+            .stream().map(SysDeptRelation::getAncestor).collect(Collectors.toList())
+        : new ArrayList<>();
+    if (operatorRoleIds.contains(37) && CollUtil.isEmpty(parentDeptIds)) {
+      throw new RuntimeException("没有找到对应的区域");
+    }
+    List<Integer> childDeptIds = operatorRoleIds.contains(4) ? //区域的服务商ID
+        sysDeptRelationMapper.selectList(
+            Wrappers.<SysDeptRelation>lambdaQuery()
+                .eq(SysDeptRelation::getAncestor, SecurityUtils.getUser().getDeptId())
+                .ne(SysDeptRelation::getDescendant, SecurityUtils.getUser().getDeptId()))
+            .stream().map(SysDeptRelation::getDescendant).collect(Collectors.toList())
+        : new ArrayList<>();
+    if (operatorRoleIds.contains(4) && CollUtil.isEmpty(childDeptIds)) {
+      throw new RuntimeException("没有找到对应的服务商");
+    }
+
+    Map<Integer, SysDept> dis =
+        depts.stream()
+            .filter(d -> d.getLevel() == 3)
+            .filter(d -> !operatorRoleIds.contains(4) || operatorRoleIds.contains(4) && d.getDeptId().equals(SecurityUtils.getUser().getDeptId())) //区域管理员
+            .filter(d -> !operatorRoleIds.contains(43) || operatorRoleIds.contains(43) && d.getDeptId().equals(SecurityUtils.getUser().getDeptId())) //地市管理员
+            .filter(d -> !operatorRoleIds.contains(37) || operatorRoleIds.contains(37) && parentDeptIds.contains(d.getDeptId())) //服务商管理员
+            .collect(Collectors.toMap(SysDept::getDeptId, Function.identity()));
+    Map<Integer, SysDept> service =
+        depts.stream()
+            .filter(d -> d.getLevel() == 4)
+            .filter(d -> !operatorRoleIds.contains(4) || operatorRoleIds.contains(4) && childDeptIds.contains(d.getDeptId())) //区域管理员
+            .filter(d -> !operatorRoleIds.contains(43) || operatorRoleIds.contains(43) && childDeptIds.contains(d.getDeptId())) //地市管理员
+            .filter(d -> !operatorRoleIds.contains(37) || operatorRoleIds.contains(37) && d.getDeptId().equals(SecurityUtils.getUser().getDeptId())) //服务商管理员
+            .collect(Collectors.toMap(SysDept::getDeptId, Function.identity()));
+
+    if (CollUtil.isEmpty(dis) || CollUtil.isEmpty(service)) {
+      throw new BizException("不存在生效的区域或服务商,无法获取导出数据");
+    }
+
+    // 获取区域发的包
+    List<WmScorePackage> pkgs =
+        scorePackageService.list(
+            Wrappers.<WmScorePackage>lambdaQuery()
+                .eq(WmScorePackage::getEnableFlag, EnableEnum.ENABLE.val())
+                .between(WmScorePackage::getCreateTime, startDate, endDate)
+                .in(
+                    WmScorePackage::getSendPackageDeptId,
+                    dis.keySet().stream()
+                        .map(String::valueOf)
+                        .sorted()
+                        .collect(Collectors.toList())));
+
+    if (CollUtil.isEmpty(pkgs)) {
+      throw new BizException(
+          String.format(
+              "%s至%s没有区域发包记录,不支持导出",
+              DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN).format(startDate),
+              DateTimeFormatter.ofPattern(DatePattern.CHINESE_DATE_PATTERN).format(endDate)));
+    }
+
+    List<String> pkgIds =
+        pkgs.stream().map(WmScorePackage::getId).distinct().sorted().collect(Collectors.toList());
+
+    // 获取子集包
+    List<WmScorePackage> childrenPkgs =
+        scorePackageService.list(
+            Wrappers.<WmScorePackage>lambdaQuery()
+                .eq(WmScorePackage::getEnableFlag, EnableEnum.ENABLE.val())
+                .in(WmScorePackage::getRelationScoreId, pkgIds));
+    List<String> cPkgIds =
+        childrenPkgs.stream()
+            .map(WmScorePackage::getId)
+            .distinct()
+            .sorted()
+            .collect(Collectors.toList());
+
+    // 父级下的所有子集
+    Map<String, List<String>> parentId2PkgMap =
+        CollUtil.isEmpty(childrenPkgs)
+            ? Collections.emptyMap()
+            : childrenPkgs.stream()
+                .collect(
+                    Collectors.groupingBy(
+                        WmScorePackage::getRelationScoreId,
+                        Collectors.mapping(WmScorePackage::getId, Collectors.toList())));
+
+    // 获取下发的
+    List<WmPackageTaskTypeQty> taskTypeQties =
+    packageTaskTypeQtyService.listPkgTaskTypeQtyByPkgIds(
+        cPkgIds.stream()
+            .mapToInt(Integer::parseInt)
+            .boxed()
+            .distinct()
+            .sorted()
+            .collect(Collectors.toList()));
+    Map<Integer, List<WmPackageTaskTypeQty>> pttMap =
+        taskTypeQties.stream().collect(Collectors.groupingBy(WmPackageTaskTypeQty::getPackageId));
+
+    // 获取包所关联的产品
+    List<String> drugIds =
+        pkgs.stream()
+            .flatMap(p -> Arrays.stream(p.getDrugtable()))
+            .distinct()
+            .sorted()
+            .collect(Collectors.toList());
+
+    Map<String, WmDaDrugEntDrugtable> drugtableMap =
+        CollUtil.isEmpty(drugIds)
+            ? Collections.emptyMap()
+            : wmDaDrugEntDrugtableMapper.selectBatchIds(drugIds).stream()
+                .collect(Collectors.toMap(WmDaDrugEntDrugtable::getId, Function.identity()));
+
+    return new WmPackageExportScope(dis, service, pkgs, drugtableMap, operatorRoleIds,
+      childrenPkgs, cPkgIds, parentId2PkgMap, pttMap);
+  }
+
+  private Integer toInteger(Object obj) {
+    return Integer.valueOf(obj.toString());
+  }
 }

+ 4 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/mapper/SysCheckChainNodeCheckHistoryMapper.java

@@ -2,6 +2,7 @@ package com.qunzhixinxi.hnqz.admin.mapper;
 
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qunzhixinxi.hnqz.admin.api.entity.SysCheckChainNodeCheckHistory;
+import com.baomidou.mybatisplus.annotation.SqlParser;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import java.util.List;
 import java.util.Map;
@@ -31,4 +32,7 @@ public interface SysCheckChainNodeCheckHistoryMapper
   List<Map<String, Object>> listTaskCheckHis(@Param("taskIds") List<Integer> taskIds);
 
   Page<Integer> pageCheckHisByUsername(Page<Integer> page, @Param("createBy") String createBy);
+
+  @SqlParser(filter=true)
+  List<Map<String, Object>> getTaskCheckHisForDivisionPkgs(@Param("pkgIds") List<String> pkgIds);
 }

+ 17 - 0
hnqz-upms/hnqz-upms-biz/src/main/resources/mapper/SysCheckChainNodeCheckHistoryMapper.xml

@@ -31,4 +31,21 @@
     </where>
     ORDER BY ch.target_id
   </select>
+
+  <select id="getTaskCheckHisForDivisionPkgs" resultType="map">
+    SELECT p.id cpkg_id, p.relation_score_id pkg_id,
+      t.id task_id,
+      h.his_id, h.node_id, h.check_result, h.create_time1,
+      case when h.node_id > 6 then 4 else h.node_id end seq
+    FROM wm_score_package p
+    JOIN wm_task t
+    ON p.id = t.score_package_id
+    JOIN sys_chain_node_check_his AS h
+    ON t.id = h.target_id
+    WHERE p.enable_flag = '0' 
+    AND p.relation_score_id IN
+    <foreach collection="pkgIds" item="pkgId" open="(" close=")" separator=",">
+      #{pkgId}
+    </foreach>
+  </select>
 </mapper>