提交 2409a64f authored 作者: Matrix's avatar Matrix

[核查模块]

- 重构了核查统计的逻辑,现在的逻辑更加的清晰简洁,且优化了统计速度 - 优化了核查模块的单元测试部分 - 优化了核查模块一些类的命名以及将时间字段统一为LocalDateTime - 增加了BaseEntity类,用于普通类别的继承 - 将ResultObj对象添加泛型类型 - 增加了AreaUnitService服务,用于频繁的进行单位和地区的查询 - 去除了测试类的事务部分,后面会将单元测试的环境更改为内存数据库
上级 70295f20
package com.tykj.dev.device.confirmcheck.controller;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.tykj.dev.config.GlobalMap;
import com.tykj.dev.config.swagger.AutoDocument;
import com.tykj.dev.device.confirmcheck.entity.cache.AreaCache;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckBillEntity;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckDetailEntity;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckBill;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckDetail;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckStat;
import com.tykj.dev.device.confirmcheck.entity.vo.*;
import com.tykj.dev.device.confirmcheck.repository.DeviceCheckBillDao;
......@@ -34,22 +35,22 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDate;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.tykj.dev.misc.base.BusinessEnum.CONFIRM_CHECK_DETAIL;
import static com.tykj.dev.misc.base.BusinessEnum.CONFIRM_CHECK_STAT;
import static com.tykj.dev.misc.base.StatusEnum.*;
import static com.tykj.dev.misc.utils.TimestampUtil.localDateToDate;
import static java.util.stream.Collectors.*;
/**
* @author dengdiyi
*/
@SuppressWarnings("OptionalGetWithoutIsPresent")
@RestController
@RequestMapping(value = "/check/confirm")
@AutoDocument
......@@ -78,56 +79,57 @@ public class DeviceCheckController {
private TaskService taskService;
@Autowired
private AuthenticationUtils AuthenticationUtils;
@Autowired
private AreaCache areaCache;
@GetMapping("/area/{fatherId}")
@ApiOperation(value = "查询指定区域下的所有区域信息")
public ResponseEntity findAreaUnderId(@PathVariable Integer fatherId) {
return ResponseEntity.ok(new ResultObj(areaRepo.findByFatherId(fatherId)));
public ResponseEntity<ResultObj<List<Area>>> findAreaUnderId(@PathVariable Integer fatherId) {
return ResponseEntity.ok(new ResultObj<>(areaRepo.findByFatherId(fatherId)));
}
@ApiOperation(value = "根据id查询核查统计数据", notes = "可以通过这个接口查询核查统计数据")
@GetMapping("/stat/{id}")
public ResponseEntity findStatById(@PathVariable Integer id) {
public ResponseEntity<ResultObj<CheckStatVo>> findStatById(@PathVariable Integer id) {
//还要查询出所有的
CheckStatVo statVoList = statRepo.findById(id)
.map(transUtil::checkStatDo2Vo)
.orElse(CheckStatVo.empty());
return ResponseEntity.ok(new ResultObj(statVoList));
return ResponseEntity.ok(new ResultObj<>(statVoList));
}
@ApiOperation(value = "根据id查询核查详情数据", notes = "可以通过这个接口查询核查详情数据")
@GetMapping("/detail/{id}")
public ResponseEntity findDetail(@PathVariable Integer id) {
public ResponseEntity<ResultObj<CheckDetailVo>> findDetail(@PathVariable Integer id) {
CheckDetailVo detailVoList = detailRepo.findById(id)
.map(transUtil::CheckDetailDo2Vo)
.orElse(null);
return ResponseEntity.ok(new ResultObj(detailVoList));
return ResponseEntity.ok(new ResultObj<>(detailVoList));
}
@ApiOperation(value = "发起自动核查", notes = "发起自动核查")
@PostMapping("/check/auto")
public ResponseEntity startAutoCheck() {
@PostMapping("/auto")
public ResponseEntity<ResultObj<Map<String, List<Integer>>>> startAutoCheck() {
// 构建返回数据对象
Map<String, List<Integer>> resultIds = new HashMap<>();
resultIds.put("statId", new ArrayList<>());
resultIds.put("detailId", new ArrayList<>());
resultIds.put("taskId", new ArrayList<>());
Map<String, Integer> areaStatIdMap = new HashMap<>();
// 发起省级的统计 - 获得所有的市级单位
List<Units> cityUnits = unitsRepo.findAllByLevel(2);
Units provUnit = unitsRepo.findById(1).get();
String baseTitle = LocalDate.now().getYear() + "年" + (LocalDate.now().getMonthValue() + 1) + "月";
String baseTitle = "自动-" + LocalDate.now().getYear() + "年" + (LocalDate.now().getMonthValue() + 1) + "月";
// 构建省的统计账单
DeviceCheckStat provinceStatDo = initStatData("自动核查",
0,
0,
"自动-" + baseTitle,
provUnit.getName(),
cityUnits);
DeviceCheckStat provStat = statRepo.save(provinceStatDo);
DeviceCheckStat provStatDo = new DeviceCheckStat(
baseTitle + provUnit.getName() + "核查统计单",
"核查统计单",
"系统发起的统计|" + provUnit.getName() + "|" + provUnit.getAreaId());
DeviceCheckStat provStat = statRepo.save(provStatDo);
resultIds.get("statId").add(provStat.getId());
List<DeviceLibrary> deviceList = deviceRepo.findAll();
Map<String, List<DeviceLibrary>> devInLib = deviceList.stream()
......@@ -154,35 +156,35 @@ public class DeviceCheckController {
List<Units> countyUnits = unitsRepo.findByAreaIdIn(areaIds);
// 构建市统账单
DeviceCheckStat cityStatDo = initStatData("系统发起的统计|" + cityUnit.getName() + "|" + cityUnit.getAreaId(),
0,
0,
"自动-" + baseTitle,
cityUnit.getName(),
countyUnits);
DeviceCheckStat cityStatDo = new DeviceCheckStat(
baseTitle + cityUnit.getName() + "核查统计单",
"核查统计单",
"系统发起的统计|" + cityUnit.getName() + "|" + cityUnit.getAreaId()
);
DeviceCheckStat cityStat = statRepo.save(cityStatDo);
cityStatList.add(cityStat);
String cityName = areaCache.findById(cityUnit.getAreaId()).getName();
areaStatIdMap.put(cityName, cityStat.getId());
resultIds.get("statId").add(cityStat.getId());
// 构建市统task 获得id
TaskBto cityStatTask = new Task(CHECK_STAT_0.id, cityUnit.getName() + "自动核查统计", provStatTask.getId(), addNode(provStatTask.getNodeIdDetail(), provinceStatDo.getId()), CONFIRM_CHECK_STAT.id, cityStat.getId(), cityUnit.getUnitId())
TaskBto cityStatTask = new Task(CHECK_STAT_0.id, cityUnit.getName() + "自动核查统计", provStatTask.getId(), addNode(provStatTask.getNodeIdDetail(), provStatDo.getId()), CONFIRM_CHECK_STAT.id, cityStat.getId(), cityUnit.getUnitId())
.parse2Bto();
cityStatTask.setInvolveUserIdList(Lists.newArrayList(-1));
cityStatTask = taskService.start(cityStatTask);
resultIds.get("taskId").add(cityStatTask.getId());
// 构建市自查账单
DeviceCheckDetailEntity cityDetailDo = DeviceCheckDetailEntity.EmptyWithChecker(
DeviceCheckDetail cityDetailDo = DeviceCheckDetail.EmptyWithChecker(
"系统发起的自查|" + cityUnit.getName() + "|" + cityUnit.getAreaId(),
"自动-" + baseTitle,
baseTitle,
0, 0, 0, 0,
cityUnit.getName(),
devInLib.getOrDefault(cityUnit.getName(), new ArrayList<>()),
devNotInLib.getOrDefault(cityUnit.getName(), new ArrayList<>()));
DeviceCheckDetailEntity cityDetail = detailRepo.save(cityDetailDo);
DeviceCheckDetail cityDetail = detailRepo.save(cityDetailDo);
resultIds.get("detailId").add(cityDetail.getId());
String cityName = areaRepo.findNameById(cityUnit.getAreaId());
List<CheckDeviceStatVo> cityStatVoList = deviceList.stream()
.filter(d -> d.getOwnUnit().equals(cityUnit.getName()))
.map(d -> transUtil.device2InitStatVo(d, cityName, cityStat.getId(), cityDetail.getId()))
......@@ -198,14 +200,14 @@ public class DeviceCheckController {
String countyName = areaCache.findById(countyUnit.getAreaId()).getName();
countyAreaNames.add(countyName);
//构建县自查账单
DeviceCheckDetailEntity countyDetailDo = DeviceCheckDetailEntity.EmptyWithChecker(
DeviceCheckDetail countyDetailDo = DeviceCheckDetail.EmptyWithChecker(
"系统发起的自查|" + countyUnit.getName() + "|" + countyUnit.getAreaId(),
"自动" + baseTitle,
baseTitle,
0, 0, 0, 0,
countyUnit.getName(),
devInLib.getOrDefault(countyUnit.getName(), new ArrayList<>()),
devNotInLib.getOrDefault(countyUnit.getName(), new ArrayList<>()));
DeviceCheckDetailEntity countyDetail = detailRepo.save(countyDetailDo);
DeviceCheckDetail countyDetail = detailRepo.save(countyDetailDo);
resultIds.get("detailId").add(countyDetail.getId());
List<CheckDeviceStatVo> countyStatVoList = deviceList.stream()
.filter(d -> d.getOwnUnit().equals(countyUnit.getName()))
......@@ -223,52 +225,35 @@ public class DeviceCheckController {
// 处理JSON INFO 数据
// 对于省统计来说,需要把区的数据累加到市级中去
List<CheckDeviceStatVo> statVoListCopy1 = MapperUtils.mapAll(statVoList, CheckDeviceStatVo.class);
List<CheckDeviceStatVo> statVoListCopy2 = MapperUtils.mapAll(statVoList, CheckDeviceStatVo.class);
List<CheckDeviceStatVo> statVoListCopy1 = MapperUtils.deepClone(statVoList, CheckDeviceStatVo::new);
List<CheckDeviceStatVo> statVoListCopy2 = MapperUtils.deepClone(statVoList, CheckDeviceStatVo::new);
//按照区数据与市数据进行分组 - true->区级装备统计信息 false->市级装备统计是信息
Map<Boolean, List<CheckDeviceStatVo>> regionMap = statVoListCopy1.stream()
.collect(partitioningBy(stat -> countyAreaNames.contains(stat.getAreaStatList().get(0).getAreaName())));
// 区数据
List<CheckDeviceStatVo> countyVo = regionMap.get(true);
// 市级 key model -> areaName -> Vo
Map<String, Map<String, List<CheckDeviceStatVo>>> modAreaMap = regionMap.get(false).stream()
.collect(groupingBy(CheckDeviceStatVo::getDeviceModel,
groupingBy(c -> c.getAreaStatList().get(0).getAreaName())));
// 市级数据
Map<String, CheckDeviceStatVo> map = regionMap.get(false).stream()
.collect(toMap(CheckDeviceStatVo::getDeviceModel, Function.identity()));
//查找区域数据内的父级地区(即市),将数据count数据add进去(通过两次get),将areaList数据也加进去
for (CheckDeviceStatVo v : countyVo) {
String couName = v.getAreaStatList().get(0).getAreaName();
String fatherAreaName = areaCache.findFatherByName(couName).getName();
// 父级地区有的装备数据累加上去
boolean modelExists = modAreaMap.get(v.getDeviceModel()) != null;
if (modelExists) {
modAreaMap.get(v.getDeviceModel())
.computeIfPresent(fatherAreaName, (k2, v2) -> {
log.warn("发现需要堆叠计算的装备,装备信息为: {}", v2);
v2.get(0).addDeviceCount(1);
v2.get(0).getAreaStatList().get(0).addSuppose(1);
v2.get(0).getAreaStatList().addAll(v.getAreaStatList());
return v2;
});
} else {
// 父级地区没有则直接添加区数据进去
Map<String, List<CheckDeviceStatVo>> map = new HashMap<>();
map.put(couName, Lists.newArrayList(v));
modAreaMap.put(v.getDeviceModel(), map);
}
String cityName = areaCache.findFatherByName(couName).getName();
//把相同型号的区级的数据merge到市级即可,没有的话改个名加进去
Integer cityStatId = areaStatIdMap.get(cityName);
map.computeIfPresent(v.getDeviceModel(), (k, value) -> value.reduce(v, cityName, cityStatId));
map.putIfAbsent(v.getDeviceModel(), v);
}
//将市级Map里的数据全部取出来展平一层并累加
List<CheckDeviceStatVo> filterVoList = new ArrayList<>();
modAreaMap.forEach((model, v1) -> v1.forEach((name, v2) -> filterVoList.addAll(v2)));
//按照model分组并累加然后再次积累成一个checkDeviceStatVo
List<CheckDeviceStatVo> provStatVoList = new ArrayList<>();
filterVoList.stream()
.collect(Collectors.groupingBy(CheckDeviceStatVo::getDeviceModel, reducing(CheckDeviceStatVo::add)))
.forEach((k, v) -> provStatVoList.add(v.get()));
provStat.setStatInfo(JacksonUtil.toJSon(provStatVoList));
List<CheckDeviceStatVo> filterVoList = new ArrayList<>(map.values());
provStat.setStatInfo(JacksonUtil.toJSon(filterVoList));
statRepo.save(provStat);
// 对于市统计来说,只需要自己本市以及其下地区的数据
for (DeviceCheckStat csd : cityStatList) {
List<String> cityNames = new ArrayList<>();
......@@ -286,14 +271,14 @@ public class DeviceCheckController {
List<CheckDeviceStatVo> cityStatVo = new ArrayList<>();
statVoListCopy2.stream()
.filter(stat -> cityNames.contains(stat.getAreaStatList().get(0).getAreaName()))
.collect(Collectors.groupingBy(CheckDeviceStatVo::getDeviceModel, reducing(CheckDeviceStatVo::add)))
.collect(Collectors.groupingBy(CheckDeviceStatVo::getDeviceModel, reducing(CheckDeviceStatVo::reduce)))
.forEach((k, v) -> cityStatVo.add(v.get()));
csd.setStatInfo(JacksonUtil.toJSon(cityStatVo));
}
statRepo.saveAll(cityStatList);
return ResponseEntity.ok(new ResultObj(resultIds, "自动核查任务发起成功"));
return ResponseEntity.ok(new ResultObj<>(resultIds, "自动核查任务发起成功"));
}
/**
......@@ -305,10 +290,11 @@ public class DeviceCheckController {
* @param billVo 核查发起对象
*/
@ApiOperation(value = "发起手动核查", notes = "手动发起核查,需要指定参数")
@PostMapping("/check/bill")
public ResponseEntity startManualCheck(@RequestBody CheckBillVo billVo) {
@PostMapping("/manual")
public ResponseEntity<ResultObj> startManualCheck(@RequestBody CheckBillVo billVo) {
List<Integer> detailIds = new ArrayList<>();
// 1. 添加发起核查bill记录
DeviceCheckBillEntity billDo = transUtil.checkBillVo2Do(billVo);
DeviceCheckBill billDo = transUtil.checkBillVo2Do(billVo);
billRepo.save(billDo);
// 2 构建发起单位的 统计账单 与 统计任务
......@@ -319,10 +305,10 @@ public class DeviceCheckController {
log.info("[核查模块]发起手动核查,发起单位为{},被查单位为{}", startUnit.getName(), checkedUnitNames);
// 2-1 构建发起单位的 统计账单
DeviceCheckStat provinceCheckStat = initStatData(billVo.getRemark(), billVo.getUserAId(), billVo.getUserBId(), billVo.getCheckTitle(), startUnit.getName(), checkedUnits);
Integer billId = statRepo.save(provinceCheckStat).getId();
DeviceCheckStat provinceCheckStat = initStatData(billVo.getCheckTitle(), billVo.getRemark(), billVo.getUserAId(), billVo.getUserBId(), startUnit.getName(), checkedUnits);
Integer statId = statRepo.save(provinceCheckStat).getId();
// 2-2 构建发起单位的 统计任务
TaskBto provStatTask = new Task(CHECK_STAT_0.id, CONFIRM_CHECK_STAT.name, 0, ".0.", CONFIRM_CHECK_STAT.id, billId, startUnitId)
TaskBto provStatTask = new Task(CHECK_STAT_0.id, CONFIRM_CHECK_STAT.name, 0, ".0.", CONFIRM_CHECK_STAT.id, statId, startUnitId)
.parse2Bto();
provStatTask.getInvolveUserIdList().add(AuthenticationUtils.getAuthentication().getCurrentUserInfo().getUserId());
provStatTask.getInvolveUserIdList().add(-1);
......@@ -343,15 +329,19 @@ public class DeviceCheckController {
// 对每个需要核查的单位构建其detail账单与task
for (Units unit : checkedUnits) {
// 3-1 构建被查单位的 自查账单
DeviceCheckDetailEntity unitDetailDoc = DeviceCheckDetailEntity.EmptyWithChecker(billVo.getRemark(), billVo.getCheckTitle(), billVo.getUserAId(), billVo.getUserBId(), 0, 0, unit.getName(), devInLib.getOrDefault(unit.getName(), new ArrayList<>()), devNotInLib.getOrDefault(unit.getName(), new ArrayList<>()));
DeviceCheckDetailEntity detail = detailRepo.save(unitDetailDoc);
DeviceCheckDetail unitDetailDoc = DeviceCheckDetail.EmptyWithChecker(billVo.getRemark(), billVo.getCheckTitle(), billVo.getUserAId(), billVo.getUserBId(), 0, 0, unit.getName(), devInLib.getOrDefault(unit.getName(), new ArrayList<>()), devNotInLib.getOrDefault(unit.getName(), new ArrayList<>()));
DeviceCheckDetail detail = detailRepo.save(unitDetailDoc);
detailIds.add(detail.getId());
// 3-1 构建被查单位的 自查任务 (根据被查单位的级别来区分是县级状态是市级状态)
TaskBto checkedTask = new TaskBto(CHECK_DETAIL_0.id, "自核查任务", provStatTask.getId(), addNode(provStatTask.getNodeIdDetail(), provStatTask.getId()), CONFIRM_CHECK_DETAIL.id, detail.getId(), unit.getUnitId(), 0);
taskService.start(checkedTask);
}
log.info("[核查模块] {}单位成功发起对 {} 单位的核查任务分发", startUnit.getName(), checkedUnitNames);
return ResponseEntity.ok(new ResultObj(String.format("[核查模块] [%s]单位成功发起对 [%s] 单位的核查任务分发", startUnit.getName(), checkedUnitNames)));
return ResponseEntity.ok(new ResultObj<>(
ImmutableMap.of("statIds", statId, "detailIds", detailIds),
String.format("[核查模块] [%s]单位成功发起对 [%s] 单位的核查任务分发", startUnit.getName(), checkedUnitNames)
));
}
......@@ -365,10 +355,10 @@ public class DeviceCheckController {
*/
@ApiOperation(value = "专管员A核查详情单")
@PutMapping("/detail/A/{id}")
public ResponseEntity checkUserA(@PathVariable Integer id,
@RequestParam int assignUserId,
@RequestParam String checkResult,
@RequestBody DevLibVo devLibVo) {
public ResponseEntity<ResultObj> checkUserA(@PathVariable Integer id,
@RequestParam int assignUserId,
@RequestParam String checkResult,
@RequestBody DevLibVo devLibVo) {
//1. 更新checkDetail
log.info("[核查模块] 专管员A正在进行详情账单核查,且指定下一个审核人B id 为 {}", assignUserId);
String detailString = transUtil.devLib2String(devLibVo.getDevInLibrary(), devLibVo.getDevNotInLibrary());
......@@ -390,23 +380,24 @@ public class DeviceCheckController {
DeviceCheckStat cityStat = statRepo.findById(cityStatId).get();
CheckStatVo cityVo = transUtil.checkStatDo2Vo(cityStat);
cityVo.getDeviceStatVoList()
.forEach(c->c.getAreaStatList().forEach(CheckAreaStatVo::start));
.forEach(c -> c.getAreaStatList().forEach(CheckAreaStatVo::start));
statRepo.save(cityVo.toDo());
//尝试寻找父级的父级
Integer provId = cityTask.getParentTaskId();
if (provId != 0) {
DeviceCheckStat provStat = statRepo.findById(provId).get();
Integer taskProvTaskId = cityTask.getParentTaskId();
if (taskProvTaskId != 0) {
Integer provStatId = taskRepo.findById(taskProvTaskId).get().getBillId();
DeviceCheckStat provStat = statRepo.findById(provStatId).get();
CheckStatVo provVO = transUtil.checkStatDo2Vo(provStat);
provVO.getDeviceStatVoList()
.forEach(c->c.getAreaStatList().forEach(CheckAreaStatVo::start));
.forEach(c -> c.getAreaStatList().forEach(CheckAreaStatVo::start));
statRepo.save(cityVo.toDo());
log.info("[核查模块 检测到是自动核查任务,将省级统计 id = {} 认为开启]",provStat.getId());
log.info("[核查模块 检测到是自动核查任务,将省级统计 id = {} 认为开启]", provStat.getId());
}
TaskBto fatherStatTask = taskService.get(fatherId);
return ResponseEntity.ok(new ResultObj("专管员A操作成功"));
return ResponseEntity.ok(new ResultObj<>("专管员A操作成功"));
}
/**
......@@ -414,13 +405,13 @@ public class DeviceCheckController {
*/
@ApiOperation(value = "专管员B核查详情单")
@PutMapping("/detail/B/{id}")
public ResponseEntity checkUserB(@PathVariable Integer id,
@RequestParam int checkStatus,
@RequestParam(required = false, defaultValue = "0") int checkUserAId,
@RequestParam(required = false, defaultValue = "0") int checkUserBId) {
public ResponseEntity<ResultObj> checkUserB(@PathVariable Integer id,
@RequestParam int checkStatus,
@RequestParam(required = false, defaultValue = "0") int checkUserAId,
@RequestParam(required = false, defaultValue = "0") int checkUserBId) {
log.info("[核查模块] 专管员B正在进行核查操作,核查账单id为 {} ,且审核状态为 : {}", id, checkStatus == 1 ? "通过" : "不通过");
if (checkStatus == 0) {
return ResponseEntity.status(400).body(new ResultObj("checkStatus不应该为0!"));
return ResponseEntity.status(400).body(new ResultObj<>("checkStatus不应该为0!"));
}
//先更新checkUser
......@@ -431,14 +422,14 @@ public class DeviceCheckController {
// 审核通过与不通过的逻辑不同
TaskBto currentTask = taskService.get(id, CONFIRM_CHECK_DETAIL.id);
if (!currentTask.getBillStatus().equals(CHECK_DETAIL_1.id)) {
return ResponseEntity.status(400).body(new ResultObj(String.format("当前任务的状态异常!当前任务状态为 %s , 任务状态应该为 %s", GlobalMap.getStatusEnumMap().get(currentTask.getBillStatus()), CHECK_DETAIL_1.name)));
return ResponseEntity.status(400).body(new ResultObj<>(String.format("当前任务的状态异常!当前任务状态为 %s , 任务状态应该为 %s", GlobalMap.getStatusEnumMap().get(currentTask.getBillStatus()), CHECK_DETAIL_1.name)));
}
if (checkStatus == 1) {
//依据detail账单对应的checkUserId来判断是2流程还是多流程的
DeviceCheckDetailEntity detailDo = detailRepo.findById(id).get();
Integer userAId = detailDo.getCheckUserAId();
Integer userBId = detailDo.getCheckUserBId();
DeviceCheckDetail currentDetail = detailRepo.findById(id).get();
Integer userAId = currentDetail.getCheckUserAId();
Integer userBId = currentDetail.getCheckUserBId();
// 如果是4流程的,则需要指定核查组成员A接任务
detailRepo.updateCheckStatus(id, checkStatus);
......@@ -447,6 +438,8 @@ public class DeviceCheckController {
} else {
// 如果是2流程的,则直接结束该任务
taskService.moveToEnd(currentTask);
summaryDetail(currentTask, currentDetail);
}
} else {
//不通过则回到第一阶段
......@@ -455,68 +448,73 @@ public class DeviceCheckController {
}
log.info("[核查模块] 专管员B操作成功");
return ResponseEntity.ok(new ResultObj("专管B操作成功"));
return ResponseEntity.ok(new ResultObj<>("专管B操作成功"));
}
@ApiOperation(value = "核查组A/B确认核查详情单")
@PutMapping("/detail/C/{id}")
public ResponseEntity checkUserC(@PathVariable Integer id,
@RequestParam boolean pass) {
public ResponseEntity<ResultObj> checkUserC(@PathVariable Integer id,
@RequestParam boolean pass) {
TaskBto currentTask = taskService.get(id, CONFIRM_CHECK_DETAIL.id);
DeviceCheckDetailEntity currentDetail = detailRepo.findById(id).get();
DeviceCheckDetail currentDetail = detailRepo.findById(id).get();
if (pass) {
// 如果当前是第3步(利用余数来判断),则需要指定核查组B的人来接受任务
log.info("[核查模块] C 检查组成员A正在进行核查操作,核查详情账单id为 : {}", id);
if (currentTask.getBillStatus() % 10 == 2) {
log.info("[核查模块] C 检查组成员A正在进行核查操作,核查详情账单id为 : {}", id);
if (!currentTask.getBillStatus().equals(CHECK_DETAIL_2.id)) {
return ResponseEntity.status(400).body(new ResultObj(String.format("当前任务的状态异常!当前任务状态为 %s , 任务状态应该为 %s", GlobalMap.getStatusEnumMap().get(currentTask.getBillStatus()), CHECK_DETAIL_2.name)));
return ResponseEntity.status(400).body(new ResultObj<>(String.format("当前任务的状态异常!当前任务状态为 %s , 任务状态应该为 %s", GlobalMap.getStatusEnumMap().get(currentTask.getBillStatus()), CHECK_DETAIL_2.name)));
}
currentTask = taskService.moveToNext(currentTask, currentDetail.getCheckUserBId());
taskService.moveToNext(currentTask, currentDetail.getCheckUserBId());
log.info("[核查模块] C 操作完毕");
} else if (currentTask.getBillStatus() % 10 == 3) {
}
if (currentTask.getBillStatus() % 10 == 3) {
if (!currentTask.getBillStatus().equals(CHECK_DETAIL_3.id)) {
return ResponseEntity.status(400).body(new ResultObj(String.format("当前任务的状态异常!当前任务状态为 %s , 任务状态应该为 %s", GlobalMap.getStatusEnumMap().get(currentTask.getBillStatus()), CHECK_DETAIL_3.name)));
return ResponseEntity.status(400).body(new ResultObj<>(String.format("当前任务的状态异常!当前任务状态为 %s , 任务状态应该为 %s", GlobalMap.getStatusEnumMap().get(currentTask.getBillStatus()), CHECK_DETAIL_3.name)));
}
// 如果当前是第4步,则直接结束任务,并且进行结果汇总
log.info("[核查模块] D 检查组成员A正在进行核查操作,核查详情账单id为 : {}", id);
currentTask = taskService.moveToEnd(currentTask);
// 任务结束后需要将当前城市的统计信息汇总上去
Units units = unitsRepo.findById(currentTask.getOwnUnit()).get();
int level = units.getLevel();
// 先找到汇总地区的账单id 查询当前detail task 的 父级TASK
Integer fatherTaskId = currentTask.getParentTaskId();
int statId = taskRepo.findBillId(fatherTaskId, CONFIRM_CHECK_STAT.id);
// 获得当前城市的统计信息 以及 要汇总的地区信息 并累加保存
List<CheckDeviceStatVo> addVos = parseStatString2Vo(currentTask, level, currentDetail.getCheckDetail());
CheckStatVo resultVo = transUtil.checkStatDo2Vo(statRepo.findById(statId).get());
resultVo = resultVo.addStatList(addVos);
statRepo.save(resultVo.toDo());
// 判断地区数据是否均汇总完毕
boolean over = taskService.TaskTreeIsOver(fatherTaskId);
log.info("[核查模块] D 汇总完毕,汇总的账单id为 {}, Task id为 {}", statId, fatherTaskId);
// 如果汇总完毕则将父级的统计任务推进
if (over) {
TaskBto fatherTask = taskService.get(fatherTaskId);
//如果上一个id是-1 则证明是所有人的跟踪统计,即自动核查,那么下一步推进到所有人的待办
Integer lastUserId = fatherTask.getLastUserId() == -1 ? 0 : fatherTask.getLastUserId();
TaskBto statTask = taskService.moveToNext(fatherTask, lastUserId);
}
summaryDetail(currentTask, currentDetail);
log.info("[核查模块] D 操作完毕");
}
} else {
// 如果没通过则返回第1步
StatusEnum firstStatus = getFirstStatus(currentTask.getBillStatus());
currentTask = taskService.moveToSpecial(currentTask, firstStatus, currentTask.getFirstUserId());
taskService.moveToSpecial(currentTask, firstStatus, currentTask.getFirstUserId());
}
return ResponseEntity.ok(new ResultObj("操作成功"));
return ResponseEntity.ok(new ResultObj<>("操作成功"));
}
private void summaryDetail(TaskBto currentTask, DeviceCheckDetail currentDetail) {
log.info("[核查模块] 正在进行数据汇总");
// 任务结束后需要将当前城市的统计信息汇总上去()
Units units = unitsRepo.findById(currentTask.getOwnUnit()).get();
int level = units.getLevel();
// 先找到汇总地区的账单id 查询当前detail task 的 父级TASK
Integer fatherTaskId = currentTask.getParentTaskId();
int statId = taskRepo.findBillId(fatherTaskId, CONFIRM_CHECK_STAT.id);
// 获得当前城市的统计信息 以及 要汇总的地区信息 并累加保存
List<CheckDeviceStatVo> addVos = parseStatString2Vo(currentTask, level, currentDetail.getCheckDetail());
CheckStatVo resultVo = transUtil.checkStatDo2Vo(statRepo.findById(statId).get());
resultVo = resultVo.cleanReduce(addVos);
statRepo.save(resultVo.toDo());
// 判断地区数据是否均汇总完毕
boolean over = taskService.TaskTreeIsOver(fatherTaskId);
// 如果汇总完毕则将父级的统计任务推进
if (over) {
TaskBto fatherTask = taskService.get(fatherTaskId);
//如果上一个id是-1 则证明是所有人的跟踪统计,即自动核查,那么下一步推进到所有人的待办
Integer lastUserId = fatherTask.getLastUserId() == -1 ? 0 : fatherTask.getLastUserId();
taskService.moveToNext(fatherTask, lastUserId);
}
log.info("[核查模块] 数据汇总完毕");
}
......@@ -525,7 +523,7 @@ public class DeviceCheckController {
*/
@ApiOperation(value = "统计数据确认")
@PostMapping("/stat/verify")
public ResponseEntity statConfirm(@RequestParam int statId) {
public ResponseEntity<ResultObj> statConfirm(@RequestParam int statId) {
log.info("[核查模块] 正在进行统计数据确认,统计账单id为 : {}", statId);
//将当前的统计task完结
TaskBto currentTask = taskService.get(statId, CONFIRM_CHECK_STAT.id);
......@@ -535,11 +533,16 @@ public class DeviceCheckController {
Integer parentTaskId = currentTask.getParentTaskId();
boolean hasParent = parentTaskId != 0;
if (hasParent) {
// 累加当前地区数据
// 累加当前地区数据到上级(省级)
TaskBto parentTask = taskService.get(parentTaskId);
CheckStatVo cityStat = transUtil.checkStatDo2Vo(statRepo.findById(statId).get());
CheckStatVo provinceStat = transUtil.checkStatDo2Vo(statRepo.findById(parentTask.getBillId()).get());
provinceStat.addStatList(cityStat.getDeviceStatVoList());
String cityName = areaCache.findById(unitsRepo.findAreaId(currentTask.getOwnUnit())).getName();
// 将区级信息合并到市中
List<CheckDeviceStatVo> mergedVo = cityStat.getDeviceStatVoList().stream()
.map(vo -> vo.combine(cityName, cityStat.getId()))
.collect(toList());
provinceStat.cleanReduce(mergedVo);
statRepo.save(provinceStat.toDo());
// 如果所有子地区统计任务都已经完结,则推进父地区统计任务进度
boolean allOver = taskService.TaskTreeIsOver(parentTaskId);
......@@ -550,7 +553,7 @@ public class DeviceCheckController {
}
log.info("[核查模块] 统计数据确认操作成功");
return ResponseEntity.ok(new ResultObj("统计数据确认完毕"));
return ResponseEntity.ok(new ResultObj<>("统计数据确认完毕"));
}
......@@ -609,52 +612,37 @@ public class DeviceCheckController {
* 构建初始化核查统计数据
* 依据不同地区装备的在库情况构造出舒适化的统计数据出来
*
* @param title 标题
* @param remark 备注
* @param checkAId 核查组成员A id
* @param checkBId 核查组成员B id
* @param startUnitName 发起核查的单位名
* @param unitsList 被核查单位列表
* @return 一份初始化好统计数据(没有向上合并 , 只做了同级地区数据合并)的核查统计单
*/
private DeviceCheckStat initStatData(String remark, Integer checkUserAId, Integer checkUserBId, String checkTitle, String startUnitName, List<Units> unitsList) {
private DeviceCheckStat initStatData(String title, String remark, Integer checkAId, Integer checkBId, String startUnitName, List<Units> unitsList) {
//获得要被统计的单位名列表
List<String> unitNameList = unitsList.stream().map(Units::getName).collect(toList());
Map<String, List<DeviceLibrary>> modelMap = deviceRepo.findAll()
List<String> unitNameList = unitsList.stream()
.map(Units::getName)
.collect(toList());
Collection<CheckDeviceStatVo> statVos = deviceRepo.findAll()
.stream()
.collect(groupingBy(DeviceLibrary::getModel));
//查询所有装备-按照型号分组-遍历每一组型号的装备,过滤出所属在指定单位的装备,并按照单位名称分组
List<CheckDeviceStatVo> checkDeviceStatVos = new ArrayList<>();
modelMap.forEach((model, deviceModelList) -> {
//按照市级区域分组
Map<String, List<DeviceLibrary>> unitMap = deviceModelList.stream()
.filter(device -> unitNameList.contains(device.getOwnUnit()))
.collect(groupingBy(DeviceLibrary::getOwnUnit));
List<CheckAreaStatVo> areaStatVoList = new ArrayList<>();
// 遍历每个地区的该型号的装备 -> 构造出该地区的该型号的初始数据
unitMap.forEach((unitName, devices) -> {
//unitName map to area
int areaId = unitsRepo.findAreaIdByName(unitName);
String areaName = areaRepo.findNameById(areaId);
areaStatVoList.add(new CheckAreaStatVo(areaName, 0, devices.size(), 0, 0, 0, 0));
});
//构造出各型号装备的list - 如果该型号的装备在所有地区都没有,那么就不添加这条数据
if (!CollectionUtils.isEmpty(areaStatVoList)) {
checkDeviceStatVos.add(new CheckDeviceStatVo(model, deviceModelList.get(0).getName(), deviceModelList.size(), areaStatVoList));
}
});
.filter(dev -> unitNameList.contains(dev.getOwnUnit()))
.map(transUtil::device2InitStatVo)
.collect(toMap(CheckDeviceStatVo::getDeviceModel, Function.identity(), CheckDeviceStatVo::reduce))
.values();
//构造最终数据
LocalDate startTime = LocalDate.now();
LocalDate endTime = startTime.plusMonths(1);
return new CheckStatVo(
remark,
checkUserAId,
checkUserBId,
null,
checkTitle + startUnitName + "核查统计单",
startUnitName + "待核查装备统计",
localDateToDate(startTime),
localDateToDate(endTime),
checkDeviceStatVos).toDo();
return new DeviceCheckStat(title,
startUnitName + "待核查装备统计单",
JacksonUtil.toJSon(new ArrayList<>(statVos)),
checkAId,
checkBId,
remark);
}
private String addNode(String originalNode, Integer fatherId) {
......
package com.tykj.dev.device.confirmcheck.entity.domain;
import com.tykj.dev.misc.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
......@@ -18,98 +20,53 @@ import java.util.Date;
/**
* entity class for device_check_bill
* 装备核查账单
* @author matrix
*/
@Data
@Entity
@EntityListeners(AuditingEntityListener.class)
@SQLDelete(sql = "update device_check_bill set delete_tag = 1 where id = ?")
@Where(clause = "delete_tag = 0")
@ApiModel("装备核查账单")
@NoArgsConstructor
@ApiModel("装备核查账单")
@Table(name = "device_check_bill")
public class DeviceCheckBillEntity {
@EqualsAndHashCode(callSuper = true)
@SQLDelete(sql = "update device_check_bill set delete_tag = 1 where id = ?")
public class DeviceCheckBill extends BaseEntity {
/**
* 主键id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ApiModelProperty(name = "主键id")
private Integer id;
/**
* 检查组成员1(省A岗)id
*/
@ApiModelProperty(value = "检查组成员1(省A岗)id")
@Column(name = "userA_id")
private Integer userAId;
/**
* 检查组成员2(省A岗)id
*/
@ApiModelProperty(value = "检查组成员2(省A岗)id")
@Column(name = "userB_id")
private Integer userBId;
/**
* 核查状态(0:决算待审核,1:决算审核失败,2:决算中,3:决算完成)
*/
@ApiModelProperty(value = "核查状态(0:决算待审核,1:决算审核失败,2:决算中,3:决算完成)")
private Integer checkStatus;
/**
* 核查单位主键id(x作为分隔符),例如1x2,意为单位id为1和2的装备核查
*/
@ApiModelProperty(value = "核查单位主键id(x作为分隔符),例如1x2,意为单位id为1和2的装备核查")
private String checkDetail;
/**
* 核查标题
*/
@ApiModelProperty(value = "核查标题")
private String checkTitle;
/**
* 备注
*/
@ApiModelProperty(value = "备注")
private String remark;
/**
* 创建用户id
*/
@CreatedBy
@ApiModelProperty(value = "创建用户id")
private Integer createUserId;
/**
* 创建时间
*/
@CreatedDate
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* 更新用户id
*/
@LastModifiedBy
@ApiModelProperty(value = "更新用户id")
private Integer updateUserId;
/**
* 更新时间
*/
@LastModifiedDate
@ApiModelProperty(value = "更新时间")
private Date updateTime;
/**
* 删除标记(0:未删除,1:已删除)
*/
@ApiModelProperty(value = "删除标记(0:未删除,1:已删除)")
private Integer deleteTag = 0;
public DeviceCheckBillEntity(Integer userAId, Integer userBId, Integer checkStatus, String checkDetail, String checkTitle, Date completeTime, String remark) {
public DeviceCheckBill(Integer userAId, Integer userBId, Integer checkStatus, String checkDetail, String checkTitle, Date completeTime, String remark) {
this.userAId = userAId;
this.userBId = userBId;
this.checkStatus = checkStatus;
......
package com.tykj.dev.device.confirmcheck.entity.domain;
import com.tykj.dev.device.library.subject.domin.DeviceLibrary;
import com.tykj.dev.misc.base.BaseEntity;
import com.tykj.dev.misc.utils.TimestampUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
......@@ -24,24 +25,15 @@ import java.util.stream.Collectors;
/**
* entity class for device_check_detail
* 核查详情
* @author matrix
*/
@Data
@Entity
@EntityListeners(AuditingEntityListener.class)
@SQLDelete(sql = "update device_check_detail set delete_tag = 1 where id = ?")
@Where(clause = "delete_tag = 0")
@ApiModel("核查详情")
@NoArgsConstructor
@Table(name = "device_check_detail")
public class DeviceCheckDetailEntity {
/**
* 主键id
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@ApiModelProperty(name = "主键id")
private Integer id;
public class DeviceCheckDetail extends BaseEntity {
/**
* 检查详情名称
......@@ -113,7 +105,7 @@ public class DeviceCheckDetailEntity {
@ApiModelProperty(value = "核查结果")
private String checkResult;
/**
* 核查详情(装备主键id+核对结果(0缺失1无误2新增,字符-作为状态分隔符字符,作为分隔符))
* 核查详情(装备主键id+核对结果(0缺失1无误2新增3不在库9未检查,字符-作为状态分隔符字符,作为分隔符))
*/
@ApiModelProperty(value = "核查详情(装备主键id+核对结果(0缺失1无误2新增3不在库9未检查,字符x作为分隔符)),例如1-2,2-2,意为主键id为1的装备缺失,为2的无误,为3的新增")
......@@ -124,66 +116,23 @@ public class DeviceCheckDetailEntity {
@ApiModelProperty(value = "核查状态(0:待核查,1:审核失败,2:核查完成)")
private Integer checkStatus;
/**
* 创建用户id
*/
@CreatedBy
@ApiModelProperty(value = "创建用户id")
private Integer createUserId;
/**
* 创建时间
*/
@CreatedDate
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* 更新用户id
*/
@LastModifiedBy
@ApiModelProperty(value = "更新用户id")
private Integer updateUserId;
/**
* 更新时间
*/
@LastModifiedDate
@ApiModelProperty(value = "更新时间")
private Date updateTime;
/**
* 删除标记(0:未删除,1:已删除)
*/
@ApiModelProperty(value = "删除标记(0:未删除,1:已删除)")
private Integer deleteTag = 0;
/**
* 预留字段1
*/
@ApiModelProperty(value = "备注")
private String remark;
/**
* 预留字段2
*/
@ApiModelProperty(value = "预留字段2")
private String var2;
@ApiModelProperty(value = "创建人")
@Transient
private String createUser;
@ApiModelProperty(value = "核查人")
@Transient
private String checkUser;
@ApiModelProperty(value = "审核人")
@Transient
private String confirmUser;
/**
* 用于生成市级的核查详情账单的构造函数
*/
public DeviceCheckDetailEntity(Integer finalCheckId, Date checkTime, String checkUnit, Integer checkingCount, Integer checkedCount, String checkResult, String checkDetail, Integer checkStatus) {
public DeviceCheckDetail(Integer finalCheckId, Date checkTime, String checkUnit, Integer checkingCount, Integer checkedCount, String checkResult, String checkDetail, Integer checkStatus) {
this.finalCheckId = finalCheckId;
this.checkTime = checkTime;
this.checkUnit = checkUnit;
......@@ -197,20 +146,20 @@ public class DeviceCheckDetailEntity {
/**
* 用于生成县级的核查详情账单的构造函数
*/
public DeviceCheckDetailEntity(String title,
Integer finalCheckId,
Integer checkUserAId,
Integer checkUserBId,
Integer userAId,
Integer userBId,
Date checkTime,
String checkUnit,
Integer checkingCount,
Integer checkedCount,
String checkResult,
String checkDetail,
Integer checkStatus,
String remark) {
public DeviceCheckDetail(String title,
Integer finalCheckId,
Integer checkUserAId,
Integer checkUserBId,
Integer userAId,
Integer userBId,
Date checkTime,
String checkUnit,
Integer checkingCount,
Integer checkedCount,
String checkResult,
String checkDetail,
Integer checkStatus,
String remark) {
this.title = title;
this.finalCheckId = finalCheckId;
this.checkUserAId = checkUserAId;
......@@ -233,7 +182,7 @@ public class DeviceCheckDetailEntity {
* @param devNotInLib 所属在,但所在不在本单位的装备集合
* @return 初始化的账单(还没有被人修改过的)
*/
public static DeviceCheckDetailEntity EmptyWithChecker(
public static DeviceCheckDetail EmptyWithChecker(
String remark,
String title,
Integer checkUserA,
......@@ -262,7 +211,7 @@ public class DeviceCheckDetailEntity {
//如果不在库的不为空,则拼接,否则没必要
String checkDetail = StringUtils.isEmpty(badCheckDetail) ? goodCheckDetail : goodCheckDetail + "," + badCheckDetail;
return new DeviceCheckDetailEntity(
return new DeviceCheckDetail(
title + checkUnit + "核查详情单",
0,
checkUserA,
......
package com.tykj.dev.device.confirmcheck.entity.domain;
import com.tykj.dev.misc.base.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
......@@ -13,7 +15,7 @@ import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.*;
import java.util.Date;
import java.time.LocalDateTime;
/**
* DeviceCheckStat.
......@@ -21,21 +23,15 @@ import java.util.Date;
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/8/15 at 7:09 下午
*/
@EqualsAndHashCode(callSuper = true)
@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
@Data
@Entity
@EntityListeners(AuditingEntityListener.class)
@SQLDelete(sql = "update device_check_stat set delete_tag = 1 where id = ?")
@Where(clause = "delete_tag = 0")
@ApiModel("装备核查统计")
@NoArgsConstructor
@Table(name = "device_check_stat")
public class DeviceCheckStat {
/**
* 主键
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
public class DeviceCheckStat extends BaseEntity {
/**
* 父标题
......@@ -50,66 +46,73 @@ public class DeviceCheckStat {
/**
* 开始时间
*/
private Date startTime;
private LocalDateTime startTime;
/**
* 结束时间
*/
private Date endTime;
private LocalDateTime endTime;
/**
* 统计信息以JSON形式存储
*/
private String statInfo;
@Column(name = "check_userA_id")
private Integer checkUserAId;
@Column(name = "check_userB_id")
private Integer checkUserBId;
private String remark;
/**
* 创建用户id
* 检查组成员A
*/
@CreatedBy
@Column(name = "check_userA_id")
private Integer checkUserAId;
@ApiModelProperty(value = "创建用户id")
private Integer createUserId;
/**
* 创建时间
*/
@CreatedDate
@ApiModelProperty(value = "创建时间")
private Date createTime;
/**
* 更新用户id
*/
@LastModifiedBy
@ApiModelProperty(value = "更新用户id")
private Integer updateUserId;
/**
* 更新时间
* 检查组成员B
*/
@LastModifiedDate
@Column(name = "check_userB_id")
private Integer checkUserBId;
@ApiModelProperty(value = "更新时间")
private Date updateTime;
/**
* 删除标记(0:未删除,1:已删除)
* 备注信息
*/
private String remark;
@ApiModelProperty(value = "删除标记(0:未删除,1:已删除)")
private Integer deleteTag = 0;
public DeviceCheckStat(String title, String subtitle, LocalDateTime startTime, LocalDateTime endTime, String statInfo) {
this.title = title;
this.subtitle = subtitle;
this.startTime = startTime;
this.endTime = endTime;
this.statInfo = statInfo;
}
public DeviceCheckStat(String title, String subtitle, Date startTime, Date endTime, String statInfo) {
public DeviceCheckStat(String title, String subtitle, LocalDateTime startTime, LocalDateTime endTime, String statInfo, Integer checkUserAId, Integer checkUserBId, String remark) {
this.title = title;
this.subtitle = subtitle;
this.startTime = startTime;
this.endTime = endTime;
this.statInfo = statInfo;
this.checkUserAId = checkUserAId;
this.checkUserBId = checkUserBId;
this.remark = remark;
}
public DeviceCheckStat(String title, String subtitle, String statInfo, Integer checkUserAId, Integer checkUserBId, String remark) {
this.title = title;
this.subtitle = subtitle;
this.startTime = LocalDateTime.now();
this.endTime = LocalDateTime.now().plusMonths(1);
this.statInfo = statInfo;
this.checkUserAId = checkUserAId;
this.checkUserBId = checkUserBId;
this.remark = remark;
}
public DeviceCheckStat(String title, String subtitle, String remark) {
this.title = title;
this.subtitle = subtitle;
this.startTime = LocalDateTime.now();
this.endTime = LocalDateTime.now().plusMonths(1);
this.statInfo = "";
this.checkUserAId = 0;
this.checkUserBId = 0;
this.remark = remark;
}
}
......@@ -3,6 +3,9 @@ package com.tykj.dev.device.confirmcheck.entity.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import javax.validation.constraints.NotNull;
/**
* CheckAreaStatVo.
......@@ -13,7 +16,8 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Data
public class CheckAreaStatVo {
@Accessors(chain = true)
public class CheckAreaStatVo implements Cloneable {
/**
* 地区名
......@@ -50,23 +54,92 @@ public class CheckAreaStatVo {
*/
private int areaDetailId;
public CheckAreaStatVo(CheckAreaStatVo vo) {
this.areaName = vo.getAreaName();
this.actualCount = vo.getActualCount();
this.supposeCount = vo.getSupposeCount();
this.comProgress = vo.getComProgress();
this.comSituation = vo.getComSituation();
this.areaStatId = vo.getAreaStatId();
this.areaDetailId = vo.getAreaDetailId();
}
public CheckAreaStatVo addSuppose(int supposeCount) {
this.supposeCount += supposeCount;
return this;
}
public CheckAreaStatVo add(CheckAreaStatVo other) {
public void start() {
comProgress = 1;
}
/**
* 将相同地区的统计数据合并
*
* @param other 要合并的地区
* @return 合并后的新地区数据(深度拷贝出来的新对象)
* @throws IllegalArgumentException 在合并的地区名不同或者统计账单id不同时会抛出(初始账单合并除外,即this.detailId=0)
*/
public CheckAreaStatVo reduce(@NotNull CheckAreaStatVo other) {
// 合并的两个对象地区与账单id必须相同
if (!this.areaName.equals(other.areaName) || this.areaStatId != other.areaStatId) {
//初始化账单的话则不用抛出异常,将other的detailId赋予即可
if (this.areaDetailId == 0) {
this.areaDetailId = other.areaStatId;
} else {
throw new IllegalArgumentException(String.format(
"要合并的两个地区统计数据的areaName与areaDetailId必须保持一致," +
"你提供的分别是areaName = %s 与 %s , areaDetailId = %d 与 %d %n",
this.areaName, other.areaName, this.areaStatId, other.areaStatId));
}
}
CheckAreaStatVo reducedVo = new CheckAreaStatVo(this);
reducedVo.supposeCount += other.supposeCount;
reducedVo.actualCount += other.actualCount;
reducedVo.comProgress = other.comProgress;
reducedVo.comSituation = other.comSituation;
return reducedVo;
}
/**
* 将相同地区的统计数据合并(清洁版)
* 只会将实际核查的结果添加进去,并不会重复添加期望指标数字
*
* @param other 要合并的地区
* @return 合并后的新地区数据(深度拷贝出来的新对象)
* @throws IllegalArgumentException 在合并的地区名不同或者统计账单id不同时会抛出(初始账单合并除外,即this.detailId=0)
*/
@SuppressWarnings("DuplicatedCode")
public CheckAreaStatVo cleanReduce(@NotNull CheckAreaStatVo other) {
// 合并的两个对象地区与账单id必须相同
if (!this.areaName.equals(other.areaName) || this.areaStatId != other.areaStatId) {
//初始化账单的话则不用抛出异常,将other的detailId赋予即可
if (this.areaDetailId == 0) {
this.areaDetailId = other.areaStatId;
} else {
throw new IllegalArgumentException(String.format(
"要合并的两个地区统计数据的areaName与areaDetailId必须保持一致," +
"你提供的分别是areaName = %s 与 %s , areaDetailId = %d 与 %d %n",
this.areaName, other.areaName, this.areaStatId, other.areaStatId));
}
}
CheckAreaStatVo reducedVo = new CheckAreaStatVo(this);
reducedVo.actualCount += other.actualCount;
reducedVo.comProgress = other.comProgress;
reducedVo.comSituation = other.comSituation;
return reducedVo;
}
public CheckAreaStatVo combine(CheckAreaStatVo other, Integer cityStatId) {
this.areaName = other.getAreaName();
this.areaStatId = other.getAreaStatId();
this.areaDetailId = other.getAreaDetailId();
this.areaStatId = cityStatId;
this.areaDetailId = 0;
this.supposeCount += other.getSupposeCount();
this.actualCount += other.getActualCount();
this.comProgress = other.getComProgress();
this.comSituation = other.getComSituation();
return this;
}
public void start() {
comProgress = 1;
}
}
package com.tykj.dev.device.confirmcheck.entity.vo;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
......@@ -25,7 +26,7 @@ import static java.util.stream.Collectors.toMap;
@Data
@Builder
@Slf4j
public class CheckDeviceStatVo {
public class CheckDeviceStatVo implements Cloneable {
/**
* 装备型号
......@@ -48,39 +49,131 @@ public class CheckDeviceStatVo {
*/
private List<CheckAreaStatVo> areaStatList;
public CheckDeviceStatVo(CheckDeviceStatVo vo) {
this.deviceModel = vo.getDeviceModel();
this.deviceName = vo.getDeviceName();
this.deviceCount = vo.getDeviceCount();
this.areaStatList = new ArrayList<>();
for (CheckAreaStatVo areaStatVo : vo.getAreaStatList()) {
this.areaStatList.add(new CheckAreaStatVo(areaStatVo));
}
}
/**
* 增加指定的装备数量
*
* @param count 装备数量
*/
public CheckDeviceStatVo addDeviceCount(int count) {
this.deviceCount += count;
return this;
}
/**
* other的model一定要与本deviceModel相同
* 累加装备统计数据(相同型号),并将其下面各个地区的统计信息合并(次级地区会强制更改为{cityName})
* 多用于装备统计数据中既附带区又附带市的统计信息,想全部合并为市的操作(为了统一给省级单位查看统计数据)
* <li>将所有地区全部改名为市级地区</li>
* <li>合并所有数据</li>
*
* @param other 要合并的装备统计对象
* @param cityName 统一后的地区名称
* @return 合并后的装备统计对象,基于深拷贝的新对象
*/
public CheckDeviceStatVo add(CheckDeviceStatVo other) {
public CheckDeviceStatVo reduce(CheckDeviceStatVo other, String cityName, Integer cityStatId) {
if (!deviceModel.equals(other.deviceModel)) {
throw new IllegalArgumentException("累加的统计信息对象必须是相同型号的装备");
}
CheckDeviceStatVo mergeVo = new CheckDeviceStatVo(this);
mergeVo.deviceCount += other.deviceCount;
//添加地区数据 -> 调用combine 合并地区数据
mergeVo.areaStatList.addAll(other.getAreaStatList());
return mergeVo.combine(cityName, cityStatId);
}
/**
* 将相同型号的不同地区数据合并到一起
*
* @param other 要合并的装备统计信息
* @return 合并后的装备统计信息对相关,基于深拷贝
* @throws IllegalArgumentException 累加的统计信息对象必须是相同型号的装备
*/
public CheckDeviceStatVo reduce(CheckDeviceStatVo other) {
if (!deviceModel.equals(other.getDeviceModel())) {
log.warn("[核查] 合并统计的数据发现装备不统一的情况");
return this;
throw new IllegalArgumentException("累加的统计信息对象必须是相同型号的装备");
}
deviceCount += other.getDeviceCount();
CheckDeviceStatVo mergeVo = new CheckDeviceStatVo(this);
mergeVo.deviceCount += other.deviceCount;
// 如果源地区为空,则直接覆盖掉
if (CollectionUtils.isEmpty(areaStatList)) {
areaStatList = other.getAreaStatList();
mergeVo.areaStatList = other.getAreaStatList();
return mergeVo;
}
Map<String, CheckAreaStatVo> areaMap = areaStatList.stream()
Map<String, CheckAreaStatVo> areaMap = mergeVo.areaStatList.stream()
.collect(toMap(CheckAreaStatVo::getAreaName, Function.identity()));
for (CheckAreaStatVo otherArea : other.getAreaStatList()) {
//如果原来的没有则添加,否则累加
areaMap.putIfAbsent(otherArea.getAreaName(), otherArea);
areaMap.computeIfPresent(otherArea.getAreaName(), (k, v) -> v.add(otherArea));
areaMap.computeIfPresent(otherArea.getAreaName(), (k, v) -> v.reduce(otherArea));
}
areaStatList = new ArrayList<>(areaMap.values());
mergeVo.areaStatList = new ArrayList<>(areaMap.values());
return mergeVo;
}
return this;
/**
* 将相同型号的不同地区数据合并到一起(清洁版)
* 与普通reduce的区别是只会将统计结果合并,不会将统计指标合并,适用于预期结果+实际核查结果类型数据相加
*
* @param other 要合并的装备统计信息
* @return 合并后的装备统计信息对相关,基于深拷贝
* @throws IllegalArgumentException 累加的统计信息对象必须是相同型号的装备
*/
public CheckDeviceStatVo cleanReduce(CheckDeviceStatVo other) {
if (!deviceModel.equals(other.getDeviceModel())) {
throw new IllegalArgumentException("累加的统计信息对象必须是相同型号的装备");
}
CheckDeviceStatVo mergeVo = new CheckDeviceStatVo(this);
// 如果源地区为空,则直接覆盖掉
if (CollectionUtils.isEmpty(areaStatList)) {
mergeVo.areaStatList = other.getAreaStatList();
return mergeVo;
}
Map<String, CheckAreaStatVo> areaMap = mergeVo.areaStatList.stream()
.collect(toMap(CheckAreaStatVo::getAreaName, Function.identity()));
for (CheckAreaStatVo otherArea : other.getAreaStatList()) {
//如果原来的没有则添加,否则累加
areaMap.putIfAbsent(otherArea.getAreaName(), otherArea);
areaMap.computeIfPresent(otherArea.getAreaName(), (k, v) -> v.cleanReduce(otherArea));
}
mergeVo.areaStatList = new ArrayList<>(areaMap.values());
return mergeVo;
}
public CheckDeviceStatVo addDeviceCount(int count) {
this.deviceCount += count;
return this;
/**
* 将当前 {@link CheckDeviceStatVo} 对象里的所有地区数据统一改名并合并数据
*
* @param newAreaName 要更新的地区名称
* @param statId 要重新绑定的stat统计账单id,多为市级的账单统计id
* @return 改名&合并地区数据后的统计对象,基于深拷贝的新对象
*/
public CheckDeviceStatVo combine(String newAreaName, Integer statId) {
CheckDeviceStatVo mergeVo = new CheckDeviceStatVo(this);
CheckAreaStatVo mergedAreaStat = mergeVo.getAreaStatList().stream()
.map(v -> v.setAreaName(newAreaName))
.reduce((vo1, vo2) -> vo1.combine(vo2, statId))
.orElse(new CheckAreaStatVo());
mergeVo.setAreaStatList(Lists.newArrayList(mergedAreaStat));
return mergeVo;
}
}
......@@ -13,6 +13,8 @@ import org.springframework.util.CollectionUtils;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
......@@ -52,17 +54,17 @@ public class CheckStatVo {
* 开始时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
private LocalDateTime startTime;
/**
* 结束时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
private LocalDateTime endTime;
private Date createTime;
private LocalDateTime createTime;
private Date updateTime;
private LocalDateTime updateTime;
private Integer createUserId;
......@@ -84,7 +86,7 @@ public class CheckStatVo {
private List<CheckDeviceStatVo> deviceStatVoList;
public CheckStatVo(String remark, Integer checkUserAId, Integer checkUserBId, Integer id, String title, String subtitle, Date startTime, Date endTime, List<CheckDeviceStatVo> deviceStatVoList) {
public CheckStatVo(String remark, Integer checkUserAId, Integer checkUserBId, Integer id, String title, String subtitle, LocalDateTime startTime, LocalDateTime endTime, List<CheckDeviceStatVo> deviceStatVoList) {
this.checkUserAId = checkUserAId;
this.checkUserBId = checkUserBId;
this.id = id;
......@@ -101,7 +103,7 @@ public class CheckStatVo {
return new CheckStatVo("", 0, 0, 0, "无指定数据", "无指定数据", null, null, emptyList);
}
public CheckStatVo addStatList(List<CheckDeviceStatVo> otherList) {
public CheckStatVo cleanReduce(List<CheckDeviceStatVo> otherList) {
if (CollectionUtils.isEmpty(deviceStatVoList)) {
deviceStatVoList = otherList;
return this;
......@@ -112,12 +114,11 @@ public class CheckStatVo {
//遍历要加入的LIST 如果在源数据map中寻找到了则累加,否则添加进去
for (CheckDeviceStatVo vo : otherList) {
oriModelMap.computeIfPresent(vo.getDeviceModel(), (k, v) -> v.cleanReduce(vo));
oriModelMap.putIfAbsent(vo.getDeviceModel(), vo);
oriModelMap.computeIfPresent(vo.getDeviceModel(), (k, v) -> v.add(vo));
}
deviceStatVoList = new ArrayList<>(oriModelMap.values());
return this;
}
......
......@@ -29,5 +29,8 @@ public class DeviceInLibVo {
private String rfidCardId;
/**
* 0缺失1无误2新增3不在库9未检查
*/
private int proofResult;
}
package com.tykj.dev.device.confirmcheck.repository;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckBillEntity;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckBill;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
/**
* @author dengdiyi
*/
public interface DeviceCheckBillDao extends JpaRepository<DeviceCheckBillEntity, Integer>, JpaSpecificationExecutor<DeviceCheckBillEntity> {
public interface DeviceCheckBillDao extends JpaRepository<DeviceCheckBill, Integer>, JpaSpecificationExecutor<DeviceCheckBill> {
}
package com.tykj.dev.device.confirmcheck.repository;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckDetailEntity;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckDetail;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
......@@ -11,7 +11,7 @@ import org.springframework.transaction.annotation.Transactional;
* @author dengdiyi
*/
@Transactional
public interface DeviceCheckDetailDao extends JpaRepository<DeviceCheckDetailEntity, Integer>, JpaSpecificationExecutor<DeviceCheckDetailEntity> {
public interface DeviceCheckDetailDao extends JpaRepository<DeviceCheckDetail, Integer>, JpaSpecificationExecutor<DeviceCheckDetail> {
/**
* 根据id更新checkDetail
......@@ -20,11 +20,11 @@ public interface DeviceCheckDetailDao extends JpaRepository<DeviceCheckDetailEnt
* @param checkDetail 要更新的检查结果
*/
@Modifying
@Query("update DeviceCheckDetailEntity o set o.checkDetail=?2,o.checkResult = ?3,o.userAId =?4,o.userBId=?5,o.checkedCount=?6 where o.id=?1")
@Query("update DeviceCheckDetail o set o.checkDetail=?2,o.checkResult = ?3,o.userAId =?4,o.userBId=?5,o.checkedCount=?6 where o.id=?1")
void updateCheckDetail(Integer id, String checkDetail, String checkResult, int userAId, int userBId, Integer checkedCount);
@Modifying
@Query("update DeviceCheckDetailEntity o set o.checkStatus=?2 where o.id=?1")
@Query("update DeviceCheckDetail o set o.checkStatus=?2 where o.id=?1")
int updateCheckStatus(int id, int checkStatus);
/**
......@@ -35,6 +35,6 @@ public interface DeviceCheckDetailDao extends JpaRepository<DeviceCheckDetailEnt
* @param checkUserBId 核查组成员B
*/
@Modifying
@Query("update DeviceCheckDetailEntity o set o.checkUserAId =?2,o.checkUserBId=?3 where o.id =?1")
@Query("update DeviceCheckDetail o set o.checkUserAId =?2,o.checkUserBId=?3 where o.id =?1")
void updateCheckUser(int id, int checkUserAId, int checkUserBId);
}
......@@ -3,8 +3,8 @@ package com.tykj.dev.device.confirmcheck.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckBillEntity;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckDetailEntity;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckBill;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckDetail;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckStat;
import com.tykj.dev.device.confirmcheck.entity.vo.*;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
......@@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
......@@ -102,9 +103,9 @@ public class ObjTransUtil {
return initialStat;
}
public DeviceCheckBillEntity checkBillVo2Do(CheckBillVo vo) {
public DeviceCheckBill checkBillVo2Do(CheckBillVo vo) {
ModelMapper modelMapper = BeanHelper.getUserMapper();
DeviceCheckBillEntity billDo = modelMapper.map(vo, DeviceCheckBillEntity.class);
DeviceCheckBill billDo = modelMapper.map(vo, DeviceCheckBill.class);
billDo.setCheckStatus(0);
//areas -> unitIds -> unitStrings
String unitString = vo.getAreaRange().stream()
......@@ -116,9 +117,9 @@ public class ObjTransUtil {
return billDo;
}
public DeviceCheckDetailEntity checkDetailVo2Do(CheckDetailVo detailVo) {
public DeviceCheckDetail checkDetailVo2Do(CheckDetailVo detailVo) {
ModelMapper modelMapper = BeanHelper.getUserMapper();
DeviceCheckDetailEntity detailDo = modelMapper.map(detailVo, DeviceCheckDetailEntity.class);
DeviceCheckDetail detailDo = modelMapper.map(detailVo, DeviceCheckDetail.class);
//将inLib与notInLib 的集合 转化为压缩字符串
String checkDetailString = devLib2String(detailVo.getDevInLibrary(), detailVo.getDevNotInLibrary());
detailDo.setCheckDetail(checkDetailString);
......@@ -145,7 +146,7 @@ public class ObjTransUtil {
}
public CheckDetailVo CheckDetailDo2Vo(DeviceCheckDetailEntity detailDo) {
public CheckDetailVo CheckDetailDo2Vo(DeviceCheckDetail detailDo) {
//查询人物id
Integer checkUserAId = detailDo.getCheckUserAId();
Integer checkUserBId = detailDo.getCheckUserBId();
......@@ -177,8 +178,11 @@ public class ObjTransUtil {
List<DeviceInLibVo> inLibVoList = new ArrayList<>();
List<DeviceNotInLibVo> notInLibVoList = new ArrayList<>();
String checkDetail = detailDo.getCheckDetail();
String[] detailArray = checkDetail.split(",");
for (String detail : detailArray) {
List<String> devCheckList = Lists.newArrayList(checkDetail.split(","));
for (String detail : devCheckList) {
if (StringUtils.isEmpty(detail)) {
continue;
}
String[] array = detail.split("-");
Integer deviceId = Integer.valueOf(array[0]);
int proofResult = Integer.parseInt(array[1]);
......
......@@ -20,11 +20,6 @@
<artifactId>config</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-java8</artifactId>
<version>5.1.0.Final</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.tykj.dev.misc.base;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Where;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;
import java.util.Date;
/**
* BaseEntity.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/9/27 at 1:25 上午
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Where(clause = "delete_tag = 0")
public class BaseEntity {
/**
* 主键id
*/
@Id
@GeneratedValue
private Integer id;
/**
* 创建用户id
*/
@CreatedBy
private Integer createUserId;
/**
* 更新用户id
*/
@LastModifiedBy
private Integer updateUserId;
/**
* 创建时间
*/
@CreatedDate
private LocalDateTime createTime;
/**
* 更新时间
*/
@LastModifiedDate
private LocalDateTime updateTime;
/**
* 删除标记(0:未删除,1:已删除)
*/
private Integer deleteTag = 0;
}
......@@ -13,19 +13,18 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@JsonPropertyOrder(value = {"message","data"})
public class ResultObj {
public class ResultObj<T> {
private Object data;
private T data;
private String message;
public ResultObj(Object o) {
public ResultObj(T o) {
this.data = o;
this.message = "no message";
}
public ResultObj(String m) {
this.message = m;
this.data = new Object();
}
}
......@@ -5,6 +5,7 @@ import org.modelmapper.convention.MatchingStrategies;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
......@@ -64,6 +65,18 @@ public class MapperUtils {
.collect(Collectors.toList());
}
/**
* @param entityList list of entities that needs to be mapped
* @param constructor deep copy constructor
* @param <D> type of objects in result list and entityList
* @return the deepCopy List of entityList
*/
public static <D extends Cloneable> List<D> deepClone(final Collection<D> entityList, Function<D, D> constructor) {
return entityList.stream()
.map(constructor)
.collect(Collectors.toList());
}
/**
* Maps {@code source} to {@code destination}.
*
......
package com.tykj.dev.union;
import cn.hutool.core.util.ArrayUtil;
import com.tykj.dev.config.GlobalMap;
import com.tykj.dev.config.Log;
import com.tykj.dev.config.Param;
import com.tykj.dev.config.LogType;
import com.tykj.dev.device.allot.repository.AllotBillDao;
import com.tykj.dev.device.allot.service.AllotBackBillService;
import com.tykj.dev.device.allot.service.AllotBillService;
import com.tykj.dev.device.allot.subject.domin.AllotBackBill;
import com.tykj.dev.device.allot.subject.domin.AllotBill;
import com.tykj.dev.device.apply.service.DeviceApplyBillService;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckBillEntity;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckDetailEntity;
import com.tykj.dev.device.confirmcheck.entity.domain.DeviceCheckStat;
import com.tykj.dev.device.confirmcheck.repository.DeviceCheckBillDao;
import com.tykj.dev.device.confirmcheck.repository.DeviceCheckDetailDao;
import com.tykj.dev.device.confirmcheck.repository.DeviceCheckStatRepo;
import com.tykj.dev.device.destroy.entity.domain.DeviceDestroyBill;
import com.tykj.dev.device.destroy.service.DeviceDestroyBillService;
import com.tykj.dev.device.library.subject.vo.FileVo;
import com.tykj.dev.device.library.subject.vo.LogVo;
import com.tykj.dev.device.matching.service.MatchingDeviceBillService;
import com.tykj.dev.device.matching.service.MatchingDeviceLibraryService;
import com.tykj.dev.device.matching.subject.domin.MatchingDeviceBill;
import com.tykj.dev.device.packing.service.PackingLibraryService;
import com.tykj.dev.device.packing.subject.domin.PackingLibrary;
import com.tykj.dev.device.repair.repository.RepairBackBillDao;
import com.tykj.dev.device.repair.repository.RepairSendBillDao;
import com.tykj.dev.device.repair.service.RepairBillService;
import com.tykj.dev.device.repair.service.RepairSendBillService;
import com.tykj.dev.device.repair.subject.domin.RepairBackBill;
import com.tykj.dev.device.repair.subject.domin.RepairBill;
import com.tykj.dev.device.repair.subject.domin.RepairSendBill;
import com.tykj.dev.device.retired.entity.domain.DeviceRetiredBill;
import com.tykj.dev.device.retired.service.DeviceRetiredBillService;
import com.tykj.dev.device.selfcheck.service.SelfCheckBillService;
import com.tykj.dev.device.selfcheck.subject.domin.SelfCheckBill;
import com.tykj.dev.device.sendback.entity.domain.SendBackBill;
import com.tykj.dev.device.sendback.repository.SendBackBillDao;
import com.tykj.dev.device.storage.service.StorageBillService;
import com.tykj.dev.device.storage.subject.domin.StorageBill;
......@@ -46,14 +33,10 @@ import com.tykj.dev.device.task.subject.bto.TaskBto;
import com.tykj.dev.device.task.subject.bto.TaskLogBto;
import com.tykj.dev.device.train.dao.TrainThemeDao;
import com.tykj.dev.device.train.dao.WorkHandoverDao;
import com.tykj.dev.device.train.entity.TrainTheme;
import com.tykj.dev.device.train.entity.WorkHandover;
import com.tykj.dev.device.train.service.TrainThemeService;
import com.tykj.dev.device.user.util.UserUtils;
import com.tykj.dev.misc.base.BeanHelper;
import com.tykj.dev.misc.base.StatusEnum;
import com.tykj.dev.misc.utils.SpringUtils;
import com.tykj.dev.rfid.entity.domin.RfidChangeBill;
import com.tykj.dev.rfid.service.RfidChangeBillService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
......@@ -65,7 +48,6 @@ import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
......
package com.tykj.dev.confirmcheck;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.wenhao.jpa.Specifications;
import com.google.common.collect.Lists;
import com.tykj.dev.device.confirmcheck.controller.DeviceCheckController;
import com.tykj.dev.device.confirmcheck.entity.vo.CheckBillVo;
import com.tykj.dev.device.confirmcheck.entity.vo.CheckDetailVo;
import com.tykj.dev.device.confirmcheck.entity.vo.CheckStatVo;
import com.tykj.dev.device.confirmcheck.entity.vo.DevLibVo;
import com.tykj.dev.device.confirmcheck.repository.DeviceCheckDetailDao;
import com.tykj.dev.device.confirmcheck.repository.DeviceCheckStatRepo;
import com.tykj.dev.device.confirmcheck.utils.ObjTransUtil;
import com.tykj.dev.device.library.repository.DeviceLibraryDao;
import com.tykj.dev.device.task.repository.TaskDao;
import com.tykj.dev.device.task.subject.domin.Task;
import com.tykj.dev.misc.base.StatusEnum;
import com.tykj.dev.device.user.base.enums.AuExample;
import com.tykj.dev.device.user.subject.dao.AreaDao;
import com.tykj.dev.device.user.subject.dao.UnitsDao;
import com.tykj.dev.device.user.subject.service.AuService;
import com.tykj.dev.union.BaseTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -24,13 +29,14 @@ import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.RequestBuilder;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
import java.util.stream.StreamSupport;
import static com.tykj.dev.misc.utils.JacksonUtil.toJSon;
import static java.util.stream.Collectors.toList;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
......@@ -46,30 +52,38 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@ActiveProfiles("test")
class DeviceCheckControllerTest extends BaseTest {
private static Task initTask;
@Autowired
protected MockMvc mockMvc;
ObjectMapper objectMapper = new ObjectMapper();
RequestBuilder request;
Integer detailBillId;
String baseUrl = "/check/confirm/detail/";
@Autowired
private DeviceCheckController checkController;
@Autowired
private DeviceCheckDetailDao detailRepo;
@Autowired
private DeviceCheckStatRepo statRepo;
@Autowired
private DeviceLibraryDao deviceRepo;
@Autowired
private AreaDao areaRepo;
@Autowired
private UnitsDao unitsDao;
@Autowired
private TaskDao taskRepo;
@Autowired
private ObjTransUtil transUtil;
@Autowired
private AuService auService;
@Test
void startAutoCheck() throws Exception {
// 测试
RequestBuilder request;
request = post("/check/confirm/check/auto")
request = post("/check/confirm/auto")
.header("Origin", "*");
......@@ -80,16 +94,21 @@ class DeviceCheckControllerTest extends BaseTest {
System.out.println("[测试结果] 自动发起核查任务测试通过,返回结果为 : " +
resultString);
// 测试 生成的数据是否都能正常访问
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(resultString);
StreamSupport
.stream(jsonNode.get("data").get("statId").spliterator(), false)
.map(JsonNode::asInt)
.forEach(statId -> {
//测试访问
checkController.findStatById(statId);
CheckStatVo statRes = checkController.findStatById(statId).getBody().getData();
try {
System.out.println(objectMapper.writeValueAsString(statRes));
} catch (JsonProcessingException e) {
System.out.println("数据转JSON发生异常");
e.printStackTrace();
}
System.out.printf("[数据清理-统计] 删除id为 %d 的统计数据 %n", statId);
statRepo.deleteById(statId);
// statRepo.deleteById(statId);
});
StreamSupport
.stream(jsonNode.get("data").get("detailId").spliterator(), false)
......@@ -98,75 +117,27 @@ class DeviceCheckControllerTest extends BaseTest {
//测试访问
checkController.findDetail(detailId);
System.out.printf("[数据清理-自查] 删除id为 %d 的自查数据 %n", detailId);
detailRepo.deleteById(detailId);
// detailRepo.deleteById(detailId);
});
StreamSupport
.stream(jsonNode.get("data").get("taskId").spliterator(), false)
.map(JsonNode::asInt)
.forEach(taskId -> {
System.out.printf("[数据清理-任务] 删除id为 %d 的任务数据 %n", taskId);
taskRepo.deleteById(taskId);
});
// deleteAutoCheckData(resultString);
}
private void deleteAutoCheckData(String resultString) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(resultString);
StreamSupport
.stream(jsonNode.get("data").get("statId").spliterator(), false)
.map(JsonNode::asInt)
.forEach(statId -> {
System.out.printf("[数据清理-统计] 删除id为 %d 的统计数据 %n", statId);
statRepo.deleteById(statId);
});
StreamSupport
.stream(jsonNode.get("data").get("detailId").spliterator(), false)
.map(JsonNode::asInt)
.forEach(detailId -> {
System.out.printf("[数据清理-自查] 删除id为 %d 的自查数据 %n", detailId);
detailRepo.deleteById(detailId);
});
StreamSupport
.stream(jsonNode.get("data").get("taskId").spliterator(), false)
.map(JsonNode::asInt)
.forEach(taskId -> {
System.out.printf("[数据清理-任务] 删除id为 %d 的任务数据 %n", taskId);
taskRepo.deleteById(taskId);
// taskRepo.deleteById(taskId);
});
}
@Test
void startManualCheck() throws Exception {
CheckBillVo param = new CheckBillVo();
param.setUnitId(1);
param.setAreaRange(Lists.newArrayList(1));
param.setCheckTitle("单元测试手动核查");
param.setRemark("这是一段测试用的数据");
param.setUserAId(1);
param.setUserBId(2);
// 测试
RequestBuilder request;
request = post("/check/confirm/check/bill")
.header("Origin", "*")
.contentType(MediaType.APPLICATION_JSON)
.content(toJSon(param));
mockMvc.perform(request)
.andExpect(status().isOk())
.andDo(mvcResult1 -> System.out.println("[测试结果] 手动发起核查任务测试通过"));
void checkUserA2D() throws Exception {
// checkUserA 接口
Task initTask = taskRepo.findAll(Specifications.<Task>and()
.eq("billStatus", StatusEnum.CHECK_DETAIL_0.id)
.build())
.get(0);
Integer detailBillId = initTask.getBillId();
// initTask = taskRepo.findAll(Specifications.<Task>and()
// .eq("billStatus", StatusEnum.CHECK_DETAIL_0.id)
// .build())
// .get(0);
initTask = taskRepo.findById(676).get();
detailBillId = initTask.getBillId();
CheckDetailVo detailVoList = detailRepo.findById(detailBillId)
.map(transUtil::CheckDetailDo2Vo)
......@@ -174,12 +145,12 @@ class DeviceCheckControllerTest extends BaseTest {
DevLibVo devLibVo = new DevLibVo(detailVoList.getDevInLibrary(), detailVoList.getDevNotInLibrary());
devLibVo.getDevInLibrary().forEach(d -> d.setProofResult(1));
Map<String, String> paramMap = new HashMap<>();
paramMap.put("assignUserId", "2");
paramMap.put("checkResult", "\"检查结果无误\"");
String baseUrl = "/check/confirm/detail/";
String url_a = baseUrl + "A/" + detailBillId;
StringJoiner joiner = new StringJoiner("&", "?", "");
......@@ -202,67 +173,97 @@ class DeviceCheckControllerTest extends BaseTest {
initTask.getId(),
initTask.getBillId())));
// // checkUserB 接口 测试审核通过
// String url_b = baseUrl + "B/" + detailBillId + "?" + "checkStatus=1";
// request = put(url_b)
// .header("Origin", "*");
//
// mockMvc.perform(request)
// .andExpect(status().isOk())
// .andDo(s -> System.out.println(
// String.format("[测试结果] 对任务id=%d的任务执行岗位B详情审核操作成功,审核的详情表id为%d",
// initTask.getId(),
// initTask.getBillId())));
//
// // checkUserC - C 接口 测试审核通过
// String url_c = baseUrl + "C/" + detailBillId + "?" + "pass=1";
// request = put(url_c)
// .header("Origin", "*");
//
// mockMvc.perform(request)
// .andExpect(status().isOk())
// .andDo(s -> System.out.println(
// String.format("[测试结果] 对任务id=%d的任务执行岗位C详情审核操作成功,审核的详情表id为%d",
// initTask.getId(),
// initTask.getBillId())));
//
// // checkUserC - D 接口 测试审核通过
// String url_d = baseUrl + "C/" + detailBillId + "?" + "pass=1";
// request = put(url_c)
// .header("Origin", "*");
//
// mockMvc.perform(request)
// .andExpect(status().isOk())
// .andDo(s -> System.out.println(
// String.format("[测试结果] 对任务id=%d的任务执行岗位D详情审核操作成功,审核的详情表id为%d",
// initTask.getId(),
// initTask.getBillId())));
//
// // 统计数据确认接口
// // 获取父级的billId
// Integer statTaskId = initTask.getParentTaskId();
// Integer statId = taskRepo.findById(statTaskId).get().getBillId();
// String url_verify = "/check/confirm/stat/verify?statId=" + statId;
// request = post(url_verify)
// .header("Origin", "*");
//
// mockMvc.perform(request)
// .andExpect(status().isOk())
// .andDo(s -> System.out.println(
// String.format("[测试结果] 对任务id=%d的任务执行统计数据确认操作成功,审核的数据表id为%d",
// statTaskId,
// statId)));
// 结束之后删除本次建立的数据 包括 task 以及相应的业务表数据
// 删除父级任务
// Task fatherTask = taskRepo.findById(statTaskId).get();
// Integer statBillId = fatherTask.getBillId();
// taskRepo.deleteById(fatherTask.getId());
// statRepo.deleteById(statBillId);
//
// List<Task> childTask = taskRepo.findAllByParentTaskId(statTaskId);
// List<Integer> childTaskIds = childTask.stream().map(Task::getId).collect(toList());
// List<Integer> childBillIds = childTask.stream().map(Task::getBillId).collect(toList());
// checkUserB 接口 测试审核通过
String url_b = baseUrl + "B/" + detailBillId + "?" + "checkStatus=1";
request = put(url_b)
.header("Origin", "*");
mockMvc.perform(request)
.andExpect(status().isOk())
.andDo(s -> System.out.println(
String.format("[测试结果] 对任务id=%d的任务执行岗位B详情审核操作成功,审核的详情表id为%d",
initTask.getId(),
initTask.getBillId())));
// checkUserC - C 接口 测试审核通过
String url_c = baseUrl + "C/" + detailBillId + "?" + "pass=true";
request = put(url_c)
.header("Origin", "*");
mockMvc.perform(request)
.andExpect(status().isOk())
.andDo(s -> System.out.println(
String.format("[测试结果] 对任务id=%d的任务执行岗位C详情审核操作成功,审核的详情表id为%d",
initTask.getId(),
initTask.getBillId())));
// checkUserC - D 接口 测试审核通过
String url_d = baseUrl + "C/" + detailBillId + "?" + "pass=true";
request = put(url_d)
.header("Origin", "*");
mockMvc.perform(request)
.andExpect(status().isOk())
.andDo(s -> System.out.println(
String.format("[测试结果] 对任务id=%d的任务执行岗位D详情审核操作成功,审核的详情表id为%d",
initTask.getId(),
initTask.getBillId())));
}
@Test
void verifyStat() throws Exception {
// 统计数据确认接口
// 获取父级的billId
Integer statTaskId = initTask.getParentTaskId();
Integer statId = taskRepo.findById(statTaskId).get().getBillId();
String url_verify = "/check/confirm/stat/verify?statId=" + statId;
request = post(url_verify)
.header("Origin", "*");
mockMvc.perform(request)
.andExpect(status().isOk())
.andDo(s -> System.out.println(
String.format("[测试结果] 对任务id=%d的任务执行统计数据确认操作成功,审核的数据表id为%d",
statTaskId,
statId)));
}
@Test
void startManualCheck() throws Exception {
CheckBillVo param = new CheckBillVo();
param.setUnitId(1);
List<Integer> checkedUnitIds = Lists.newArrayList(1);
param.setAreaRange(checkedUnitIds);
param.setCheckTitle("单元测试手动核查");
param.setRemark("这是一段测试用的数据");
param.setUserAId(1);
param.setUserBId(2);
// 测试发起核查
request = post("/check/confirm/manual")
.header("Origin", "*")
.contentType(MediaType.APPLICATION_JSON)
.content(toJSon(param));
String content = mockMvc.perform(request)
.andExpect(status().isOk())
.andReturn().getResponse().getContentAsString();
// 检查手动发起核查数据的有效性
// 统计数据是合理的,通过查询查询指定单位的装备的数量来核对deviceCount,supposeCount与suppose
List<Integer> statIds = StreamSupport
.stream(objectMapper.readTree(content).get("data").get("statIds").spliterator(), false)
.map(JsonNode::asInt)
.collect(toList());
// 测试auService
checkedUnitIds.stream()
.map(uid -> auService.findOne(AuExample.UnitId, uid))
.forEach(System.out::println);
}
}
\ No newline at end of file
......@@ -15,6 +15,5 @@ import org.springframework.transaction.annotation.Transactional;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = UnionApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
//@Transactional
public class BaseTest {
}
package com.tykj.dev.device.user.base.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* AuExample.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/9/26 at 8:22 下午
*/
@AllArgsConstructor
@Getter
public enum AuExample {
/**
* 查询条件是area表的name字段
*/
AreaId("id", 1),
/**
* 查询条件是area表的name字段
*/
AreaName("name", 1),
/**
* 查询条件是area表的fatherId字段
*/
AreaFatherId("fatherId", 1),
/**
* 查询条件是unit表的unitId字段
*/
UnitId("unitId", 2),
/**
* 查询条件是unit表的name字段
*/
UnitName("name", 2);
private final String fieldName;
/**
* 1 = 地区 2 = 单位 ,根据type来决定查哪张表
*/
private final int type;
}
......@@ -32,6 +32,8 @@ public interface UnitsDao extends JpaRepository<Units, Integer>, JpaSpecificatio
@Query("select o.areaId from Units o where o.unitId=?1")
int findAreaId(int id);
Units findByAreaIdAndLevel(Integer areaId , Integer level);
Units findByAreaIdAndLevel(Integer areaId, Integer level);
Units findByAreaIdEquals(Integer areaId);
}
......@@ -56,4 +56,8 @@ public class Area {
return mapper.map(this, AreaVo.class);
}
public static Area empty(){
return new Area(0, "不存在的地区", 0, "0", 0);
}
}
package com.tykj.dev.device.user.subject.entity.bto;
import com.google.common.collect.Lists;
import com.tykj.dev.device.user.subject.entity.Area;
import com.tykj.dev.device.user.subject.entity.Units;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* AreaUnit.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/9/26 at 8:11 下午
*/
@Data
@NoArgsConstructor
public class AreaUnit {
private Integer id;
private String name;
private Integer type;
private String orders;
private Integer fatherId;
/**
* 默认等于{@link #unitList}里的第一个元素
*/
private Unit unit;
/**
* 为以后的扩展准备,防止一个地区有多个单位出现
*/
private List<Unit> unitList;
public AreaUnit(Area area, Units units) {
this.id = area.getId();
this.name = area.getName();
this.type = area.getType();
this.orders = area.getOrders();
this.fatherId = area.getFatherId();
this.unit = new Unit(units.getUnitId(), units.getName(), units.getUnitDesc(), units.getCode());
this.unitList = Lists.newArrayList(this.unit);
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class Unit {
private Integer unitId;
private String name;
private String unitDesc;
private String code;
}
}
package com.tykj.dev.device.user.subject.service;
import com.tykj.dev.device.user.base.enums.AuExample;
import com.tykj.dev.device.user.subject.entity.bto.AreaUnit;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* AuService.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/9/26 at 8:28 下午
*/
public interface AuService {
List<AreaUnit> findAll(AuExample example, Object value);
AreaUnit findOne(AuExample example, Object value);
}
package com.tykj.dev.device.user.subject.service.impl;
import com.github.wenhao.jpa.Specifications;
import com.tykj.dev.device.user.base.enums.AuExample;
import com.tykj.dev.device.user.subject.dao.AreaDao;
import com.tykj.dev.device.user.subject.dao.UnitsDao;
import com.tykj.dev.device.user.subject.entity.Area;
import com.tykj.dev.device.user.subject.entity.Units;
import com.tykj.dev.device.user.subject.entity.bto.AreaUnit;
import com.tykj.dev.device.user.subject.service.AuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* AuServiceImpl.
*
* @author Matrix <xhyrzldf@gmail.com>
* @since 2020/9/26 at 8:29 下午
*/
@Service
public class AuServiceImpl implements AuService {
@Autowired
private AreaDao areaRepo;
@Autowired
private UnitsDao unitsRepo;
@Override
public List<AreaUnit> findAll(AuExample example, Object value) {
//解析条件
if (example.getType() == 1) {
Specification<Area> pred = Specifications.<Area>and()
.eq(Objects.nonNull(value), example.getFieldName(), value)
.build();
List<Area> areaList = areaRepo.findAll(pred);
List<AreaUnit> areaUnits = new ArrayList<>();
for (Area area : areaList) {
Units units = unitsRepo.findByAreaId(area.getId()).get(0);
areaUnits.add(new AreaUnit(area, units));
}
return areaUnits;
} else {
Specification<Units> pred = Specifications.<Units>and()
.eq(Objects.nonNull(value), example.getFieldName(), value)
.build();
List<Units> unitList = unitsRepo.findAll(pred);
List<AreaUnit> areaUnits = new ArrayList<>();
for (Units units : unitList) {
Area area = areaRepo.findById(units.getAreaId()).get();
areaUnits.add(new AreaUnit(area, units));
}
return areaUnits;
}
}
@Override
public AreaUnit findOne(AuExample example, Object value) {
if (example.getType() == 1) {
Specification<Area> pred = Specifications.<Area>and()
.eq(Objects.nonNull(value), example.getFieldName(), value)
.build();
Area area = areaRepo.findOne(pred).orElse(Area.empty());
Units units = unitsRepo.findByAreaIdEquals(area.getId());
return new AreaUnit(area, units);
} else {
Specification<Units> pred = Specifications.<Units>and()
.eq(Objects.nonNull(value), example.getFieldName(), value)
.build();
Units units = unitsRepo.findOne(pred).get();
Area area = areaRepo.findById(units.getAreaId()).get();
return new AreaUnit(area, units);
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论