提交 1ae0a3dd authored 作者: Matrix's avatar Matrix

feat(核查模块): 完善了阅知,自动终结任务的机制

上级 723c7806
...@@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON; ...@@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON;
import com.github.wenhao.jpa.Specifications; import com.github.wenhao.jpa.Specifications;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.sun.tools.corba.se.idl.StringGen;
import com.tykj.dev.config.GlobalMap; import com.tykj.dev.config.GlobalMap;
import com.tykj.dev.config.swagger.AutoDocument; import com.tykj.dev.config.swagger.AutoDocument;
import com.tykj.dev.device.confirmcheck.common.CcNodeType; import com.tykj.dev.device.confirmcheck.common.CcNodeType;
...@@ -34,6 +33,7 @@ import com.tykj.dev.device.task.subject.bto.TaskBto; ...@@ -34,6 +33,7 @@ import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.task.subject.bto.TaskLogBto; import com.tykj.dev.device.task.subject.bto.TaskLogBto;
import com.tykj.dev.device.task.subject.domin.Task; import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.device.user.base.enums.AuExample; import com.tykj.dev.device.user.base.enums.AuExample;
import com.tykj.dev.device.user.base.ret.UserShenRe;
import com.tykj.dev.device.user.cache.AreaCache; import com.tykj.dev.device.user.cache.AreaCache;
import com.tykj.dev.device.user.read.service.MessageService; import com.tykj.dev.device.user.read.service.MessageService;
import com.tykj.dev.device.user.read.subject.bto.MessageBto; import com.tykj.dev.device.user.read.subject.bto.MessageBto;
...@@ -237,7 +237,7 @@ public class DeviceCheckController { ...@@ -237,7 +237,7 @@ public class DeviceCheckController {
return ccService.findAllStatTable(checkBillSelectVo); return ccService.findAllStatTable(checkBillSelectVo);
} }
@ApiOperation(value = "根据id查询核查详情数据", notes = "可以通过这个接口查询核查详情数据") @ApiOperation(value = "根据billId查询核查详情数据", notes = "可以通过这个接口查询核查详情数据")
@GetMapping("/detail/{id}") @GetMapping("/detail/{id}")
public ResponseEntity<ResultObj<CheckDetailVo>> findDetail(@PathVariable Integer id) { public ResponseEntity<ResultObj<CheckDetailVo>> findDetail(@PathVariable Integer id) {
CheckDetailVo detailVoList = detailRepo.findById(id) CheckDetailVo detailVoList = detailRepo.findById(id)
...@@ -246,6 +246,20 @@ public class DeviceCheckController { ...@@ -246,6 +246,20 @@ public class DeviceCheckController {
return ResponseEntity.ok(new ResultObj<>(detailVoList)); return ResponseEntity.ok(new ResultObj<>(detailVoList));
} }
@ApiOperation(value = "提供taskId,该接口返回可以跳转到详情页面的数据", notes = "提供taskId,该接口返回可以跳转到详情页面的数据")
@GetMapping("/msgLink")
public ResponseEntity msgLink(@RequestParam Integer taskId) {
// 如果是businessType = 7 走unionLink 否则走detail接口
Task task = taskRepo.findById(taskId).orElseThrow(() -> new ApiException(String.format("没有找到taskId = %d 的任务", taskId)));
if (task.getBusinessType().equals(CONFIRM_CHECK_STAT.id)){
return unionLink(7, task.getBillId());
}else if (task.getBusinessType().equals(CONFIRM_CHECK_DETAIL.id)){
return findDetail(task.getBillId());
}
return ResponseEntity.status(400).body("该businessType不在处理范围内!本接口处理的type = 7 ,8");
}
@ApiOperation(value = "根据id查询核查详情数据", notes = "可以通过这个接口查询核查详情数据") @ApiOperation(value = "根据id查询核查详情数据", notes = "可以通过这个接口查询核查详情数据")
@GetMapping("/detail/unit/{unitId}") @GetMapping("/detail/unit/{unitId}")
public ResponseEntity<ResultObj<List<CheckDetailVo>>> findDetailsByUnitId(@PathVariable Integer unitId) { public ResponseEntity<ResultObj<List<CheckDetailVo>>> findDetailsByUnitId(@PathVariable Integer unitId) {
...@@ -341,43 +355,6 @@ public class DeviceCheckController { ...@@ -341,43 +355,6 @@ public class DeviceCheckController {
return ResponseEntity.ok(new ResultObj<>(cdVo)); return ResponseEntity.ok(new ResultObj<>(cdVo));
} }
/**
* 获得指定单位的在库装备与非在库装备
*
* @param checkUnit 单位名
* @param allDevices 装备列表
* @return true -> 在库装备,false -> 非在库装备
*/
@NotNull
private Map<Boolean, List<DeviceLibrary>> getDevLibMap(String checkUnit, List<DeviceLibrary> allDevices) {
//在库 = A and B & not B 去除掉ls = 10 的装备 把ls = 11 的装备加入到非在库
Map<Boolean, List<DeviceLibrary>> locationMap = allDevices.stream()
.collect(partitioningBy(d -> d.getLocationUnit().equals(checkUnit)));
List<DeviceLibrary> devInLib = locationMap.get(true);
// filter ls == 11 join to 非在库
List<DeviceLibrary> ls11Lib = devInLib.stream().filter(d -> d.getLifeStatus() == 11).collect(toList());
// filter ls == 10
devInLib = devInLib.stream()
.filter(d -> d.getLifeStatus() != 10 && d.getLifeStatus() != 11)
.collect(toList());
// 非在库 = not A and in B
List<DeviceLibrary> devNotInLib = locationMap.get(false)
.stream().filter(d -> d.getOwnUnit().equals(checkUnit))
.collect(toList());
devNotInLib.addAll(ls11Lib);
Map<Boolean, List<DeviceLibrary>> devLib = new HashMap<>();
devLib.put(true, devInLib);
devLib.put(false, devNotInLib);
return devLib;
}
/** /**
* 该接口负责处理以下跳转情况 * 该接口负责处理以下跳转情况
* 1 - 统计跳转 * 1 - 统计跳转
...@@ -427,8 +404,7 @@ public class DeviceCheckController { ...@@ -427,8 +404,7 @@ public class DeviceCheckController {
.toVo() .toVo()
.getLinkVo(); .getLinkVo();
linkVo.setShutDown(true); linkVo.setShutDown(true);
} } else {
else {
// 正常处理,即时计算 // 正常处理,即时计算
// checkType = 0 核查,checkType = 1 检查 // checkType = 0 核查,checkType = 1 检查
if (ctVo.getCheckType() == 0) { if (ctVo.getCheckType() == 0) {
...@@ -601,8 +577,8 @@ public class DeviceCheckController { ...@@ -601,8 +577,8 @@ public class DeviceCheckController {
} }
//将此次使用的linkVo更新 //将此次使用的linkVo更新
DeviceCheckLink updateLink = linkRepo.findByStatId(billId) .orElse(new DeviceCheckLink()); DeviceCheckLink updateLink = linkRepo.findByStatId(billId).orElse(new DeviceCheckLink());
updateLink.setLinkText(JSON.toJSONStringWithDateFormat(linkVo,"yyyy-MM-dd")); updateLink.setLinkText(JSON.toJSONStringWithDateFormat(linkVo, "yyyy-MM-dd"));
updateLink.setStatId(billId); updateLink.setStatId(billId);
linkRepo.save(updateLink); linkRepo.save(updateLink);
...@@ -610,396 +586,146 @@ public class DeviceCheckController { ...@@ -610,396 +586,146 @@ public class DeviceCheckController {
} }
@NotNull /**
private LinkExamDetail getLed(LocalDateTime endTime, LocalDateTime updateTime, Task child) { * @param periodId 1-月度 2-季度 3-年度
Integer childBusType = child.getBusinessType(); * @return
Integer childBusId = child.getBillId(); */
@ApiOperation(value = "更新自动核查周期", notes = "更新自动核查周期")
DeviceCheckDetail childDetail = detailRepo.findById(childBusId).get(); @PutMapping("/task/{periodId}")
String unitName = childDetail.getCheckUnit(); public ResponseEntity updateTaskPeriod(
@PathVariable @ApiParam(value = "核查周期,1-月度 2-季度 3-年度", example = "1") Integer periodId) {
if (periodId < 1 || periodId > 3) {
return ResponseEntity.status(400).body(new ResultObj<>("提供了错误的周期参数!应该是 1/2/3 , 您提供的是" + periodId));
}
TaskPeriod period = TaskPeriod.values()[periodId - 1];
List<CheckAreaStatVo> casList = parseStatString2Vo(child.parse2Bto(), childDetail).stream() // 更新最新的周期
.map(CheckDeviceStatVo::getAreaStatList) ccService.updateTaskPeriod(period);
.flatMap(checkAreaStatVos -> checkAreaStatVos.stream()) // 结束当前任务,开启下轮任务
.collect(toList()); ccService.stopAutoCheckCron();
//自查的areaName要从detail里找 boolean startSuccess = ccService.startAutoCheckCron();
String areaName = childDetail.getCheckUnit();
CheckAreaStatVo cas;
if (casList.isEmpty()) { if (startSuccess) {
cas = new CheckAreaStatVo("默认地区", 0, 0, 0, 0, 0, 0); String nextTime = ccService.getNextTaskDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
return ResponseEntity.ok(new ResultObj<>(String.format("更新自动核查周期成功,下一次任务的执行时间为%s", nextTime)));
} else { } else {
cas = casList.get(0); return ResponseEntity.status(400).body("自动核查更新周期失败了!");
}
} }
LinkExamDetail led = cas2led(cas, child, endTime, updateTime); @ApiOperation(value = "获取下一次自动核查任务执行的具体时间", notes = "获取下一次自动核查任务执行的具体时间")
@GetMapping("/task/next")
public Map<String, LocalDate> getNextTaskTime() {
return ImmutableMap.of("nextTaskTime", ccService.getNextTaskDate());
}
led.setCheckUnit(unitName); @ApiOperation(value = "获取当前自动核查的核查周期", notes = "monthly-月度,quarterly-季度,yearly-年度")
return led; @GetMapping("/task/current")
public Map<String, String> getCurrentTaskPeriod() {
String periodName = ccService.getCurrentTaskPeriod().getCronExpression().name();
return ImmutableMap.of("currentTaskPeriod", periodName);
} }
/** /**
* lcd 里的列表都为检查,因此是集合对 * 发起检查时获取核查的标题
* *
* @param examJobId
* @return * @return
*/ */
private LinkCheckDetail cas2lcd(List<CheckAreaStatVo> casList, Task task, List<Task> detailTasks, String finalCityName) { @GetMapping("/title/{examJobId}")
LinkCheckDetail lcd = new LinkCheckDetail(); public ResponseEntity getNames(@PathVariable Integer examJobId) {
lcd.setId(task.getBillId()); // 根据检查的主键id 查询到prov city Stat的title
String finalSituation = ""; Integer provId = taskService.get(examJobId).getParentTaskId();
// 检查的job id 找到 father 进而找到 father的billid 进而找到title Id
// 核查结果的判断具体细节可以查看 docs/confirmCheck.md文档 Integer statId = taskService.get(provId).getBillId();
List<String> situationList = detailTasks.stream() DeviceCheckStat deviceCheckStat = statRepo.findById(statId).get();
.map(this::getDetailSituation) String title = deviceCheckStat.getTitle();
.collect(toList()); String remark = deviceCheckStat.getRemark();
return ResponseEntity.ok(new CheckTitleAndTimeVo(title, deviceCheckStat.getEndTime(), remark));
// 如果 size = 0 或全都是 无 ,则无
if (situationList.size() == 0) {
finalSituation = "无";
} else {
boolean allIsNothing = situationList.stream().allMatch(s -> s.equals("无"));
if (allIsNothing) {
finalSituation = "无";
}
//如果 有任意一个区状态是待审核
boolean anyIsAudit = situationList.stream().anyMatch(s -> s.equals("等待市审核"));
if (anyIsAudit) {
finalSituation = "等待市审核";
}
//如果 全都是 完成,那么是完成
boolean allIsFinish = situationList.stream().allMatch(s -> s.equals("完成"));
if (allIsFinish) {
finalSituation = "完成";
} }
// 其他情况,则是进行中 @ApiOperation(value = "发起自动核查", notes = "发起自动核查")
if (StringUtils.isEmpty(finalSituation)) { @PostMapping("/auto")
finalSituation = "进行中"; public ResultObj<Map<String, List<Integer>>> startAutoCheck() {
} Map<String, List<Integer>> resultIds = ccService.autoCheck();
return new ResultObj<>(resultIds, "自动核查任务发起成功");
} }
lcd.setCheckSituation(finalSituation); @ApiOperation(value = "根据地区ID获取下级的单位", notes = "根据地区ID获取下级的单位")
@GetMapping("/under/{areaId}")
// 核查情况 所有子任务都是初始状态 = 无 10=未 public ResponseEntity getUnitsUnderAreaId(@PathVariable Integer areaId, @RequestParam(defaultValue = "true") boolean filter) {
String checkReuslt = ""; //1.获取child AreaId List
// Task 先将历史数据给过滤掉 - 方法是按照billId分组排序,跳出主键id最大的即最新的一条 List<Integer> areaIds = areaRepo.findAllByFatherId(areaId).stream()
detailTasks = detailTasks.stream() .map(Area::getId)
.collect(groupingBy(Task::getTitle,
collectingAndThen(maxBy(Comparator.comparing(Task::getId)), Optional::get)))
.values().stream()
.collect(toList()); .collect(toList());
// 不能存在有9999的任务 //2. 根据childId 获得对应的unit
boolean notExistsEnd = detailTasks.stream() List<Units> unitsList = unitsRepo.findAllByAreaIdIn(areaIds);
.allMatch(t -> !t.getBillStatus().equals(END.id));
if (notExistsEnd) { // 根据filter 决定是否将没有数据的装备给过滤掉
checkReuslt = "无"; if (filter) {
} else { unitsList = unitsList.stream()
// 任意一个是10则是待审核 .filter(unit -> deviceRepo.findAllByOwnUnit(unit.getName()).size() != 0)
boolean waitAudit = casList.stream() .collect(toList());
.anyMatch(cas -> cas.getComSituation() == 10); }
boolean notPassed = casList.stream() return ResponseEntity.ok(unitsList);
.anyMatch(cas -> cas.getComSituation() == 13); }
// 需要每一个城市都有无误(即12) 才算无误 @ApiOperation(value = "检查地区是否可以发起核查", notes = "检查地区是否可以发起核查")
Map<String, List<CheckAreaStatVo>> map = casList.stream() @PostMapping("/checkPossible")
.collect(groupingBy(CheckAreaStatVo::getAreaName)); public ResponseEntity checkPossible(@RequestBody UnitIds unitIds) {
List<String> unitNames = unitIds.getIds().stream()
.map(id -> auService.findOne(AuExample.UnitId, id))
.map(AreaUnit::getUnitName)
.collect(toList());
long okCount = 0; boolean findEmpty = false;
String alertString = "[";
for (List<CheckAreaStatVo> vos : map.values()) { for (String unitName : unitNames) {
boolean containsOk = vos.stream() List<DeviceLibrary> devices = deviceRepo.findAllByOwnUnit(unitName);
.anyMatch(checkAreaStatVo -> checkAreaStatVo.getComSituation() == 12); if (devices.size() == 0) {
if (containsOk) { findEmpty = true;
okCount++; alertString += unitName + " ";
} }
} }
boolean allOk = okCount >= map.size(); alertString += "]";
alertString += "单位没有装备数据,请重新勾选!";
if (waitAudit) { return ResponseEntity.ok(ImmutableMap.of("empty", findEmpty, "msg", alertString));
checkReuslt = CHECK_RESULT_WAIT;
} else if (allOk) {
checkReuslt = CHECK_RESULT_DONE;
} else if (notPassed) {
checkReuslt = "未通过";
} else {
checkReuslt = "进行中";
}
} }
lcd.setCheckResult(checkReuslt);
lcd.setCheckUnit(finalCityName + "局"); @ApiOperation(value = "发起核查", notes = "对指定单位发起核查任务")
@PostMapping("/startCheck")
public ResponseEntity startCheck(@RequestBody CheckCheckVo ccVO) {
// 构建省的统计账单
Integer startUnitId = ccVO.getUnitId();
Units startUnit = unitsRepo.findById(startUnitId).get();
List<Units> checkedUnits = unitsRepo.findAllById(ccVO.getUnitRange());
// 1.发起自己的自查 (市,tpye=2,省 level = 0,1,2)
// 2.发起自己的检查(只是市级别的 level=2)
List<String> checkedUnitNames = checkedUnits.stream().map(Units::getName).collect(toList());
return lcd; log.info("[核查模块]发起核查,发起单位为{},被查单位为{}", startUnit.getName(), checkedUnitNames);
} // 构建省的统计账单,所有的checkedUnits都要被包含到统计中去
DeviceCheckStat provinceCheckStat = initStatData(ccVO.getTitle(), ccVO.getRemark(), 0, 0, startUnit.getName(), checkedUnits, ccVO.getEndTime().atStartOfDay());
provinceCheckStat.setCheckType(CheckType.CT_CHECK);
Integer statId = statRepo.save(provinceCheckStat).getId();
List<CheckDeviceStatVo> deviceStatVos = Arrays.stream(
Objects.requireNonNull(JacksonUtil.readValue(provinceCheckStat.getStatInfo(), CheckDeviceStatVo[].class)))
.collect(toList());
@GetMapping("/test/test") // 构建省的统计任务
private String justForTest() { TaskBto provStatTask = new Task(CHECK_STAT_1.id, getUnitDateString(startUnit, ccVO.getTitle()), 0, ".0.", CONFIRM_CHECK_STAT.id, statId, startUnitId)
CheckChart.taskStatus2Situation.forEach((k, v) -> System.out.println(v)); .parse2Bto();
return "test"; provStatTask.getInvolveUserIdList().add(authenticationUtils.getAuthentication().getCurrentUserInfo().getUserId());
} provStatTask.getInvolveUserIdList().add(0);
provStatTask.setCurrentPoint(1);
/** provStatTask.setCustomInfo("check");
* 获得自查的核查情况 provStatTask = taskService.start(provStatTask);
*/
private String getDetailSituation(Task task) {
Integer taskStatus = task.getBillStatus();
String situation = CheckChart.taskStatus2Situation.get(taskStatus);
// 无的情况要分两种 一种是初始的无 一种是重做导致的无 通过判断task的remark
String remark = task.getRemark();
if (situation.equals("无")) {
if (Objects.nonNull(remark) && remark.contains("ROLLBACK")) {
situation = "未通过";
}
}
return situation;
}
/**
* led 里的列表都为自查,因此都是单个对象
*
* @return
*/
private LinkExamDetail cas2led(CheckAreaStatVo cas, Task task, LocalDateTime endTime, LocalDateTime updateTime) {
LinkExamDetail led = new LinkExamDetail();
led.setId(task.getBillId());
int comProgress = cas.getComProgress();
int comSituation = cas.getComSituation();
// 核查情况依照 新的与task status来对应 详情可以查看docs/confirmcheck.md里的对应表 对照表
String situation = getDetailSituation(task);
// 逾期的处理,只在完成的那一步才判断
if (situation.equals("完成") && updateTime.isAfter(endTime)) {
situation = "逾期完成";
}
led.setCheckSituation(situation);
String checkResult = "";
String remark = task.getRemark();
// 核查结果 - 如果省的自查任务,核查情况是完成了之后,核查结果就是无误
String unitName = detailRepo.findById(task.getBillId()).get().getCheckUnit();
Integer areaType = auService.findOne(AuExample.UnitName, unitName).getType();
if (!situation.contains("完成")) {
checkResult = "无";
} else if (comSituation == 10) {
// 再判断一下 是2级结构(检查统计)还是3级结构(核查统计)
Integer rootId = taskService.findByTaskId(task.getParentTaskId()).getParentTaskId();
boolean isTwoLevel = rootId == null || rootId == 0;
// 2级结构 - 检查统计 发起人单位是省,结果为等待省审核,发起人是市则是无
if (isTwoLevel) {
Integer startUnitId = userService.findById(task.getCreateUserId()).getUnitsId();
if (startUnitId != 1) {
checkResult = "无";
} else {
//根据detail userC为省且任务状态是完结状态时 变为无误 否则是等待省审核
Integer detailId = task.getBillId();
Integer userCId = detailRepo.findById(detailId).get().getUserCId();
if (task.getBillStatus().equals(END.id) && userIsProv(userCId)) {
checkResult = CHECK_RESULT_DONE;
} else {
checkResult = CHECK_RESULT_WAIT;
}
}
} else {
checkResult = CHECK_RESULT_WAIT;
}
} else if (comSituation == 12) {
checkResult = CHECK_RESULT_DONE;
} else if (comSituation == 13) {
int redoTime = 1;
if (Objects.nonNull(remark) && remark.contains("ROLLBACK")) {
redoTime = Integer.valueOf(remark.split("-")[1]);
}
checkResult = redoTime + "次未通过";
} else if (comSituation == 0) {
if (task.getBillStatus().equals(END.id)) {
int redoTime = 1;
if (Objects.nonNull(remark) && remark.contains("ROLLBACK")) {
redoTime = Integer.valueOf(remark.split("-")[1]);
}
checkResult = redoTime + "次未通过";
} else {
checkResult = CHECK_RESULT_WAIT;
}
} else {
checkResult = "状态异常";
}
led.setCheckResult(checkResult);
led.setCheckUnit(cas.getAreaName() + "局");
return led;
}
/**
* 判断用户是否是省级用户
*
* @return
*/
private boolean userIsProv(Integer userId) {
if (Objects.isNull(userId) || userId == 0) {
return false;
}
Integer unitsId = userService.findById(userId).getUnitsId();
Integer level = unitsRepo.findById(unitsId).get().getLevel();
return level == 1;
}
/**
* @param periodId 1-月度 2-季度 3-年度
* @return
*/
@ApiOperation(value = "更新自动核查周期", notes = "更新自动核查周期")
@PutMapping("/task/{periodId}")
public ResponseEntity updateTaskPeriod(
@PathVariable @ApiParam(value = "核查周期,1-月度 2-季度 3-年度", example = "1") Integer periodId) {
if (periodId < 1 || periodId > 3) {
return ResponseEntity.status(400).body(new ResultObj<>("提供了错误的周期参数!应该是 1/2/3 , 您提供的是" + periodId));
}
TaskPeriod period = TaskPeriod.values()[periodId - 1];
// 更新最新的周期
ccService.updateTaskPeriod(period);
// 结束当前任务,开启下轮任务
ccService.stopAutoCheckCron();
boolean startSuccess = ccService.startAutoCheckCron();
if (startSuccess) {
String nextTime = ccService.getNextTaskDate().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
return ResponseEntity.ok(new ResultObj<>(String.format("更新自动核查周期成功,下一次任务的执行时间为%s", nextTime)));
} else {
return ResponseEntity.status(400).body("自动核查更新周期失败了!");
}
}
@ApiOperation(value = "获取下一次自动核查任务执行的具体时间", notes = "获取下一次自动核查任务执行的具体时间")
@GetMapping("/task/next")
public Map<String, LocalDate> getNextTaskTime() {
return ImmutableMap.of("nextTaskTime", ccService.getNextTaskDate());
}
@ApiOperation(value = "获取当前自动核查的核查周期", notes = "monthly-月度,quarterly-季度,yearly-年度")
@GetMapping("/task/current")
public Map<String, String> getCurrentTaskPeriod() {
String periodName = ccService.getCurrentTaskPeriod().getCronExpression().name();
return ImmutableMap.of("currentTaskPeriod", periodName);
}
/**
* 发起检查时获取核查的标题
*
* @param examJobId
* @return
*/
@GetMapping("/title/{examJobId}")
public ResponseEntity getNames(@PathVariable Integer examJobId) {
// 根据检查的主键id 查询到prov city Stat的title
Integer provId = taskService.get(examJobId).getParentTaskId();
// 检查的job id 找到 father 进而找到 father的billid 进而找到title Id
Integer statId = taskService.get(provId).getBillId();
DeviceCheckStat deviceCheckStat = statRepo.findById(statId).get();
String title = deviceCheckStat.getTitle();
String remark = deviceCheckStat.getRemark();
return ResponseEntity.ok(new CheckTitleAndTimeVo(title, deviceCheckStat.getEndTime(), remark));
}
@ApiOperation(value = "发起自动核查", notes = "发起自动核查")
@PostMapping("/auto")
public ResultObj<Map<String, List<Integer>>> startAutoCheck() {
Map<String, List<Integer>> resultIds = ccService.autoCheck();
return new ResultObj<>(resultIds, "自动核查任务发起成功");
}
@ApiOperation(value = "根据地区ID获取下级的单位", notes = "根据地区ID获取下级的单位")
@GetMapping("/under/{areaId}")
public ResponseEntity getUnitsUnderAreaId(@PathVariable Integer areaId, @RequestParam(defaultValue = "true") boolean filter) {
//1.获取child AreaId List
List<Integer> areaIds = areaRepo.findAllByFatherId(areaId).stream()
.map(Area::getId)
.collect(toList());
//2. 根据childId 获得对应的unit
List<Units> unitsList = unitsRepo.findAllByAreaIdIn(areaIds);
// 根据filter 决定是否将没有数据的装备给过滤掉
if (filter) {
unitsList = unitsList.stream()
.filter(unit -> deviceRepo.findAllByOwnUnit(unit.getName()).size() != 0)
.collect(toList());
}
return ResponseEntity.ok(unitsList);
}
@ApiOperation(value = "检查地区是否可以发起核查", notes = "检查地区是否可以发起核查")
@PostMapping("/checkPossible")
public ResponseEntity checkPossible(@RequestBody UnitIds unitIds) {
List<String> unitNames = unitIds.getIds().stream()
.map(id -> auService.findOne(AuExample.UnitId, id))
.map(AreaUnit::getUnitName)
.collect(toList());
boolean findEmpty = false;
String alertString = "[";
for (String unitName : unitNames) {
List<DeviceLibrary> devices = deviceRepo.findAllByOwnUnit(unitName);
if (devices.size() == 0) {
findEmpty = true;
alertString += unitName + " ";
}
}
alertString += "]";
alertString += "单位没有装备数据,请重新勾选!";
return ResponseEntity.ok(ImmutableMap.of("empty", findEmpty, "msg", alertString));
}
private String getUnitDateString(Units units, String title) {
return "[" + units.getUnitDesc() + "]" + title;
}
@ApiOperation(value = "发起核查", notes = "对指定单位发起核查任务")
@PostMapping("/startCheck")
public ResponseEntity startCheck(@RequestBody CheckCheckVo ccVO) {
// 构建省的统计账单
Integer startUnitId = ccVO.getUnitId();
Units startUnit = unitsRepo.findById(startUnitId).get();
List<Units> checkedUnits = unitsRepo.findAllById(ccVO.getUnitRange());
// 1.发起自己的自查 (市,tpye=2,省 level = 0,1,2)
// 2.发起自己的检查(只是市级别的 level=2)
List<String> checkedUnitNames = checkedUnits.stream().map(Units::getName).collect(toList());
log.info("[核查模块]发起核查,发起单位为{},被查单位为{}", startUnit.getName(), checkedUnitNames);
// 构建省的统计账单,所有的checkedUnits都要被包含到统计中去
DeviceCheckStat provinceCheckStat = initStatData(ccVO.getTitle(), ccVO.getRemark(), 0, 0, startUnit.getName(), checkedUnits, ccVO.getEndTime().atStartOfDay());
provinceCheckStat.setCheckType(CheckType.CT_CHECK);
Integer statId = statRepo.save(provinceCheckStat).getId();
List<CheckDeviceStatVo> deviceStatVos = Arrays.stream(
Objects.requireNonNull(JacksonUtil.readValue(provinceCheckStat.getStatInfo(), CheckDeviceStatVo[].class)))
.collect(toList());
// 构建省的统计任务
TaskBto provStatTask = new Task(CHECK_STAT_1.id, getUnitDateString(startUnit, ccVO.getTitle()), 0, ".0.", CONFIRM_CHECK_STAT.id, statId, startUnitId)
.parse2Bto();
provStatTask.getInvolveUserIdList().add(authenticationUtils.getAuthentication().getCurrentUserInfo().getUserId());
provStatTask.getInvolveUserIdList().add(0);
provStatTask.setCurrentPoint(1);
provStatTask.setCustomInfo("check");
provStatTask = taskService.start(provStatTask);
desMap.put(provStatTask.getId(), ccVO.getRemark()); desMap.put(provStatTask.getId(), ccVO.getRemark());
//构建市的检查任务(level=2) //构建市的检查任务(level=2)
...@@ -1304,14 +1030,6 @@ public class DeviceCheckController { ...@@ -1304,14 +1030,6 @@ public class DeviceCheckController {
return ResponseEntity.ok(desBillMap.get(billId)); return ResponseEntity.ok(desBillMap.get(billId));
} }
private TaskBto selectProvTask(Integer taskId) {
TaskBto taskBto = taskService.get(taskId);
if (taskBto.getParentTaskId() == 0) {
return taskBto;
}
return selectProvTask(taskBto.getParentTaskId());
}
/** /**
* 对于专员A来说的逻辑 * 对于专员A来说的逻辑
* 1. 修改detailString * 1. 修改detailString
...@@ -1542,20 +1260,6 @@ public class DeviceCheckController { ...@@ -1542,20 +1260,6 @@ public class DeviceCheckController {
} }
/**
* 尝试自动完结检查任务(市/省的)
* 1. 当且仅当该检查任务的状态等于@link{CHECK_EXAM_STAT_1}时且其下的所有子任务均为完结状态,自动推进
*
* @param exam的taskId
*/
private void advanceExamTask(Integer examTaskId) {
TaskBto parentTask = taskService.findByTaskId(examTaskId);
if (parentTask.getBillStatus().equals(CHECK_EXAM_STAT_1.id) && taskService.TaskTreeIsOver(examTaskId)) {
log.info("[核查模块] 检测到task id = {}的检查任务已经可以自动推进了,自动推进至下一步", examTaskId);
statConfirm(parentTask.getBillId());
}
}
/** /**
* 省专管员审核自查数据的方法 * 省专管员审核自查数据的方法
* *
...@@ -1581,11 +1285,12 @@ public class DeviceCheckController { ...@@ -1581,11 +1285,12 @@ public class DeviceCheckController {
@ApiOperation(value = "终结stat任务,多指核查任务") @ApiOperation(value = "终结stat任务,多指核查任务")
@PutMapping("/stat/shutdown/{statId}") @PutMapping("/stat/shutdown/{statId}")
public ResponseEntity shutDown(@PathVariable Integer statId) { public ResponseEntity shutDown(@PathVariable Integer statId) {
log.info("[核查模块] 终止任务 - 正在终止statId = {} 的统计任务",statId); log.info("[核查模块] 终止任务 - 正在终止statId = {} 的统计任务", statId);
Task checkTask = taskRepo.findByBillIdAndBusinessType(statId, CONFIRM_CHECK_STAT.id).get(); Task checkTask = taskRepo.findByBillIdAndBusinessType(statId, CONFIRM_CHECK_STAT.id).get();
// 将该stat任务置为20000,即终止 // 将该stat任务置为20000,即终止
unionLink(7, statId); unionLink(7, statId);
taskService.moveToSpecial(checkTask.parse2Bto(), REVOKEALLOTTASK); taskService.moveToSpecial(checkTask.parse2Bto(), REVOKEALLOTTASK);
supplyLogMsg(checkTask);
// 检验所有还没有end的节点 // 检验所有还没有end的节点
// 1级节点分为两类 自查类节点&统计数据确认节点 以及 检查类节点 // 1级节点分为两类 自查类节点&统计数据确认节点 以及 检查类节点
...@@ -1595,6 +1300,7 @@ public class DeviceCheckController { ...@@ -1595,6 +1300,7 @@ public class DeviceCheckController {
// c1里的检查节点也shutDown掉 并保存掉 // c1里的检查节点也shutDown掉 并保存掉
unionLink(7, c1.getBillId());//save unionLink(7, c1.getBillId());//save
taskService.moveToSpecial(c1.parse2Bto(), REVOKEALLOTTASK); taskService.moveToSpecial(c1.parse2Bto(), REVOKEALLOTTASK);
supplyLogMsg(c1);
List<Task> c2Childs = taskRepo.findAllByParentTaskId(c1.getId()); List<Task> c2Childs = taskRepo.findAllByParentTaskId(c1.getId());
c2Childs.forEach(c2 -> shutDownNode(c2)); c2Childs.forEach(c2 -> shutDownNode(c2));
} else { } else {
...@@ -1606,197 +1312,622 @@ public class DeviceCheckController { ...@@ -1606,197 +1312,622 @@ public class DeviceCheckController {
} }
/** /**
* 关闭某个节点,该节点下必须没有子节点树了 * @param taskId 待办任务id
* <p>1.将该任务进度推进至9999</> * @param statId 市级统计的STAT ID
* <p>2.手动补充终结日志</>
* <p>3.将终结信息添加阅知列表里面</>
*
* @param node
*/
private void shutDownNode(Task node) {
log.info("[核查模块] 终止任务-正在关闭 task id = {} 的任务节点");
// 如果是核查类捡点,抛出异常
if (node.getCustomInfo().equals("check") || node.getCustomInfo().equals("exam")) {
throw new ApiException("关闭节点里不处理核查/核查节点...,你提供的任务节点id = " + node.getId());
}
// 其余节点,执行关闭策略
// 1.将该任务进度推进至9999
TaskBto nodeBto = node.parse2Bto();
taskService.moveToEnd(nodeBto);
// 2.手动补充终结日志
String adminUser = authenticationUtils.getAuthentication().getCurrentUserInfo().getName();
String shutDownMsg = String.format("专管员[%s]终止了该任务", adminUser);
TaskLogBto taskLog = new TaskLogBto(node.getId(), shutDownMsg);
taskLogService.addLog(taskLog);
// 3.添加阅知信息
MessageBto msgBto = new MessageBto(node.getId(), node.getBusinessType(), shutDownMsg, nodeBto.getInvolveUserIdList());
messageService.add(msgBto);
log.info("[核查模块] 终止任务-task id = {} 成功关闭");
}
/**
* 将detail里的detailString里的检查数字该为指定数值
*
* @param detail
* @param number
*/
private DeviceCheckDetail setDetailCheckNumber(DeviceCheckDetail detail, Integer number) {
String detailString = detail.getCheckDetail();
String updatedString = Arrays.stream(detailString.split(","))
.map(s -> s.split("-")[0] + "-" + number)
.collect(joining(","));
detail.setCheckDetail(updatedString);
return detail;
}
/**
* 省对区审查 未通过的 逻辑
*
* @param id detail Id
* @return * @return
*/ */
private ResponseEntity provAuitNotPassed(Integer id) { @ApiOperation(value = "跟踪任务待办办结确认")
//1. bill单的自查将百位数变为3 @PostMapping("/stat/done")
DeviceCheckDetail detail = detailRepo.findById(id).get(); public ResponseEntity confirmDone(@RequestParam int taskId, @RequestParam int statId) {
String detailString = detail.getCheckDetail(); log.info("[核查模块] 正在进行办结任务确认,任务id为 : {}", taskId);
String initalDetail = Arrays.stream(detailString.split(",")) TaskBto cityDoneTask = taskService.get(taskId);
.map(s -> s.split("-")[0] + "-" + 119)
.collect(joining(","));
String updateDetail = changeHunds(detailString, 3); //市的task 且statId保持一致 省待办 需要的是 市的统计taskId
Specification<Task> pred = Specifications.<Task>and()
.eq("billId", statId)
.eq("businessType", CONFIRM_CHECK_STAT.id)
.build();
detailRepo.updateCheckDetail(id, updateDetail, "", 0, 0, 0); // 找到child任务 -> 市级任务 如果是2级的则直接找自己
List<Task> tasks = taskRepo.findAll(pred);
Task cityTask = tasks.stream()
.filter(task -> task.getParentTaskId() != 0 && task.getParentTaskId() != null)
.findFirst()
.orElse(tasks.get(0));
//2. 当前任务结束,开启一个新的 退回任务(连带一个新的detail) // 如果没有父统计TASK 则证明是两级
TaskBto currentTask = taskService.get(id, CONFIRM_CHECK_DETAIL.id); boolean doubleLevel = cityTask.getParentTaskId() == 0 || cityTask.getParentTaskId() == null;
String remark = currentTask.getRemark(); if (doubleLevel) {
if (Objects.nonNull(remark) && remark.contains("ROLLBACK")) { log.info("[核查模块] 办结确认两级检查任务");
Integer times = Integer.valueOf(remark.split("-")[1]);
remark = "ROLLBACK-" + ++times;
} else { } else {
remark = "ROLLBACK-1"; log.info("[核查模块] 办结确认三级检查任务");
} //1.累加数据 累加市级数据数据到省级
CheckStatVo cityStat = transUtil.checkStatDo2Vo(statRepo.findById(statId).get());
currentTask.setRemark(remark); Integer provStatId = taskService.get(cityTask.getParentTaskId()).getBillId();
TaskBto newTask = currentTask.toDo().copy().parse2Bto(); CheckStatVo provinceStat = transUtil.checkStatDo2Vo(statRepo.findById(provStatId).get());
currentTask.setCustomInfo(currentTask.getCustomInfo()); String cityName = areaCache.findById(unitsRepo.findAreaId(cityTask.getOwnUnit())).getName();
taskService.moveToEnd(currentTask); // 将区级信息合并到市中
// 创建新的detail 新的detail会在B的时候加入,所以老的stat要去除掉 List<CheckDeviceStatVo> mergedVo = cityStat.getDeviceStatVoList().stream()
DeviceCheckDetail cDetail = detail.copyWithoutId(); .map(vo -> vo.combine(cityName, cityStat.getId()))
cDetail.setId(null); .collect(toList());
cDetail.setCheckDetail(initalDetail); // 如果是第一个市,则替换,否则累加
cDetail.setCheckFiles(""); boolean firstCity = taskService.TaskTreeIsStart(cityTask.getParentTaskId(), true);
cDetail.setCheckFileList(Lists.newArrayList()); if (firstCity) {
cDetail = detailRepo.save(cDetail); provinceStat.setDeviceStatVoList(mergedVo);
// 创建新的任务(被拒绝的自查单位如果是区则是140状态,否则是160状态 ) log.info("[核查模块] 检测到该任务的合并状态为第一个市统计任务,因此直接替换省级统计数据");
String unitName = cDetail.getCheckUnit();
Integer level = unitsRepo.findByName(unitName).getLevel();
Integer initStatusId = 0;
if (level == 3) {
initStatusId = CHECK_DETAIL_REGION_0.id;
} else { } else {
initStatusId = CHECK_DETAIL_CITY_0.id; provinceStat.cleanReduce(mergedVo);
} log.info("[核查模块] 数据累加成功");
newTask.setBillStatus(initStatusId);
newTask.setBillId(cDetail.getId());
newTask.setId(0);
newTask.setCustomInfo(newTask.getCustomInfo());
newTask.getInvolveUserIdList().add(0);
newTask.setCurrentPoint(newTask.getInvolveUserIdList().size() - 1);
// 尝试从老任务中获取重做次数 - 新任务老任务都需要更新remark
newTask.setRemark(remark);
log.info("[核查模块] 省回退操作中... 任务remark = {}", remark);
newTask.setRemark(remark);
taskService.start(newTask);
//3. 在stat的remark中追加信息 - 找到currentTask在其中的顺位
TaskBto fatherTask = taskService.get(currentTask.getParentTaskId());
List<Task> childTask = taskRepo.findAllByParentTaskId(fatherTask.getId());
int pos = 0;
for (int i = 0; i < childTask.size(); i++) {
if (childTask.get(i).getId().equals(currentTask.getId())) {
log.info("[核查模块] 记录remark的pos位置 = {}", i);
} }
DeviceCheckStat dcs = provinceStat.toDo();
statRepo.save(dcs);
} }
DeviceCheckStat dcs = statRepo.findById(fatherTask.getBillId()).get(); //2.办结待办
String[] groups = dcs.getRemark().split("\\|"); taskService.moveToEnd(cityDoneTask);
String pading = groups[pos];
dcs.setRemark(dcs.getRemark() + "|" + pading);
log.info("[核查模块] 补充remark = {}", pading);
// 老的stat要去除掉对应areaName的数据
removeDetailFromDcs(detail, dcs);
//4.父级任务变为进行中 如果父级是核查,变成111,如果父级是检查,变成131 //3.如果所有省级的子任务都完成了
if (fatherTask.getCustomInfo().contains("exam")) { boolean over = taskService.TaskTreeIsOver(cityTask.getParentTaskId());
fatherTask.setBillStatus(CHECK_EXAM_STAT_1.id); if (over) {
} else if (fatherTask.getCustomInfo().contains("check")) { log.info("[核查模块] 所有的省级子任务都完成了,将省统计任务变为待办");
fatherTask.setBillStatus(CHECK_STAT_1.id); TaskBto provTask = taskService.get(cityTask.getParentTaskId());
provTask.getInvolveUserIdList().add(0);
provTask.setCurrentPoint(provTask.getCurrentPoint() + 1);
taskService.update(provTask);
} }
taskRepo.save(fatherTask.toDo());
return ResponseEntity.ok(new ResultObj<>("回退操作成功!"));
log.info("[核查模块] 办结统计待办操作成功");
return ResponseEntity.ok(new ResultObj<>("办结统计待办确认完毕"));
} }
/** /**
* 省对区审查通过的逻辑 * @param statId 统计账单主键id
*
* @param id detail Id
* @return
*/ */
private ResponseEntity provAuditPass(Integer id) { @ApiOperation(value = "统计数据确认")
//将自查的情况的百位数全部替换成2 @PostMapping("/stat/verify")
DeviceCheckDetail detail = detailRepo.findById(id).get(); public ResponseEntity<ResultObj> statConfirm(@RequestParam int statId) {
String updatedString = changeHunds(detail.getCheckDetail(), 2); log.info("[核查模块] 正在进行统计数据确认,统计账单id为 : {}", statId);
detail.setCheckDetail(updatedString); //将当前的统计task办结
detail.setUserCId(authenticationUtils.getAuthentication().getCurrentUserInfo().getUserId()); TaskBto currentTask = taskService.get(statId, CONFIRM_CHECK_STAT.id);
log.info("[核查模块] 审核通过 - 更新后的detailString形如 {}", updatedString.split(",")[0]); currentTask = taskService.moveToEnd(currentTask);
detailRepo.save(detail); Integer parentTaskId = currentTask.getParentTaskId();
boolean hasParent = parentTaskId != 0;
//将对应stat中地区的comProgress 改为 2 comsitution 改为12
String areaName = auService.findOne(AuExample.UnitName, detail.getCheckUnit()).getName();
TaskBto currentTask = taskService.get(id, CONFIRM_CHECK_DETAIL.id);
TaskBto fatherTask = taskService.get(currentTask.getParentTaskId());
DeviceCheckStat dcs = statRepo.findById(fatherTask.getBillId()).get();
CheckStatVo csv = transUtil.checkStatDo2Vo(dcs);
for (CheckDeviceStatVo vo : csv.getDeviceStatVoList()) {
for (CheckAreaStatVo av : vo.getAreaStatList()) {
if (av.getAreaName().equals(areaName)) {
log.info("[核查模块] 审核通过 - 地区 = {} 的统计数据在统计信息中被成功修改了", areaName);
av.auditPassed();
}
}
}
return ResponseEntity.ok(new ResultObj<>("审核通过!"));
//尝试寻找老的市办结任务,如果有的话就删除加END
//5.需要将上一次市的确认任务给清理掉 统计确认任务关联的是statId 找到billId -> exam Task ->
// 父级的父级,就是省的任务,然后子child里名字包含 统计数据确认任务 的任务给 END 吧
Map<Integer, List<Task>> doneTaskList = taskRepo.findAllByParentTaskId(parentTaskId)
.stream()
.filter(task -> task.getTitle().contains("统计数据确认任务"))
.collect(groupingBy(Task::getBillId));
} List<Task> existsDone = doneTaskList.get(statId);
private void removeDetailFromDcs(DeviceCheckDetail detail, DeviceCheckStat dcs) { if (Objects.nonNull(existsDone)) {
String areaName = auService.findOne(AuExample.UnitName, detail.getCheckUnit()).getName(); for (Task d : existsDone) {
CheckStatVo csv = transUtil.checkStatDo2Vo(dcs); log.info("[核查模块] 发现了id = {}市的重复的统计确认任务,将其完结并剔除整个树节点", d.getId());
for (CheckDeviceStatVo vo : csv.getDeviceStatVoList()) { d.setParentTaskId(0);
List<CheckAreaStatVo> filterList = vo.getAreaStatList().stream() taskService.moveToEnd(d.parse2Bto());
.filter(casv -> !casv.getAreaName().equals(areaName)).collect(toList());
if (filterList.size() != vo.getAreaStatList().size()) {
log.info("[核查模块] 回退操作-将退回的数据从统计中去除了.");
vo.setAreaStatList(filterList);
} }
} }
statRepo.save(csv.toDo()); log.info("[核查模块] 统计数据确认操作成功");
return ResponseEntity.ok(new ResultObj<>("统计数据确认完毕"));
} }
/** /**
* 将detailString里的百位数改为指定数字 * 获得指定单位的在库装备与非在库装备
*
* @param checkUnit 单位名
* @param allDevices 装备列表
* @return true -> 在库装备,false -> 非在库装备
*/
@NotNull
private Map<Boolean, List<DeviceLibrary>> getDevLibMap(String checkUnit, List<DeviceLibrary> allDevices) {
//在库 = A and B & not B 去除掉ls = 10 的装备 把ls = 11 的装备加入到非在库
Map<Boolean, List<DeviceLibrary>> locationMap = allDevices.stream()
.collect(partitioningBy(d -> d.getLocationUnit().equals(checkUnit)));
List<DeviceLibrary> devInLib = locationMap.get(true);
// filter ls == 11 join to 非在库
List<DeviceLibrary> ls11Lib = devInLib.stream().filter(d -> d.getLifeStatus() == 11).collect(toList());
// filter ls == 10
devInLib = devInLib.stream()
.filter(d -> d.getLifeStatus() != 10 && d.getLifeStatus() != 11)
.collect(toList());
// 非在库 = not A and in B
List<DeviceLibrary> devNotInLib = locationMap.get(false)
.stream().filter(d -> d.getOwnUnit().equals(checkUnit))
.collect(toList());
devNotInLib.addAll(ls11Lib);
Map<Boolean, List<DeviceLibrary>> devLib = new HashMap<>();
devLib.put(true, devInLib);
devLib.put(false, devNotInLib);
return devLib;
}
@NotNull
private LinkExamDetail getLed(LocalDateTime endTime, LocalDateTime updateTime, Task child) {
Integer childBusType = child.getBusinessType();
Integer childBusId = child.getBillId();
DeviceCheckDetail childDetail = detailRepo.findById(childBusId).get();
String unitName = childDetail.getCheckUnit();
List<CheckAreaStatVo> casList = parseStatString2Vo(child.parse2Bto(), childDetail).stream()
.map(CheckDeviceStatVo::getAreaStatList)
.flatMap(checkAreaStatVos -> checkAreaStatVos.stream())
.collect(toList());
//自查的areaName要从detail里找
String areaName = childDetail.getCheckUnit();
CheckAreaStatVo cas;
if (casList.isEmpty()) {
cas = new CheckAreaStatVo("默认地区", 0, 0, 0, 0, 0, 0);
} else {
cas = casList.get(0);
}
LinkExamDetail led = cas2led(cas, child, endTime, updateTime);
led.setCheckUnit(unitName);
return led;
}
/**
* lcd 里的列表都为检查,因此是集合对
*
* @return
*/
private LinkCheckDetail cas2lcd(List<CheckAreaStatVo> casList, Task task, List<Task> detailTasks, String finalCityName) {
LinkCheckDetail lcd = new LinkCheckDetail();
lcd.setId(task.getBillId());
String finalSituation = "";
// 核查结果的判断具体细节可以查看 docs/confirmCheck.md文档
List<String> situationList = detailTasks.stream()
.map(this::getDetailSituation)
.collect(toList());
// 如果 size = 0 或全都是 无 ,则无
if (situationList.size() == 0) {
finalSituation = "无";
} else {
boolean allIsNothing = situationList.stream().allMatch(s -> s.equals("无"));
if (allIsNothing) {
finalSituation = "无";
}
//如果 有任意一个区状态是待审核
boolean anyIsAudit = situationList.stream().anyMatch(s -> s.equals("等待市审核"));
if (anyIsAudit) {
finalSituation = "等待市审核";
}
//如果 全都是 完成,那么是完成
boolean allIsFinish = situationList.stream().allMatch(s -> s.equals("完成"));
if (allIsFinish) {
finalSituation = "完成";
}
// 其他情况,则是进行中
if (StringUtils.isEmpty(finalSituation)) {
finalSituation = "进行中";
}
}
lcd.setCheckSituation(finalSituation);
// 核查情况 所有子任务都是初始状态 = 无 10=未
String checkReuslt = "";
// Task 先将历史数据给过滤掉 - 方法是按照billId分组排序,跳出主键id最大的即最新的一条
detailTasks = detailTasks.stream()
.collect(groupingBy(Task::getTitle,
collectingAndThen(maxBy(Comparator.comparing(Task::getId)), Optional::get)))
.values().stream()
.collect(toList());
// 不能存在有9999的任务
boolean notExistsEnd = detailTasks.stream()
.allMatch(t -> !t.getBillStatus().equals(END.id));
if (notExistsEnd) {
checkReuslt = "无";
} else {
// 任意一个是10则是待审核
boolean waitAudit = casList.stream()
.anyMatch(cas -> cas.getComSituation() == 10);
boolean notPassed = casList.stream()
.anyMatch(cas -> cas.getComSituation() == 13);
// 需要每一个城市都有无误(即12) 才算无误
Map<String, List<CheckAreaStatVo>> map = casList.stream()
.collect(groupingBy(CheckAreaStatVo::getAreaName));
long okCount = 0;
for (List<CheckAreaStatVo> vos : map.values()) {
boolean containsOk = vos.stream()
.anyMatch(checkAreaStatVo -> checkAreaStatVo.getComSituation() == 12);
if (containsOk) {
okCount++;
}
}
boolean allOk = okCount >= map.size();
if (waitAudit) {
checkReuslt = CHECK_RESULT_WAIT;
} else if (allOk) {
checkReuslt = CHECK_RESULT_DONE;
} else if (notPassed) {
checkReuslt = "未通过";
} else {
checkReuslt = "进行中";
}
}
lcd.setCheckResult(checkReuslt);
lcd.setCheckUnit(finalCityName + "局");
return lcd;
}
private TaskBto selectProvTask(Integer taskId) {
TaskBto taskBto = taskService.get(taskId);
if (taskBto.getParentTaskId() == 0) {
return taskBto;
}
return selectProvTask(taskBto.getParentTaskId());
}
/**
* 获得自查的核查情况
*/
private String getDetailSituation(Task task) {
Integer taskStatus = task.getBillStatus();
String situation = CheckChart.taskStatus2Situation.get(taskStatus);
// 无的情况要分两种 一种是初始的无 一种是重做导致的无 通过判断task的remark
String remark = task.getRemark();
if (situation.equals("无")) {
if (Objects.nonNull(remark) && remark.contains("ROLLBACK")) {
situation = "未通过";
}
}
return situation;
}
/**
* led 里的列表都为自查,因此都是单个对象
*
* @return
*/
private LinkExamDetail cas2led(CheckAreaStatVo cas, Task task, LocalDateTime endTime, LocalDateTime updateTime) {
LinkExamDetail led = new LinkExamDetail();
led.setId(task.getBillId());
int comProgress = cas.getComProgress();
int comSituation = cas.getComSituation();
// 核查情况依照 新的与task status来对应 详情可以查看docs/confirmcheck.md里的对应表 对照表
String situation = getDetailSituation(task);
// 逾期的处理,只在完成的那一步才判断
if (situation.equals("完成") && updateTime.isAfter(endTime)) {
situation = "逾期完成";
}
led.setCheckSituation(situation);
String checkResult = "";
String remark = task.getRemark();
// 核查结果 - 如果省的自查任务,核查情况是完成了之后,核查结果就是无误
String unitName = detailRepo.findById(task.getBillId()).get().getCheckUnit();
Integer areaType = auService.findOne(AuExample.UnitName, unitName).getType();
if (!situation.contains("完成")) {
checkResult = "无";
} else if (comSituation == 10) {
// 再判断一下 是2级结构(检查统计)还是3级结构(核查统计)
Integer rootId = taskService.findByTaskId(task.getParentTaskId()).getParentTaskId();
boolean isTwoLevel = rootId == null || rootId == 0;
// 2级结构 - 检查统计 发起人单位是省,结果为等待省审核,发起人是市则是无
if (isTwoLevel) {
Integer startUnitId = userService.findById(task.getCreateUserId()).getUnitsId();
if (startUnitId != 1) {
checkResult = "无";
} else {
//根据detail userC为省且任务状态是完结状态时 变为无误 否则是等待省审核
Integer detailId = task.getBillId();
Integer userCId = detailRepo.findById(detailId).get().getUserCId();
if (task.getBillStatus().equals(END.id) && userIsProv(userCId)) {
checkResult = CHECK_RESULT_DONE;
} else {
checkResult = CHECK_RESULT_WAIT;
}
}
} else {
checkResult = CHECK_RESULT_WAIT;
}
} else if (comSituation == 12) {
checkResult = CHECK_RESULT_DONE;
} else if (comSituation == 13) {
int redoTime = 1;
if (Objects.nonNull(remark) && remark.contains("ROLLBACK")) {
redoTime = Integer.valueOf(remark.split("-")[1]);
}
checkResult = redoTime + "次未通过";
} else if (comSituation == 0) {
if (task.getBillStatus().equals(END.id)) {
int redoTime = 1;
if (Objects.nonNull(remark) && remark.contains("ROLLBACK")) {
redoTime = Integer.valueOf(remark.split("-")[1]);
}
checkResult = redoTime + "次未通过";
} else {
checkResult = CHECK_RESULT_WAIT;
}
} else {
checkResult = "状态异常";
}
led.setCheckResult(checkResult);
led.setCheckUnit(cas.getAreaName() + "局");
return led;
}
/**
* 判断用户是否是省级用户
*
* @return
*/
private boolean userIsProv(Integer userId) {
if (Objects.isNull(userId) || userId == 0) {
return false;
}
Integer unitsId = userService.findById(userId).getUnitsId();
Integer level = unitsRepo.findById(unitsId).get().getLevel();
return level == 1;
}
private String getUnitDateString(Units units, String title) {
return "[" + units.getUnitDesc() + "]" + title;
}
/**
* 尝试自动完结检查任务(市/省的)
* 1. 当且仅当该检查任务的状态等于@link{CHECK_EXAM_STAT_1}时且其下的所有子任务均为完结状态,自动推进
*
* @param exam的taskId
*/
private void advanceExamTask(Integer examTaskId) {
TaskBto parentTask = taskService.findByTaskId(examTaskId);
if (parentTask.getBillStatus().equals(CHECK_EXAM_STAT_1.id) && taskService.TaskTreeIsOver(examTaskId)) {
log.info("[核查模块] 检测到task id = {}的检查任务已经可以自动推进了,自动推进至下一步", examTaskId);
statConfirm(parentTask.getBillId());
}
}
/**
* 关闭某个节点,该节点下必须没有子节点树了
* <p>1.将该任务进度推进至9999</>
* <p>2.手动补充终结日志</>
* <p>3.将终结信息添加阅知列表里面</>
*
* @param node
*/
private void shutDownNode(Task node) {
log.info("[核查模块] 终止任务-正在关闭 task id = {} 的任务节点");
// 如果是核查类捡点,抛出异常
if (node.getCustomInfo().equals("check") || node.getCustomInfo().equals("exam")) {
throw new ApiException("关闭节点里不处理核查/核查节点...,你提供的任务节点id = " + node.getId());
}
// 其余节点,执行关闭策略
// 1.将该任务进度推进至9999
TaskBto nodeBto = node.parse2Bto();
taskService.moveToEnd(nodeBto);
supplyLogMsg(node);
log.info("[核查模块] 终止任务-task id = {} 成功关闭");
}
/**
* 补充任务的终结日志与阅知信息
*
* @param node
*/
private void supplyLogMsg(Task node) {
// 手动补充终结日志
String adminUser = authenticationUtils.getAuthentication().getCurrentUserInfo().getName();
String shutDownMsg = String.format("专管员[%s]终止了该任务", adminUser);
TaskLogBto taskLog = new TaskLogBto(node.getId(), shutDownMsg);
taskLogService.addLog(taskLog);
// 添加阅知信息
List<Integer> involveUserIds = node.parse2Bto().getInvolveUserIdList();
int lastUserId = involveUserIds.get(involveUserIds.size() - 1) == null ? 0 : involveUserIds.get(involveUserIds.size() - 1);
List<Integer> msgUserIds;
if (lastUserId == 0) {
msgUserIds = userService.findByUniteId(node.getOwnUnit()).stream()
.map(UserShenRe::getUserId)
.collect(toList());
} else {
msgUserIds = new ArrayList<>(lastUserId);
}
MessageBto msgBto = new MessageBto(node.getId(), node.getBusinessType(), shutDownMsg, msgUserIds);
messageService.add(msgBto);
}
/**
* 将detail里的detailString里的检查数字该为指定数值
*
* @param detail
* @param number
*/
private DeviceCheckDetail setDetailCheckNumber(DeviceCheckDetail detail, Integer number) {
String detailString = detail.getCheckDetail();
String updatedString = Arrays.stream(detailString.split(","))
.map(s -> s.split("-")[0] + "-" + number)
.collect(joining(","));
detail.setCheckDetail(updatedString);
return detail;
}
/**
* 省对区审查 未通过的 逻辑
*
* @param id detail Id
* @return
*/
private ResponseEntity provAuitNotPassed(Integer id) {
//1. bill单的自查将百位数变为3
DeviceCheckDetail detail = detailRepo.findById(id).get();
String detailString = detail.getCheckDetail();
String initalDetail = Arrays.stream(detailString.split(","))
.map(s -> s.split("-")[0] + "-" + 119)
.collect(joining(","));
String updateDetail = changeHunds(detailString, 3);
detailRepo.updateCheckDetail(id, updateDetail, "", 0, 0, 0);
//2. 当前任务结束,开启一个新的 退回任务(连带一个新的detail)
TaskBto currentTask = taskService.get(id, CONFIRM_CHECK_DETAIL.id);
String remark = currentTask.getRemark();
if (Objects.nonNull(remark) && remark.contains("ROLLBACK")) {
Integer times = Integer.valueOf(remark.split("-")[1]);
remark = "ROLLBACK-" + ++times;
} else {
remark = "ROLLBACK-1";
}
currentTask.setRemark(remark);
TaskBto newTask = currentTask.toDo().copy().parse2Bto();
currentTask.setCustomInfo(currentTask.getCustomInfo());
taskService.moveToEnd(currentTask);
// 创建新的detail 新的detail会在B的时候加入,所以老的stat要去除掉
DeviceCheckDetail cDetail = detail.copyWithoutId();
cDetail.setId(null);
cDetail.setCheckDetail(initalDetail);
cDetail.setCheckFiles("");
cDetail.setCheckFileList(Lists.newArrayList());
cDetail = detailRepo.save(cDetail);
// 创建新的任务(被拒绝的自查单位如果是区则是140状态,否则是160状态 )
String unitName = cDetail.getCheckUnit();
Integer level = unitsRepo.findByName(unitName).getLevel();
Integer initStatusId = 0;
if (level == 3) {
initStatusId = CHECK_DETAIL_REGION_0.id;
} else {
initStatusId = CHECK_DETAIL_CITY_0.id;
}
newTask.setBillStatus(initStatusId);
newTask.setBillId(cDetail.getId());
newTask.setId(0);
newTask.setCustomInfo(newTask.getCustomInfo());
newTask.getInvolveUserIdList().add(0);
newTask.setCurrentPoint(newTask.getInvolveUserIdList().size() - 1);
// 尝试从老任务中获取重做次数 - 新任务老任务都需要更新remark
newTask.setRemark(remark);
log.info("[核查模块] 省回退操作中... 任务remark = {}", remark);
newTask.setRemark(remark);
taskService.start(newTask);
//3. 在stat的remark中追加信息 - 找到currentTask在其中的顺位
TaskBto fatherTask = taskService.get(currentTask.getParentTaskId());
List<Task> childTask = taskRepo.findAllByParentTaskId(fatherTask.getId());
int pos = 0;
for (int i = 0; i < childTask.size(); i++) {
if (childTask.get(i).getId().equals(currentTask.getId())) {
log.info("[核查模块] 记录remark的pos位置 = {}", i);
}
}
DeviceCheckStat dcs = statRepo.findById(fatherTask.getBillId()).get();
String[] groups = dcs.getRemark().split("\\|");
String pading = groups[pos];
dcs.setRemark(dcs.getRemark() + "|" + pading);
log.info("[核查模块] 补充remark = {}", pading);
// 老的stat要去除掉对应areaName的数据
removeDetailFromDcs(detail, dcs);
//4.父级任务变为进行中 如果父级是核查,变成111,如果父级是检查,变成131
if (fatherTask.getCustomInfo().contains("exam")) {
fatherTask.setBillStatus(CHECK_EXAM_STAT_1.id);
} else if (fatherTask.getCustomInfo().contains("check")) {
fatherTask.setBillStatus(CHECK_STAT_1.id);
}
taskRepo.save(fatherTask.toDo());
return ResponseEntity.ok(new ResultObj<>("回退操作成功!"));
}
/**
* 省对区审查通过的逻辑
*
* @param id detail Id
* @return
*/
private ResponseEntity provAuditPass(Integer id) {
//将自查的情况的百位数全部替换成2
DeviceCheckDetail detail = detailRepo.findById(id).get();
String updatedString = changeHunds(detail.getCheckDetail(), 2);
detail.setCheckDetail(updatedString);
detail.setUserCId(authenticationUtils.getAuthentication().getCurrentUserInfo().getUserId());
log.info("[核查模块] 审核通过 - 更新后的detailString形如 {}", updatedString.split(",")[0]);
detailRepo.save(detail);
//将对应stat中地区的comProgress 改为 2 comsitution 改为12
String areaName = auService.findOne(AuExample.UnitName, detail.getCheckUnit()).getName();
TaskBto currentTask = taskService.get(id, CONFIRM_CHECK_DETAIL.id);
TaskBto fatherTask = taskService.get(currentTask.getParentTaskId());
DeviceCheckStat dcs = statRepo.findById(fatherTask.getBillId()).get();
CheckStatVo csv = transUtil.checkStatDo2Vo(dcs);
for (CheckDeviceStatVo vo : csv.getDeviceStatVoList()) {
for (CheckAreaStatVo av : vo.getAreaStatList()) {
if (av.getAreaName().equals(areaName)) {
log.info("[核查模块] 审核通过 - 地区 = {} 的统计数据在统计信息中被成功修改了", areaName);
av.auditPassed();
}
}
}
return ResponseEntity.ok(new ResultObj<>("审核通过!"));
}
private void removeDetailFromDcs(DeviceCheckDetail detail, DeviceCheckStat dcs) {
String areaName = auService.findOne(AuExample.UnitName, detail.getCheckUnit()).getName();
CheckStatVo csv = transUtil.checkStatDo2Vo(dcs);
for (CheckDeviceStatVo vo : csv.getDeviceStatVoList()) {
List<CheckAreaStatVo> filterList = vo.getAreaStatList().stream()
.filter(casv -> !casv.getAreaName().equals(areaName)).collect(toList());
if (filterList.size() != vo.getAreaStatList().size()) {
log.info("[核查模块] 回退操作-将退回的数据从统计中去除了.");
vo.setAreaStatList(filterList);
}
}
statRepo.save(csv.toDo());
}
/**
* 将detailString里的百位数改为指定数字
* *
* @param detailString 要更改的自查详情字符串 * @param detailString 要更改的自查详情字符串
* @param value 想要改成的数字 * @param value 想要改成的数字
...@@ -1870,112 +2001,6 @@ public class DeviceCheckController { ...@@ -1870,112 +2001,6 @@ public class DeviceCheckController {
} }
/**
* @param taskId 待办任务id
* @param statId 市级统计的STAT ID
* @return
*/
@ApiOperation(value = "跟踪任务待办办结确认")
@PostMapping("/stat/done")
public ResponseEntity confirmDone(@RequestParam int taskId, @RequestParam int statId) {
log.info("[核查模块] 正在进行办结任务确认,任务id为 : {}", taskId);
TaskBto cityDoneTask = taskService.get(taskId);
//市的task 且statId保持一致 省待办 需要的是 市的统计taskId
Specification<Task> pred = Specifications.<Task>and()
.eq("billId", statId)
.eq("businessType", CONFIRM_CHECK_STAT.id)
.build();
// 找到child任务 -> 市级任务 如果是2级的则直接找自己
List<Task> tasks = taskRepo.findAll(pred);
Task cityTask = tasks.stream()
.filter(task -> task.getParentTaskId() != 0 && task.getParentTaskId() != null)
.findFirst()
.orElse(tasks.get(0));
// 如果没有父统计TASK 则证明是两级
boolean doubleLevel = cityTask.getParentTaskId() == 0 || cityTask.getParentTaskId() == null;
if (doubleLevel) {
log.info("[核查模块] 办结确认两级检查任务");
} else {
log.info("[核查模块] 办结确认三级检查任务");
//1.累加数据 累加市级数据数据到省级
CheckStatVo cityStat = transUtil.checkStatDo2Vo(statRepo.findById(statId).get());
Integer provStatId = taskService.get(cityTask.getParentTaskId()).getBillId();
CheckStatVo provinceStat = transUtil.checkStatDo2Vo(statRepo.findById(provStatId).get());
String cityName = areaCache.findById(unitsRepo.findAreaId(cityTask.getOwnUnit())).getName();
// 将区级信息合并到市中
List<CheckDeviceStatVo> mergedVo = cityStat.getDeviceStatVoList().stream()
.map(vo -> vo.combine(cityName, cityStat.getId()))
.collect(toList());
// 如果是第一个市,则替换,否则累加
boolean firstCity = taskService.TaskTreeIsStart(cityTask.getParentTaskId(), true);
if (firstCity) {
provinceStat.setDeviceStatVoList(mergedVo);
log.info("[核查模块] 检测到该任务的合并状态为第一个市统计任务,因此直接替换省级统计数据");
} else {
provinceStat.cleanReduce(mergedVo);
log.info("[核查模块] 数据累加成功");
}
DeviceCheckStat dcs = provinceStat.toDo();
statRepo.save(dcs);
}
//2.办结待办
taskService.moveToEnd(cityDoneTask);
//3.如果所有省级的子任务都完成了
boolean over = taskService.TaskTreeIsOver(cityTask.getParentTaskId());
if (over) {
log.info("[核查模块] 所有的省级子任务都完成了,将省统计任务变为待办");
TaskBto provTask = taskService.get(cityTask.getParentTaskId());
provTask.getInvolveUserIdList().add(0);
provTask.setCurrentPoint(provTask.getCurrentPoint() + 1);
taskService.update(provTask);
}
log.info("[核查模块] 办结统计待办操作成功");
return ResponseEntity.ok(new ResultObj<>("办结统计待办确认完毕"));
}
/**
* @param statId 统计账单主键id
*/
@ApiOperation(value = "统计数据确认")
@PostMapping("/stat/verify")
public ResponseEntity<ResultObj> statConfirm(@RequestParam int statId) {
log.info("[核查模块] 正在进行统计数据确认,统计账单id为 : {}", statId);
//将当前的统计task办结
TaskBto currentTask = taskService.get(statId, CONFIRM_CHECK_STAT.id);
currentTask = taskService.moveToEnd(currentTask);
Integer parentTaskId = currentTask.getParentTaskId();
boolean hasParent = parentTaskId != 0;
//尝试寻找老的市办结任务,如果有的话就删除加END
//5.需要将上一次市的确认任务给清理掉 统计确认任务关联的是statId 找到billId -> exam Task ->
// 父级的父级,就是省的任务,然后子child里名字包含 统计数据确认任务 的任务给 END 吧
Map<Integer, List<Task>> doneTaskList = taskRepo.findAllByParentTaskId(parentTaskId)
.stream()
.filter(task -> task.getTitle().contains("统计数据确认任务"))
.collect(groupingBy(Task::getBillId));
List<Task> existsDone = doneTaskList.get(statId);
if (Objects.nonNull(existsDone)) {
for (Task d : existsDone) {
log.info("[核查模块] 发现了id = {}市的重复的统计确认任务,将其完结并剔除整个树节点", d.getId());
d.setParentTaskId(0);
taskService.moveToEnd(d.parse2Bto());
}
}
// 停止创建省办结任务
log.info("[核查模块] 统计数据确认操作成功");
return ResponseEntity.ok(new ResultObj<>("统计数据确认完毕"));
}
/** /**
* 任务结束后需要将当前城市的统计信息汇总上 * 任务结束后需要将当前城市的统计信息汇总上
* *
......
...@@ -145,16 +145,6 @@ public class ObjTransUtil { ...@@ -145,16 +145,6 @@ public class ObjTransUtil {
List<Task> childTask = taskDao.findAllByParentTaskId(fatherTaskId); List<Task> childTask = taskDao.findAllByParentTaskId(fatherTaskId);
boolean flag = false; boolean flag = false;
boolean confirmTaskisDone = false;
for (Task task : childTask) {
if (task.getTitle().contains("统计数据确认任务")) {
if (task.getBillStatus() != 9999) {
flag = true;
} else {
confirmTaskisDone = true;
}
}
}
// 3/3 -> 统计待确认 -> 省统计任务待完结 // 3/3 -> 统计待确认 -> 省统计任务待完结
...@@ -166,7 +156,7 @@ public class ObjTransUtil { ...@@ -166,7 +156,7 @@ public class ObjTransUtil {
long total = childTask.size(); long total = childTask.size();
long done = childTask.stream() long done = childTask.stream()
.filter(task -> task.getBillStatus().equals(END.id)||task.getBillStatus().equals(REVOKEALLOTTASK.id)) .filter(task -> task.getBillStatus().equals(END.id) || task.getBillStatus().equals(REVOKEALLOTTASK.id))
.count(); .count();
//如果是检查统计的话那么还要看一下他的父节点是不是已经完成了 //如果是检查统计的话那么还要看一下他的父节点是不是已经完成了
...@@ -179,15 +169,11 @@ public class ObjTransUtil { ...@@ -179,15 +169,11 @@ public class ObjTransUtil {
completion = "核查完成待确认"; completion = "核查完成待确认";
} else { } else {
// confirmTaskidDone 为true 代表此时等待最后的father任务 为false代表 flag = false 且isDone为false 代表整个节点里没有确认节点直接完结 // confirmTaskidDone 为true 代表此时等待最后的father任务 为false代表 flag = false 且isDone为false 代表整个节点里没有确认节点直接完结
if (confirmTaskisDone) { if (fatherTask.getBillStatus().equals(END.id) || fatherTask.getBillStatus().equals(REVOKEALLOTTASK.id)) {
if (fatherTask.getBillStatus() == 9999) {
completion = "核查完成"; completion = "核查完成";
} else { } else {
completion = "核查完成待办结"; completion = "核查完成待办结";
} }
} else {
completion = "核查完成";
}
} }
} }
} else { } else {
......
...@@ -36,7 +36,6 @@ public class CacheLibraryServiceImpl implements DeviceLibraryCacheService { ...@@ -36,7 +36,6 @@ public class CacheLibraryServiceImpl implements DeviceLibraryCacheService {
public List<DeviceLibrary> getAllDeviceLibraryList() { public List<DeviceLibrary> getAllDeviceLibraryList() {
long l = System.currentTimeMillis(); long l = System.currentTimeMillis();
List<DeviceLibrary> all = deviceLibraryDao.findAll(); List<DeviceLibrary> all = deviceLibraryDao.findAll();
System.out.println("缓存时间"+(System.currentTimeMillis()-l));
return all; return all;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论