diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ SELECT mts.supplier_no, mts.supplier_name, mts.brief_name, mts.business_content, mts.tax_number, mts.bank_account, mts.bank_name, mts.bank_account_number, mts.postal_code, mts.director, mts.phone, mts.fax, mts.mobile, mts.mailbox, - mts.website, mts.company_country, mts.company_province, mts.company_city, mts.company_area, mts.company_address, + mts.website, mts.company_country, mts.company_country_name, mts.company_province, mts.company_province_name, + mts.company_city, mts.company_city_name, mts.company_area, mts.company_area_name, mts.company_address, mts.invoice_country, mts.invoice_province, mts.invoice_city, mts.invoice_area, mts.invoice_address, mts.business_scope, mts.minio_file_name, mts.approval_status, mts.remark, mts.create_time, mtsp.person_no, mtsp.name, mtsp.department, mtsp.job, mtsp.phone diff --git a/casic-metering-dao/src/main/resources/mapper/system/FlowDefMapper.xml b/casic-metering-dao/src/main/resources/mapper/system/FlowDefMapper.xml index c68ff7b..2afb680 100644 --- a/casic-metering-dao/src/main/resources/mapper/system/FlowDefMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/system/FlowDefMapper.xml @@ -20,8 +20,8 @@ su.name as directorName FROM ACT_RE_PROCDEF rp LEFT JOIN ACT_RE_DEPLOYMENT rd ON rp.deployment_id_ = rd.id_ - - INNER JOIN (SELECT max(arp.deployment_id_) AS deployment_id_ FROM ACT_RE_PROCDEF arp GROUP BY arp.key_) c ON rp.deployment_id_ = c.deployment_id_ + + LEFT JOIN system_flow_form sff ON sff.deploy_id = rd.id_ LEFT JOIN sys_user su ON su.id = rd.tenant_id_ WHERE sff.is_del = 0 @@ -40,11 +40,17 @@ and rp.suspension_state_ = #{request.suspensionState} - - and rd.tenant_id_ = #{request.directorId} + + + + + and su.name like concat('%',#{request.directorName},'%') - - and rd.deploy_time_ <= #{request.deploymentTime} + + and rd.deploy_time_ >= #{request.deploymentStartTime} + + + and rd.deploy_time_ <= #{request.deploymentEndTime} order by rd.deploy_time_ desc diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java index 516ff34..7c3bf41 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java @@ -30,7 +30,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,6 +67,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TrainPlanListRequest request) { @@ -162,6 +169,26 @@ } @Override + public ReturnDTO failUpdate(MeterTrainPlan trainPlan) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (trainPlanMapper.updateById(trainPlan) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(trainPlan.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + + @Override @Transactional public ReturnDTO submitTrainPlan(BaseApprovalSubmitRequest request) { //1.根据表单id获取流程定义id @@ -299,6 +326,9 @@ } private QueryWrapper getWrapper(TrainPlanListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getDirector()), "director", request.getDirector()); wrapper.like(StringUtils.isNotBlank(request.getEffectiveCompany()), "effective_company", request.getEffectiveCompany()); @@ -311,7 +341,7 @@ "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getCreateEndTime()), "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("train_time").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java index 516ff34..7c3bf41 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java @@ -30,7 +30,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,6 +67,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TrainPlanListRequest request) { @@ -162,6 +169,26 @@ } @Override + public ReturnDTO failUpdate(MeterTrainPlan trainPlan) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (trainPlanMapper.updateById(trainPlan) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(trainPlan.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + + @Override @Transactional public ReturnDTO submitTrainPlan(BaseApprovalSubmitRequest request) { //1.根据表单id获取流程定义id @@ -299,6 +326,9 @@ } private QueryWrapper getWrapper(TrainPlanListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getDirector()), "director", request.getDirector()); wrapper.like(StringUtils.isNotBlank(request.getEffectiveCompany()), "effective_company", request.getEffectiveCompany()); @@ -311,7 +341,7 @@ "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getCreateEndTime()), "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("train_time").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java index c994e8c..243321f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; @@ -14,8 +15,13 @@ import com.casic.missiles.mapper.system.FlowDefMapper; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; +import com.casic.missiles.modular.system.service.IUserRoleRelationService; import com.casic.missiles.service.system.IFlowDefService; import com.casic.missiles.utils.SnowflakeUtil; +import com.casic.missiles.utils.SpringContextUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -33,6 +39,7 @@ import org.flowable.validation.ProcessValidatorFactory; import org.flowable.validation.ValidationError; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -139,7 +146,12 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义保存失败"); } - }catch (Exception e){ + } catch (DuplicateKeyException e) { + log.error("该表单已保存过流程定义,异常信息:{}", e.getMessage()); + //新增异常则删除刚部署的流程 + repositoryService.deleteDeployment(deploy.getId(), true); + return ReturnUtil.failed("流程定义保存异常,该表单已存在流程定义"); + } catch (Exception e) { log.error("流程定义保存异常,异常信息:{}", e.getMessage()); //新增异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -196,7 +208,7 @@ new BpmnAutoLayout(bpmnModel).execute(); // System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - //流程部署 + //流程部署,更新 Deployment deploy = repositoryService.createDeployment() .tenantId(directorId)//租户标识符,这是一个字符串,可以是UUID、部门id .addBpmnModel(name + ".bpmn", bpmnModel) @@ -225,7 +237,7 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义更新失败"); } - }catch (Exception e){ + } catch (Exception e) { log.error("流程定义更新异常,异常信息:{}", e.getMessage()); //更新异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -266,7 +278,7 @@ //流程定义表单表删除 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("deploy_id", request.getDeployId()); - if(flowFormMapper.delete(wrapper) <= 0){ + if (flowFormMapper.delete(wrapper) <= 0) { log.error("流程定义删除失败,deployId:{}", request.getDeployId()); return ReturnUtil.failed("流程定义删除失败"); } @@ -381,30 +393,50 @@ //一个分支的子节点 JSONObject childNode = element.getJSONObject("childNode"); //一个分支的名字和表达式 - String nodeName = element.getString("nodeName");String expression = ""; + String nodeName = element.getString("nodeName"); + String expression = ""; expression = element.getString("conditionExpression"); - if(StringUtils.isEmpty(expression)){ + if (StringUtils.isEmpty(expression)) { JSONArray nodeUserList = element.getJSONArray("nodeUserList"); //1具体人员 2角色 3部门 //构造条件表达式 Iterator iterator = nodeUserList.stream().iterator(); List userIds = new ArrayList<>(); - while(iterator.hasNext()){ - HashMap map = (HashMap)iterator.next(); - if("1".equals(String.valueOf(map.get("type")))){ + while (iterator.hasNext()) { + HashMap map = (HashMap) iterator.next(); + if ("1".equals(String.valueOf(map.get("type")))) { + //用户id String targetId = String.valueOf(map.get("targetId")); userIds.add(targetId); - }else if("2".equals(String.valueOf(map.get("type")))){ - - }else if("3".equals(String.valueOf(map.get("type")))){ - + } else if ("2".equals(String.valueOf(map.get("type")))) { + //角色id + String targetId = String.valueOf(map.get("targetId")); + IUserRoleRelationService relationService = SpringContextUtil.getBean(IUserRoleRelationService.class); + BaseMapper baseMapper = relationService.getBaseMapper(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("ROLEID", targetId); + List ruRelations = baseMapper.selectList(wrapper); + ruRelations.forEach(ruRelation -> { + userIds.add(String.valueOf(ruRelation.getUserId())); + }); + } else if ("3".equals(String.valueOf(map.get("type")))) { + //部门id + String targetId = String.valueOf(map.get("targetId")); + UserMapper userMapper = SpringContextUtil.getBean(UserMapper.class); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("DEPT_ID", targetId); + List users = userMapper.selectList(wrapper); + users.forEach(user -> { + userIds.add(String.valueOf(user.getId())); + }); } } String str = StringUtils.join(userIds, ","); - // TODO: 2022/12/26 此处nodeName应为实例的发起人,但json不知对应何字段 - // TODO: 2022/12/26 ExUtils为bean实例方法,待添加 - expression = "exUtils."+"strContains("+nodeName+","+str+")"; - + // todo: 以下需验证,若不行,采用:流程实例的发起人通过TaskCreatedListener监听器设置,这里再获取,或者可能需要再加个监听器获取 + // ExUtils为bean实例方法,已添加 + // flowable表达式会自动识别流程变量,以下root也可识别为实例创建时的具体值,比如:${price < 100},price就是一个流程变量的值,UEL表达式的结果为布尔值 + String starterId = "root"; + expression = "exUtils." + "strContains(" + starterId + "," + str + ")"; } if (Objects.isNull(childNode)) { @@ -668,7 +700,7 @@ //多实例,在业务流程中,为特定步骤定义重复的方式 MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数,会签集合变量名称,flowable:collection=“assigneeList” + // 审批人集合参数,会签集合变量名称,flowable:collection=“id+assigneeList” //collection 赋值使用原因: // 通过上面的配置,当指定了 collection 的流程变量后,在引擎自动生成多任务时每个任务的assign都有值了。 // 就不再需要增加业务逻辑处理(遍历多任务后然后拿到审批人,依次给每个任务塞 处理人) diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java index 516ff34..7c3bf41 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java @@ -30,7 +30,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,6 +67,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TrainPlanListRequest request) { @@ -162,6 +169,26 @@ } @Override + public ReturnDTO failUpdate(MeterTrainPlan trainPlan) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (trainPlanMapper.updateById(trainPlan) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(trainPlan.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + + @Override @Transactional public ReturnDTO submitTrainPlan(BaseApprovalSubmitRequest request) { //1.根据表单id获取流程定义id @@ -299,6 +326,9 @@ } private QueryWrapper getWrapper(TrainPlanListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getDirector()), "director", request.getDirector()); wrapper.like(StringUtils.isNotBlank(request.getEffectiveCompany()), "effective_company", request.getEffectiveCompany()); @@ -311,7 +341,7 @@ "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getCreateEndTime()), "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("train_time").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java index c994e8c..243321f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; @@ -14,8 +15,13 @@ import com.casic.missiles.mapper.system.FlowDefMapper; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; +import com.casic.missiles.modular.system.service.IUserRoleRelationService; import com.casic.missiles.service.system.IFlowDefService; import com.casic.missiles.utils.SnowflakeUtil; +import com.casic.missiles.utils.SpringContextUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -33,6 +39,7 @@ import org.flowable.validation.ProcessValidatorFactory; import org.flowable.validation.ValidationError; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -139,7 +146,12 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义保存失败"); } - }catch (Exception e){ + } catch (DuplicateKeyException e) { + log.error("该表单已保存过流程定义,异常信息:{}", e.getMessage()); + //新增异常则删除刚部署的流程 + repositoryService.deleteDeployment(deploy.getId(), true); + return ReturnUtil.failed("流程定义保存异常,该表单已存在流程定义"); + } catch (Exception e) { log.error("流程定义保存异常,异常信息:{}", e.getMessage()); //新增异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -196,7 +208,7 @@ new BpmnAutoLayout(bpmnModel).execute(); // System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - //流程部署 + //流程部署,更新 Deployment deploy = repositoryService.createDeployment() .tenantId(directorId)//租户标识符,这是一个字符串,可以是UUID、部门id .addBpmnModel(name + ".bpmn", bpmnModel) @@ -225,7 +237,7 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义更新失败"); } - }catch (Exception e){ + } catch (Exception e) { log.error("流程定义更新异常,异常信息:{}", e.getMessage()); //更新异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -266,7 +278,7 @@ //流程定义表单表删除 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("deploy_id", request.getDeployId()); - if(flowFormMapper.delete(wrapper) <= 0){ + if (flowFormMapper.delete(wrapper) <= 0) { log.error("流程定义删除失败,deployId:{}", request.getDeployId()); return ReturnUtil.failed("流程定义删除失败"); } @@ -381,30 +393,50 @@ //一个分支的子节点 JSONObject childNode = element.getJSONObject("childNode"); //一个分支的名字和表达式 - String nodeName = element.getString("nodeName");String expression = ""; + String nodeName = element.getString("nodeName"); + String expression = ""; expression = element.getString("conditionExpression"); - if(StringUtils.isEmpty(expression)){ + if (StringUtils.isEmpty(expression)) { JSONArray nodeUserList = element.getJSONArray("nodeUserList"); //1具体人员 2角色 3部门 //构造条件表达式 Iterator iterator = nodeUserList.stream().iterator(); List userIds = new ArrayList<>(); - while(iterator.hasNext()){ - HashMap map = (HashMap)iterator.next(); - if("1".equals(String.valueOf(map.get("type")))){ + while (iterator.hasNext()) { + HashMap map = (HashMap) iterator.next(); + if ("1".equals(String.valueOf(map.get("type")))) { + //用户id String targetId = String.valueOf(map.get("targetId")); userIds.add(targetId); - }else if("2".equals(String.valueOf(map.get("type")))){ - - }else if("3".equals(String.valueOf(map.get("type")))){ - + } else if ("2".equals(String.valueOf(map.get("type")))) { + //角色id + String targetId = String.valueOf(map.get("targetId")); + IUserRoleRelationService relationService = SpringContextUtil.getBean(IUserRoleRelationService.class); + BaseMapper baseMapper = relationService.getBaseMapper(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("ROLEID", targetId); + List ruRelations = baseMapper.selectList(wrapper); + ruRelations.forEach(ruRelation -> { + userIds.add(String.valueOf(ruRelation.getUserId())); + }); + } else if ("3".equals(String.valueOf(map.get("type")))) { + //部门id + String targetId = String.valueOf(map.get("targetId")); + UserMapper userMapper = SpringContextUtil.getBean(UserMapper.class); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("DEPT_ID", targetId); + List users = userMapper.selectList(wrapper); + users.forEach(user -> { + userIds.add(String.valueOf(user.getId())); + }); } } String str = StringUtils.join(userIds, ","); - // TODO: 2022/12/26 此处nodeName应为实例的发起人,但json不知对应何字段 - // TODO: 2022/12/26 ExUtils为bean实例方法,待添加 - expression = "exUtils."+"strContains("+nodeName+","+str+")"; - + // todo: 以下需验证,若不行,采用:流程实例的发起人通过TaskCreatedListener监听器设置,这里再获取,或者可能需要再加个监听器获取 + // ExUtils为bean实例方法,已添加 + // flowable表达式会自动识别流程变量,以下root也可识别为实例创建时的具体值,比如:${price < 100},price就是一个流程变量的值,UEL表达式的结果为布尔值 + String starterId = "root"; + expression = "exUtils." + "strContains(" + starterId + "," + str + ")"; } if (Objects.isNull(childNode)) { @@ -668,7 +700,7 @@ //多实例,在业务流程中,为特定步骤定义重复的方式 MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数,会签集合变量名称,flowable:collection=“assigneeList” + // 审批人集合参数,会签集合变量名称,flowable:collection=“id+assigneeList” //collection 赋值使用原因: // 通过上面的配置,当指定了 collection 的流程变量后,在引擎自动生成多任务时每个任务的assign都有值了。 // 就不再需要增加业务逻辑处理(遍历多任务后然后拿到审批人,依次给每个任务塞 处理人) diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java index d1266ae..8d70f8f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java @@ -1,11 +1,24 @@ package com.casic.missiles.service.Impl.system; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; +import com.casic.missiles.modular.system.model.User; import com.casic.missiles.service.system.ISystemFlowFormService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + /** *

* 服务实现类 @@ -16,5 +29,47 @@ */ @Service public class SystemFlowFormServiceImpl extends ServiceImpl implements ISystemFlowFormService { + @Resource + private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; + @Override + public int getDirectorLevel(Long userId) { + //需要保证用户所在组织机构一定要有个角色的TIPS为director的角色的人 + int level = 0; + return getDirectorList(level, userId); + } + + private int getDirectorList(int level, Long userId) { + User user = userMapper.selectById(userId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(level >= 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + + if(CollectionUtils.isEmpty(list)){ + return level; + } + level += 1; + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + return getDirectorList(level, Long.valueOf(id)); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java index 516ff34..7c3bf41 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java @@ -30,7 +30,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,6 +67,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TrainPlanListRequest request) { @@ -162,6 +169,26 @@ } @Override + public ReturnDTO failUpdate(MeterTrainPlan trainPlan) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (trainPlanMapper.updateById(trainPlan) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(trainPlan.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + + @Override @Transactional public ReturnDTO submitTrainPlan(BaseApprovalSubmitRequest request) { //1.根据表单id获取流程定义id @@ -299,6 +326,9 @@ } private QueryWrapper getWrapper(TrainPlanListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getDirector()), "director", request.getDirector()); wrapper.like(StringUtils.isNotBlank(request.getEffectiveCompany()), "effective_company", request.getEffectiveCompany()); @@ -311,7 +341,7 @@ "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getCreateEndTime()), "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("train_time").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java index c994e8c..243321f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; @@ -14,8 +15,13 @@ import com.casic.missiles.mapper.system.FlowDefMapper; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; +import com.casic.missiles.modular.system.service.IUserRoleRelationService; import com.casic.missiles.service.system.IFlowDefService; import com.casic.missiles.utils.SnowflakeUtil; +import com.casic.missiles.utils.SpringContextUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -33,6 +39,7 @@ import org.flowable.validation.ProcessValidatorFactory; import org.flowable.validation.ValidationError; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -139,7 +146,12 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义保存失败"); } - }catch (Exception e){ + } catch (DuplicateKeyException e) { + log.error("该表单已保存过流程定义,异常信息:{}", e.getMessage()); + //新增异常则删除刚部署的流程 + repositoryService.deleteDeployment(deploy.getId(), true); + return ReturnUtil.failed("流程定义保存异常,该表单已存在流程定义"); + } catch (Exception e) { log.error("流程定义保存异常,异常信息:{}", e.getMessage()); //新增异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -196,7 +208,7 @@ new BpmnAutoLayout(bpmnModel).execute(); // System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - //流程部署 + //流程部署,更新 Deployment deploy = repositoryService.createDeployment() .tenantId(directorId)//租户标识符,这是一个字符串,可以是UUID、部门id .addBpmnModel(name + ".bpmn", bpmnModel) @@ -225,7 +237,7 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义更新失败"); } - }catch (Exception e){ + } catch (Exception e) { log.error("流程定义更新异常,异常信息:{}", e.getMessage()); //更新异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -266,7 +278,7 @@ //流程定义表单表删除 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("deploy_id", request.getDeployId()); - if(flowFormMapper.delete(wrapper) <= 0){ + if (flowFormMapper.delete(wrapper) <= 0) { log.error("流程定义删除失败,deployId:{}", request.getDeployId()); return ReturnUtil.failed("流程定义删除失败"); } @@ -381,30 +393,50 @@ //一个分支的子节点 JSONObject childNode = element.getJSONObject("childNode"); //一个分支的名字和表达式 - String nodeName = element.getString("nodeName");String expression = ""; + String nodeName = element.getString("nodeName"); + String expression = ""; expression = element.getString("conditionExpression"); - if(StringUtils.isEmpty(expression)){ + if (StringUtils.isEmpty(expression)) { JSONArray nodeUserList = element.getJSONArray("nodeUserList"); //1具体人员 2角色 3部门 //构造条件表达式 Iterator iterator = nodeUserList.stream().iterator(); List userIds = new ArrayList<>(); - while(iterator.hasNext()){ - HashMap map = (HashMap)iterator.next(); - if("1".equals(String.valueOf(map.get("type")))){ + while (iterator.hasNext()) { + HashMap map = (HashMap) iterator.next(); + if ("1".equals(String.valueOf(map.get("type")))) { + //用户id String targetId = String.valueOf(map.get("targetId")); userIds.add(targetId); - }else if("2".equals(String.valueOf(map.get("type")))){ - - }else if("3".equals(String.valueOf(map.get("type")))){ - + } else if ("2".equals(String.valueOf(map.get("type")))) { + //角色id + String targetId = String.valueOf(map.get("targetId")); + IUserRoleRelationService relationService = SpringContextUtil.getBean(IUserRoleRelationService.class); + BaseMapper baseMapper = relationService.getBaseMapper(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("ROLEID", targetId); + List ruRelations = baseMapper.selectList(wrapper); + ruRelations.forEach(ruRelation -> { + userIds.add(String.valueOf(ruRelation.getUserId())); + }); + } else if ("3".equals(String.valueOf(map.get("type")))) { + //部门id + String targetId = String.valueOf(map.get("targetId")); + UserMapper userMapper = SpringContextUtil.getBean(UserMapper.class); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("DEPT_ID", targetId); + List users = userMapper.selectList(wrapper); + users.forEach(user -> { + userIds.add(String.valueOf(user.getId())); + }); } } String str = StringUtils.join(userIds, ","); - // TODO: 2022/12/26 此处nodeName应为实例的发起人,但json不知对应何字段 - // TODO: 2022/12/26 ExUtils为bean实例方法,待添加 - expression = "exUtils."+"strContains("+nodeName+","+str+")"; - + // todo: 以下需验证,若不行,采用:流程实例的发起人通过TaskCreatedListener监听器设置,这里再获取,或者可能需要再加个监听器获取 + // ExUtils为bean实例方法,已添加 + // flowable表达式会自动识别流程变量,以下root也可识别为实例创建时的具体值,比如:${price < 100},price就是一个流程变量的值,UEL表达式的结果为布尔值 + String starterId = "root"; + expression = "exUtils." + "strContains(" + starterId + "," + str + ")"; } if (Objects.isNull(childNode)) { @@ -668,7 +700,7 @@ //多实例,在业务流程中,为特定步骤定义重复的方式 MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数,会签集合变量名称,flowable:collection=“assigneeList” + // 审批人集合参数,会签集合变量名称,flowable:collection=“id+assigneeList” //collection 赋值使用原因: // 通过上面的配置,当指定了 collection 的流程变量后,在引擎自动生成多任务时每个任务的assign都有值了。 // 就不再需要增加业务逻辑处理(遍历多任务后然后拿到审批人,依次给每个任务塞 处理人) diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java index d1266ae..8d70f8f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java @@ -1,11 +1,24 @@ package com.casic.missiles.service.Impl.system; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; +import com.casic.missiles.modular.system.model.User; import com.casic.missiles.service.system.ISystemFlowFormService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + /** *

* 服务实现类 @@ -16,5 +29,47 @@ */ @Service public class SystemFlowFormServiceImpl extends ServiceImpl implements ISystemFlowFormService { + @Resource + private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; + @Override + public int getDirectorLevel(Long userId) { + //需要保证用户所在组织机构一定要有个角色的TIPS为director的角色的人 + int level = 0; + return getDirectorList(level, userId); + } + + private int getDirectorList(int level, Long userId) { + User user = userMapper.selectById(userId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(level >= 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + + if(CollectionUtils.isEmpty(list)){ + return level; + } + level += 1; + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + return getDirectorList(level, Long.valueOf(id)); + } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java index b1f17a9..a36ae80 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java @@ -39,4 +39,6 @@ List approvalListPage(Page page, FileApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterFile meterFile); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java index 516ff34..7c3bf41 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java @@ -30,7 +30,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,6 +67,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TrainPlanListRequest request) { @@ -162,6 +169,26 @@ } @Override + public ReturnDTO failUpdate(MeterTrainPlan trainPlan) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (trainPlanMapper.updateById(trainPlan) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(trainPlan.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + + @Override @Transactional public ReturnDTO submitTrainPlan(BaseApprovalSubmitRequest request) { //1.根据表单id获取流程定义id @@ -299,6 +326,9 @@ } private QueryWrapper getWrapper(TrainPlanListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getDirector()), "director", request.getDirector()); wrapper.like(StringUtils.isNotBlank(request.getEffectiveCompany()), "effective_company", request.getEffectiveCompany()); @@ -311,7 +341,7 @@ "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getCreateEndTime()), "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("train_time").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java index c994e8c..243321f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; @@ -14,8 +15,13 @@ import com.casic.missiles.mapper.system.FlowDefMapper; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; +import com.casic.missiles.modular.system.service.IUserRoleRelationService; import com.casic.missiles.service.system.IFlowDefService; import com.casic.missiles.utils.SnowflakeUtil; +import com.casic.missiles.utils.SpringContextUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -33,6 +39,7 @@ import org.flowable.validation.ProcessValidatorFactory; import org.flowable.validation.ValidationError; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -139,7 +146,12 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义保存失败"); } - }catch (Exception e){ + } catch (DuplicateKeyException e) { + log.error("该表单已保存过流程定义,异常信息:{}", e.getMessage()); + //新增异常则删除刚部署的流程 + repositoryService.deleteDeployment(deploy.getId(), true); + return ReturnUtil.failed("流程定义保存异常,该表单已存在流程定义"); + } catch (Exception e) { log.error("流程定义保存异常,异常信息:{}", e.getMessage()); //新增异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -196,7 +208,7 @@ new BpmnAutoLayout(bpmnModel).execute(); // System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - //流程部署 + //流程部署,更新 Deployment deploy = repositoryService.createDeployment() .tenantId(directorId)//租户标识符,这是一个字符串,可以是UUID、部门id .addBpmnModel(name + ".bpmn", bpmnModel) @@ -225,7 +237,7 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义更新失败"); } - }catch (Exception e){ + } catch (Exception e) { log.error("流程定义更新异常,异常信息:{}", e.getMessage()); //更新异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -266,7 +278,7 @@ //流程定义表单表删除 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("deploy_id", request.getDeployId()); - if(flowFormMapper.delete(wrapper) <= 0){ + if (flowFormMapper.delete(wrapper) <= 0) { log.error("流程定义删除失败,deployId:{}", request.getDeployId()); return ReturnUtil.failed("流程定义删除失败"); } @@ -381,30 +393,50 @@ //一个分支的子节点 JSONObject childNode = element.getJSONObject("childNode"); //一个分支的名字和表达式 - String nodeName = element.getString("nodeName");String expression = ""; + String nodeName = element.getString("nodeName"); + String expression = ""; expression = element.getString("conditionExpression"); - if(StringUtils.isEmpty(expression)){ + if (StringUtils.isEmpty(expression)) { JSONArray nodeUserList = element.getJSONArray("nodeUserList"); //1具体人员 2角色 3部门 //构造条件表达式 Iterator iterator = nodeUserList.stream().iterator(); List userIds = new ArrayList<>(); - while(iterator.hasNext()){ - HashMap map = (HashMap)iterator.next(); - if("1".equals(String.valueOf(map.get("type")))){ + while (iterator.hasNext()) { + HashMap map = (HashMap) iterator.next(); + if ("1".equals(String.valueOf(map.get("type")))) { + //用户id String targetId = String.valueOf(map.get("targetId")); userIds.add(targetId); - }else if("2".equals(String.valueOf(map.get("type")))){ - - }else if("3".equals(String.valueOf(map.get("type")))){ - + } else if ("2".equals(String.valueOf(map.get("type")))) { + //角色id + String targetId = String.valueOf(map.get("targetId")); + IUserRoleRelationService relationService = SpringContextUtil.getBean(IUserRoleRelationService.class); + BaseMapper baseMapper = relationService.getBaseMapper(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("ROLEID", targetId); + List ruRelations = baseMapper.selectList(wrapper); + ruRelations.forEach(ruRelation -> { + userIds.add(String.valueOf(ruRelation.getUserId())); + }); + } else if ("3".equals(String.valueOf(map.get("type")))) { + //部门id + String targetId = String.valueOf(map.get("targetId")); + UserMapper userMapper = SpringContextUtil.getBean(UserMapper.class); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("DEPT_ID", targetId); + List users = userMapper.selectList(wrapper); + users.forEach(user -> { + userIds.add(String.valueOf(user.getId())); + }); } } String str = StringUtils.join(userIds, ","); - // TODO: 2022/12/26 此处nodeName应为实例的发起人,但json不知对应何字段 - // TODO: 2022/12/26 ExUtils为bean实例方法,待添加 - expression = "exUtils."+"strContains("+nodeName+","+str+")"; - + // todo: 以下需验证,若不行,采用:流程实例的发起人通过TaskCreatedListener监听器设置,这里再获取,或者可能需要再加个监听器获取 + // ExUtils为bean实例方法,已添加 + // flowable表达式会自动识别流程变量,以下root也可识别为实例创建时的具体值,比如:${price < 100},price就是一个流程变量的值,UEL表达式的结果为布尔值 + String starterId = "root"; + expression = "exUtils." + "strContains(" + starterId + "," + str + ")"; } if (Objects.isNull(childNode)) { @@ -668,7 +700,7 @@ //多实例,在业务流程中,为特定步骤定义重复的方式 MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数,会签集合变量名称,flowable:collection=“assigneeList” + // 审批人集合参数,会签集合变量名称,flowable:collection=“id+assigneeList” //collection 赋值使用原因: // 通过上面的配置,当指定了 collection 的流程变量后,在引擎自动生成多任务时每个任务的assign都有值了。 // 就不再需要增加业务逻辑处理(遍历多任务后然后拿到审批人,依次给每个任务塞 处理人) diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java index d1266ae..8d70f8f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java @@ -1,11 +1,24 @@ package com.casic.missiles.service.Impl.system; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; +import com.casic.missiles.modular.system.model.User; import com.casic.missiles.service.system.ISystemFlowFormService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + /** *

* 服务实现类 @@ -16,5 +29,47 @@ */ @Service public class SystemFlowFormServiceImpl extends ServiceImpl implements ISystemFlowFormService { + @Resource + private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; + @Override + public int getDirectorLevel(Long userId) { + //需要保证用户所在组织机构一定要有个角色的TIPS为director的角色的人 + int level = 0; + return getDirectorList(level, userId); + } + + private int getDirectorList(int level, Long userId) { + User user = userMapper.selectById(userId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(level >= 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + + if(CollectionUtils.isEmpty(list)){ + return level; + } + level += 1; + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + return getDirectorList(level, Long.valueOf(id)); + } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java index b1f17a9..a36ae80 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java @@ -39,4 +39,6 @@ List approvalListPage(Page page, FileApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterFile meterFile); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java index 5d114a6..2d7de64 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java @@ -42,4 +42,6 @@ List approvalListPage(Page page, TraceSupplierApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterTraceSupplier traceSupplier); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java index 516ff34..7c3bf41 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java @@ -30,7 +30,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,6 +67,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TrainPlanListRequest request) { @@ -162,6 +169,26 @@ } @Override + public ReturnDTO failUpdate(MeterTrainPlan trainPlan) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (trainPlanMapper.updateById(trainPlan) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(trainPlan.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + + @Override @Transactional public ReturnDTO submitTrainPlan(BaseApprovalSubmitRequest request) { //1.根据表单id获取流程定义id @@ -299,6 +326,9 @@ } private QueryWrapper getWrapper(TrainPlanListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getDirector()), "director", request.getDirector()); wrapper.like(StringUtils.isNotBlank(request.getEffectiveCompany()), "effective_company", request.getEffectiveCompany()); @@ -311,7 +341,7 @@ "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getCreateEndTime()), "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("train_time").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java index c994e8c..243321f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; @@ -14,8 +15,13 @@ import com.casic.missiles.mapper.system.FlowDefMapper; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; +import com.casic.missiles.modular.system.service.IUserRoleRelationService; import com.casic.missiles.service.system.IFlowDefService; import com.casic.missiles.utils.SnowflakeUtil; +import com.casic.missiles.utils.SpringContextUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -33,6 +39,7 @@ import org.flowable.validation.ProcessValidatorFactory; import org.flowable.validation.ValidationError; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -139,7 +146,12 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义保存失败"); } - }catch (Exception e){ + } catch (DuplicateKeyException e) { + log.error("该表单已保存过流程定义,异常信息:{}", e.getMessage()); + //新增异常则删除刚部署的流程 + repositoryService.deleteDeployment(deploy.getId(), true); + return ReturnUtil.failed("流程定义保存异常,该表单已存在流程定义"); + } catch (Exception e) { log.error("流程定义保存异常,异常信息:{}", e.getMessage()); //新增异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -196,7 +208,7 @@ new BpmnAutoLayout(bpmnModel).execute(); // System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - //流程部署 + //流程部署,更新 Deployment deploy = repositoryService.createDeployment() .tenantId(directorId)//租户标识符,这是一个字符串,可以是UUID、部门id .addBpmnModel(name + ".bpmn", bpmnModel) @@ -225,7 +237,7 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义更新失败"); } - }catch (Exception e){ + } catch (Exception e) { log.error("流程定义更新异常,异常信息:{}", e.getMessage()); //更新异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -266,7 +278,7 @@ //流程定义表单表删除 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("deploy_id", request.getDeployId()); - if(flowFormMapper.delete(wrapper) <= 0){ + if (flowFormMapper.delete(wrapper) <= 0) { log.error("流程定义删除失败,deployId:{}", request.getDeployId()); return ReturnUtil.failed("流程定义删除失败"); } @@ -381,30 +393,50 @@ //一个分支的子节点 JSONObject childNode = element.getJSONObject("childNode"); //一个分支的名字和表达式 - String nodeName = element.getString("nodeName");String expression = ""; + String nodeName = element.getString("nodeName"); + String expression = ""; expression = element.getString("conditionExpression"); - if(StringUtils.isEmpty(expression)){ + if (StringUtils.isEmpty(expression)) { JSONArray nodeUserList = element.getJSONArray("nodeUserList"); //1具体人员 2角色 3部门 //构造条件表达式 Iterator iterator = nodeUserList.stream().iterator(); List userIds = new ArrayList<>(); - while(iterator.hasNext()){ - HashMap map = (HashMap)iterator.next(); - if("1".equals(String.valueOf(map.get("type")))){ + while (iterator.hasNext()) { + HashMap map = (HashMap) iterator.next(); + if ("1".equals(String.valueOf(map.get("type")))) { + //用户id String targetId = String.valueOf(map.get("targetId")); userIds.add(targetId); - }else if("2".equals(String.valueOf(map.get("type")))){ - - }else if("3".equals(String.valueOf(map.get("type")))){ - + } else if ("2".equals(String.valueOf(map.get("type")))) { + //角色id + String targetId = String.valueOf(map.get("targetId")); + IUserRoleRelationService relationService = SpringContextUtil.getBean(IUserRoleRelationService.class); + BaseMapper baseMapper = relationService.getBaseMapper(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("ROLEID", targetId); + List ruRelations = baseMapper.selectList(wrapper); + ruRelations.forEach(ruRelation -> { + userIds.add(String.valueOf(ruRelation.getUserId())); + }); + } else if ("3".equals(String.valueOf(map.get("type")))) { + //部门id + String targetId = String.valueOf(map.get("targetId")); + UserMapper userMapper = SpringContextUtil.getBean(UserMapper.class); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("DEPT_ID", targetId); + List users = userMapper.selectList(wrapper); + users.forEach(user -> { + userIds.add(String.valueOf(user.getId())); + }); } } String str = StringUtils.join(userIds, ","); - // TODO: 2022/12/26 此处nodeName应为实例的发起人,但json不知对应何字段 - // TODO: 2022/12/26 ExUtils为bean实例方法,待添加 - expression = "exUtils."+"strContains("+nodeName+","+str+")"; - + // todo: 以下需验证,若不行,采用:流程实例的发起人通过TaskCreatedListener监听器设置,这里再获取,或者可能需要再加个监听器获取 + // ExUtils为bean实例方法,已添加 + // flowable表达式会自动识别流程变量,以下root也可识别为实例创建时的具体值,比如:${price < 100},price就是一个流程变量的值,UEL表达式的结果为布尔值 + String starterId = "root"; + expression = "exUtils." + "strContains(" + starterId + "," + str + ")"; } if (Objects.isNull(childNode)) { @@ -668,7 +700,7 @@ //多实例,在业务流程中,为特定步骤定义重复的方式 MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数,会签集合变量名称,flowable:collection=“assigneeList” + // 审批人集合参数,会签集合变量名称,flowable:collection=“id+assigneeList” //collection 赋值使用原因: // 通过上面的配置,当指定了 collection 的流程变量后,在引擎自动生成多任务时每个任务的assign都有值了。 // 就不再需要增加业务逻辑处理(遍历多任务后然后拿到审批人,依次给每个任务塞 处理人) diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java index d1266ae..8d70f8f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java @@ -1,11 +1,24 @@ package com.casic.missiles.service.Impl.system; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; +import com.casic.missiles.modular.system.model.User; import com.casic.missiles.service.system.ISystemFlowFormService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + /** *

* 服务实现类 @@ -16,5 +29,47 @@ */ @Service public class SystemFlowFormServiceImpl extends ServiceImpl implements ISystemFlowFormService { + @Resource + private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; + @Override + public int getDirectorLevel(Long userId) { + //需要保证用户所在组织机构一定要有个角色的TIPS为director的角色的人 + int level = 0; + return getDirectorList(level, userId); + } + + private int getDirectorList(int level, Long userId) { + User user = userMapper.selectById(userId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(level >= 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + + if(CollectionUtils.isEmpty(list)){ + return level; + } + level += 1; + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + return getDirectorList(level, Long.valueOf(id)); + } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java index b1f17a9..a36ae80 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java @@ -39,4 +39,6 @@ List approvalListPage(Page page, FileApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterFile meterFile); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java index 5d114a6..2d7de64 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java @@ -42,4 +42,6 @@ List approvalListPage(Page page, TraceSupplierApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterTraceSupplier traceSupplier); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java index 47131aa..5043880 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java @@ -41,4 +41,6 @@ List approvalListPage(Page page, TrainPlanApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterTrainPlan trainPlan); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java index 516ff34..7c3bf41 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java @@ -30,7 +30,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,6 +67,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TrainPlanListRequest request) { @@ -162,6 +169,26 @@ } @Override + public ReturnDTO failUpdate(MeterTrainPlan trainPlan) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (trainPlanMapper.updateById(trainPlan) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(trainPlan.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + + @Override @Transactional public ReturnDTO submitTrainPlan(BaseApprovalSubmitRequest request) { //1.根据表单id获取流程定义id @@ -299,6 +326,9 @@ } private QueryWrapper getWrapper(TrainPlanListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getDirector()), "director", request.getDirector()); wrapper.like(StringUtils.isNotBlank(request.getEffectiveCompany()), "effective_company", request.getEffectiveCompany()); @@ -311,7 +341,7 @@ "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getCreateEndTime()), "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("train_time").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java index c994e8c..243321f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; @@ -14,8 +15,13 @@ import com.casic.missiles.mapper.system.FlowDefMapper; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; +import com.casic.missiles.modular.system.service.IUserRoleRelationService; import com.casic.missiles.service.system.IFlowDefService; import com.casic.missiles.utils.SnowflakeUtil; +import com.casic.missiles.utils.SpringContextUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -33,6 +39,7 @@ import org.flowable.validation.ProcessValidatorFactory; import org.flowable.validation.ValidationError; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -139,7 +146,12 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义保存失败"); } - }catch (Exception e){ + } catch (DuplicateKeyException e) { + log.error("该表单已保存过流程定义,异常信息:{}", e.getMessage()); + //新增异常则删除刚部署的流程 + repositoryService.deleteDeployment(deploy.getId(), true); + return ReturnUtil.failed("流程定义保存异常,该表单已存在流程定义"); + } catch (Exception e) { log.error("流程定义保存异常,异常信息:{}", e.getMessage()); //新增异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -196,7 +208,7 @@ new BpmnAutoLayout(bpmnModel).execute(); // System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - //流程部署 + //流程部署,更新 Deployment deploy = repositoryService.createDeployment() .tenantId(directorId)//租户标识符,这是一个字符串,可以是UUID、部门id .addBpmnModel(name + ".bpmn", bpmnModel) @@ -225,7 +237,7 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义更新失败"); } - }catch (Exception e){ + } catch (Exception e) { log.error("流程定义更新异常,异常信息:{}", e.getMessage()); //更新异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -266,7 +278,7 @@ //流程定义表单表删除 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("deploy_id", request.getDeployId()); - if(flowFormMapper.delete(wrapper) <= 0){ + if (flowFormMapper.delete(wrapper) <= 0) { log.error("流程定义删除失败,deployId:{}", request.getDeployId()); return ReturnUtil.failed("流程定义删除失败"); } @@ -381,30 +393,50 @@ //一个分支的子节点 JSONObject childNode = element.getJSONObject("childNode"); //一个分支的名字和表达式 - String nodeName = element.getString("nodeName");String expression = ""; + String nodeName = element.getString("nodeName"); + String expression = ""; expression = element.getString("conditionExpression"); - if(StringUtils.isEmpty(expression)){ + if (StringUtils.isEmpty(expression)) { JSONArray nodeUserList = element.getJSONArray("nodeUserList"); //1具体人员 2角色 3部门 //构造条件表达式 Iterator iterator = nodeUserList.stream().iterator(); List userIds = new ArrayList<>(); - while(iterator.hasNext()){ - HashMap map = (HashMap)iterator.next(); - if("1".equals(String.valueOf(map.get("type")))){ + while (iterator.hasNext()) { + HashMap map = (HashMap) iterator.next(); + if ("1".equals(String.valueOf(map.get("type")))) { + //用户id String targetId = String.valueOf(map.get("targetId")); userIds.add(targetId); - }else if("2".equals(String.valueOf(map.get("type")))){ - - }else if("3".equals(String.valueOf(map.get("type")))){ - + } else if ("2".equals(String.valueOf(map.get("type")))) { + //角色id + String targetId = String.valueOf(map.get("targetId")); + IUserRoleRelationService relationService = SpringContextUtil.getBean(IUserRoleRelationService.class); + BaseMapper baseMapper = relationService.getBaseMapper(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("ROLEID", targetId); + List ruRelations = baseMapper.selectList(wrapper); + ruRelations.forEach(ruRelation -> { + userIds.add(String.valueOf(ruRelation.getUserId())); + }); + } else if ("3".equals(String.valueOf(map.get("type")))) { + //部门id + String targetId = String.valueOf(map.get("targetId")); + UserMapper userMapper = SpringContextUtil.getBean(UserMapper.class); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("DEPT_ID", targetId); + List users = userMapper.selectList(wrapper); + users.forEach(user -> { + userIds.add(String.valueOf(user.getId())); + }); } } String str = StringUtils.join(userIds, ","); - // TODO: 2022/12/26 此处nodeName应为实例的发起人,但json不知对应何字段 - // TODO: 2022/12/26 ExUtils为bean实例方法,待添加 - expression = "exUtils."+"strContains("+nodeName+","+str+")"; - + // todo: 以下需验证,若不行,采用:流程实例的发起人通过TaskCreatedListener监听器设置,这里再获取,或者可能需要再加个监听器获取 + // ExUtils为bean实例方法,已添加 + // flowable表达式会自动识别流程变量,以下root也可识别为实例创建时的具体值,比如:${price < 100},price就是一个流程变量的值,UEL表达式的结果为布尔值 + String starterId = "root"; + expression = "exUtils." + "strContains(" + starterId + "," + str + ")"; } if (Objects.isNull(childNode)) { @@ -668,7 +700,7 @@ //多实例,在业务流程中,为特定步骤定义重复的方式 MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数,会签集合变量名称,flowable:collection=“assigneeList” + // 审批人集合参数,会签集合变量名称,flowable:collection=“id+assigneeList” //collection 赋值使用原因: // 通过上面的配置,当指定了 collection 的流程变量后,在引擎自动生成多任务时每个任务的assign都有值了。 // 就不再需要增加业务逻辑处理(遍历多任务后然后拿到审批人,依次给每个任务塞 处理人) diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java index d1266ae..8d70f8f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java @@ -1,11 +1,24 @@ package com.casic.missiles.service.Impl.system; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; +import com.casic.missiles.modular.system.model.User; import com.casic.missiles.service.system.ISystemFlowFormService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + /** *

* 服务实现类 @@ -16,5 +29,47 @@ */ @Service public class SystemFlowFormServiceImpl extends ServiceImpl implements ISystemFlowFormService { + @Resource + private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; + @Override + public int getDirectorLevel(Long userId) { + //需要保证用户所在组织机构一定要有个角色的TIPS为director的角色的人 + int level = 0; + return getDirectorList(level, userId); + } + + private int getDirectorList(int level, Long userId) { + User user = userMapper.selectById(userId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(level >= 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + + if(CollectionUtils.isEmpty(list)){ + return level; + } + level += 1; + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + return getDirectorList(level, Long.valueOf(id)); + } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java index b1f17a9..a36ae80 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java @@ -39,4 +39,6 @@ List approvalListPage(Page page, FileApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterFile meterFile); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java index 5d114a6..2d7de64 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java @@ -42,4 +42,6 @@ List approvalListPage(Page page, TraceSupplierApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterTraceSupplier traceSupplier); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java index 47131aa..5043880 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java @@ -41,4 +41,6 @@ List approvalListPage(Page page, TrainPlanApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterTrainPlan trainPlan); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/system/ISystemFlowFormService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/system/ISystemFlowFormService.java index 5e3ab7b..70d391b 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/system/ISystemFlowFormService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/system/ISystemFlowFormService.java @@ -13,4 +13,5 @@ */ public interface ISystemFlowFormService extends IService { + int getDirectorLevel(Long userId); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java index b6bbdae..1ffae62 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/flowable/JsonToBpmnController.java @@ -229,7 +229,7 @@ childNode.put("childNode", null); String identifier = endExId;/*create(flowElement.getId(), childNode,model,process,sequenceFlows);*/ for (int i = 0; i < incoming.size(); i++) { - // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为啥不一样 + // TODO: 2022/12/5 此处用的connect第一个参数和并行网关的为何不一样 // TODO: 2022/12/5 为啥有后续节点这里却设置成了endExId process.addFlowElement(connect(incoming.get(i), endExId, sequenceFlows)); } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java index ec4580c..6b743c5 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterFileController.java @@ -58,7 +58,10 @@ @ApiOperation("文件列表/详情(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> listPage(@RequestBody FileListRequest request) { + public ReturnDTO> listPage(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(meterFileService.listPage(page, request))); } @@ -66,14 +69,20 @@ @ApiOperation("文件列表(不分页)") @PostMapping("/list") @ResponseBody - public ReturnDTO> list(@RequestBody FileListRequest request) { + public ReturnDTO> list(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(meterFileService.list(request)); } @ApiOperation("文件导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody FileListRequest request) throws IOException { + public void export(@RequestBody @Valid FileListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = meterFileService.listByIds(request.getIds()); @@ -141,7 +150,6 @@ throw new BusinessException(BusinessExceptionEnum.ID_NULL); }); return meterFileService.deleteFile(idDTO.getId()); - // TODO: 2022/11/26 考虑activiti流程数据除脏,否则各审批状态查询出来的还要再过滤一遍 } @ApiOperation("文件批量删除") @@ -190,4 +198,22 @@ } return meterFileService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过文件编辑(驳回后的文件重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterFile meterFile, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(meterFile.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return meterFileService.failUpdate(meterFile); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java index 7299005..c5606bc 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTraceSupplierController.java @@ -45,7 +45,10 @@ @ApiOperation("溯源供方列表(分页)") @PostMapping("/listPage") @ResponseBody - public ReturnDTO> supplierListPage(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierListPage(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(traceSupplierService.listPage(page, request))); } @@ -53,14 +56,20 @@ @ApiOperation("溯源供方列表") @PostMapping("/list") @ResponseBody - public ReturnDTO> supplierList(@RequestBody TraceSupplierListRequest request) { + public ReturnDTO> supplierList(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(traceSupplierService.list(request)); } @ApiOperation("溯源供方导出") @PostMapping("/listExport") @ResponseBody - public void export(@RequestBody TraceSupplierListRequest request) throws IOException { + public void export(@RequestBody @Valid TraceSupplierListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = traceSupplierService.listByIds(request.getIds()); @@ -176,4 +185,21 @@ return traceSupplierService.approvalDelete(request); } + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过溯源供方编辑(驳回后的溯源供方重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTraceSupplier traceSupplier, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(traceSupplier.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return traceSupplierService.failUpdate(traceSupplier); + } + } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java index 09aae1e..59fc909 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/meter/MeterTrainController.java @@ -49,7 +49,10 @@ @ApiOperation("培训计划列表(分页)") @PostMapping("/plan/listPage") @ResponseBody - public ReturnDTO> planListPage(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planListPage(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } Page page = PageFactory.defaultPage(); return ReturnUtil.success(super.packForBT(trainPlanService.listPage(page, request))); } @@ -57,14 +60,20 @@ @ApiOperation("培训计划列表") @PostMapping("/plan/list") @ResponseBody - public ReturnDTO> planList(@RequestBody TrainPlanListRequest request) { + public ReturnDTO> planList(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } return ReturnUtil.success(trainPlanService.planList(request)); } @ApiOperation("培训计划导出") @PostMapping("/plan/listExport") @ResponseBody - public void export(@RequestBody TrainPlanListRequest request) throws IOException { + public void export(@RequestBody @Valid TrainPlanListRequest request, BindingResult bindingResult) throws IOException { + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } List list; if (!CollectionUtils.isEmpty(request.getIds())) { list = trainPlanService.listByIds(request.getIds()); @@ -248,4 +257,21 @@ } return trainPlanService.approvalDelete(request); } + + /** + * 审批操作-编辑 + * 驳回的流程放置在未通过列表中,实现进行编辑后自动审核通过发起人节点 + */ + @ApiOperation("未通过培训计划编辑(驳回后的培训计划重新编辑,仅未通过列表中的编辑按钮可调用)") + @PostMapping("/failUpdate") + @ResponseBody + public ReturnDTO failUpdate(@RequestBody @Valid MeterTrainPlan trainPlan, BindingResult bindingResult) { + Assert.isFalse(Objects.isNull(trainPlan.getId()), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + if (bindingResult.hasErrors()) { + throw new BusinessException(CoreExceptionEnum.REQUEST_NULL.getCode(), bindingResult.getFieldError().getDefaultMessage()); + } + return trainPlanService.failUpdate(trainPlan); + } } diff --git a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java index 1db2f0c..c6ff4d2 100644 --- a/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java +++ b/casic-metering-api/src/main/java/com/casic/missiles/controller/system/SystemFlowDefController.java @@ -1,5 +1,6 @@ package com.casic.missiles.controller.system; +import cn.hutool.core.lang.Assert; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.core.base.controller.ExportController; @@ -8,24 +9,27 @@ import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; import com.casic.missiles.dto.system.*; +import com.casic.missiles.enums.BusinessExceptionEnum; import com.casic.missiles.enums.ExportEnum; import com.casic.missiles.exception.BusinessException; +import com.casic.missiles.model.SystemFlowForm; import com.casic.missiles.model.exception.enums.CoreExceptionEnum; import com.casic.missiles.service.system.IFlowDefService; +import com.casic.missiles.service.system.ISystemFlowFormService; +import com.casic.missiles.utils.ConvertUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.*; import javax.validation.Valid; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; import java.util.List; +import java.util.Objects; /** * @Description: 流程管理 @@ -41,6 +45,8 @@ public class SystemFlowDefController extends ExportController { @Autowired private IFlowDefService processService; + @Autowired + private ISystemFlowFormService flowFormService; /** * 保存流程定义,流程实例中才要传业务表id @@ -134,4 +140,32 @@ public void export(@RequestBody FlowListRequest request) throws IOException { super.exportExcel(FlowProcDefDTO.class, processService.list(request), ExportEnum.FLOW_DEF_EXPORT.getSheetName()); } + + /** + * 流程表单信息列表 + */ + @ApiOperation("流程表单信息列表") + @GetMapping("/flowFormList") + @ResponseBody + public ReturnDTO> flowFormList() { + List list = flowFormService.list(); + List flowFormListResponses = ConvertUtils.sourceToTarget(list, FlowFormListResponse.class); + return ReturnUtil.success(flowFormListResponses); + } + + /** + * 获取发起人主管层级数 + */ + @ApiOperation("获取发起人主管层级数") + @GetMapping("/directorLevel") + @ResponseBody + public ReturnDTO directorLevel(Long userId) { + Assert.isFalse(Objects.isNull(userId), () -> { + throw new BusinessException(BusinessExceptionEnum.ID_NULL); + }); + int level = flowFormService.getDirectorLevel(userId); + HashMap map = new HashMap<>(); + map.put("level", level); + return ReturnUtil.success(map); + } } diff --git a/casic-metering-api/src/main/resources/config/application-dev.yml b/casic-metering-api/src/main/resources/config/application-dev.yml index d963877..c9ed538 100644 --- a/casic-metering-api/src/main/resources/config/application-dev.yml +++ b/casic-metering-api/src/main/resources/config/application-dev.yml @@ -7,16 +7,17 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true + redis: + host: 111.198.10.15 + port: 11412 + password: ew5T4K3#203lwh + database: 1 + serializer: org.springframework.data.redis.serializer.StringRedisSerializer + redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer +#jms: +# pub-sub-domain: true # session: # store-type: redis -# redis: -# host: 111.198.10.15 -# port: 11412 -# password: ew5T4K3#203lwh -# serializer: org.springframework.data.redis.serializer.StringRedisSerializer -# redisValueSerializer: org.springframework.data.redis.serializer.JdkSerializationRedisSerializer casic: #kaptcha-open: false #是否开启登录时验证码 (true/false) no-login-urls: /**/**,${casic.sysUrl}/user/login,${casic.sysUrl}/user/appLogin,${casic.sysUrl}/kaptcha/base64,${casic.sysUrl}/config/baseConfig,/route/mockToken diff --git a/casic-metering-api/src/main/resources/config/application-test.yml b/casic-metering-api/src/main/resources/config/application-test.yml index c854daa..4212bf9 100644 --- a/casic-metering-api/src/main/resources/config/application-test.yml +++ b/casic-metering-api/src/main/resources/config/application-test.yml @@ -7,8 +7,8 @@ url: jdbc:mysql://111.198.10.15:11336/casic_metering?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=UTC&&allowMultiQueries=true&nullCatalogMeansCurrent=true username: root password: Casic203 -jms: - pub-sub-domain: true +#jms: +# pub-sub-domain: true # session: # store-type: redis # redis: diff --git a/casic-metering-common/pom.xml b/casic-metering-common/pom.xml index c4c3bed..7465202 100644 --- a/casic-metering-common/pom.xml +++ b/casic-metering-common/pom.xml @@ -131,5 +131,9 @@ spring-test 5.3.15 + + org.springframework.boot + spring-boot-starter-data-redis + \ No newline at end of file diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java index 35f1b6b..cb7edd1 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/CounterSignListener.java @@ -3,12 +3,16 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.enums.AssigneeSetTypeEnum; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; import com.casic.missiles.modular.system.dao.RuRelationMapper; import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.flowable.engine.RepositoryService; @@ -47,6 +51,8 @@ private RuRelationMapper ruRelationMapper; @Resource private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; //每个任务节点的开始就会执行,在userTask中设置该监听器,保证审批人设置成功 @Override @@ -60,10 +66,9 @@ String processDefinitionId = execution.getProcessDefinitionId(); List assigneeList = new ArrayList<>(); if (CollectionUtils.isEmpty(usersValue)) { - //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中是有id的字段 + //获取当前任务所在节点的审批人列表,vue3每个节点的id是通过id("xxx")方法生成的,vue2中前端传id字段 //根据任务id获取到任务节点的审批人(已经在生成id之后设置到json) ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("pro_def_id", processDefinition.getKey()); wrapper.eq("is_del", 0); @@ -76,9 +81,9 @@ return; } - if(!CollectionUtils.isEmpty(nodeUserJsonObject.getJSONArray("nodeUserList"))){ + Integer settype = nodeUserJsonObject.getInteger("settype"); + if(!Objects.isNull(settype)){ //根据节点不同审批人类型分别进行处理 - Integer settype = nodeUserJsonObject.getInteger("settype"); if (AssigneeSetTypeEnum.ASSIGN_USER == settype) { JSONArray nodeUserArray = nodeUserJsonObject.getJSONArray("nodeUserList"); //所选审批人分类 @@ -110,17 +115,70 @@ } } } else if (AssigneeSetTypeEnum.LEADER == settype) { - // TODO: 2022/12/27 选择主管作为审批人 - + // 选择主管作为审批人 + String startUserId = execution.getVariable("root", String.class); + User user = userMapper.selectById(startUserId); + //根据发起人查部门,根据部门查主管角色查主管,每个部门只有一个主管,根据角色和部门获取主管 + //sys_role表tips字段区分角色,director定义为主管角色 + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE sr.DEPT_ID = {0}" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {0}", String.valueOf(user.getDeptId()), "director"); + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); } else if (AssigneeSetTypeEnum.SELF_SELECT == settype) { - // TODO: 2022/12/27 发起人自选审批人 + // TODO: 2022/12/27 发起人自选审批人(需求暂无此功能) } else if (AssigneeSetTypeEnum.SELF == settype) { //启动流程时设置的发起人全局变量 String startUserId = execution.getVariable("root", String.class); assigneeList.add(startUserId); } else if (AssigneeSetTypeEnum.LEADER_TOP == settype) { - // TODO: 2022/12/27 连续多级主管作为审批人 + // 连续多级主管作为审批人,审批方式由多人审批时审批方式字段决定 + //根据发起人查部门,根据部门查主管角色,根据发起人部门查父部门,根据父部门查主管角色,递归 + + //多实例加签,解决手动加签的情况,这里是还未设置审批人,无需采用多实例加签的功能,增加到assigneeList即可 + //runtimeService.addMultiInstanceExecution(); + + String startUserId = execution.getVariable("root", String.class); + + //循环查询发起人的主管id + //directorLevel一定大于1,前端做下拉限制从2级起 + Integer directorLevel = nodeConfig.getInteger("directorLevel"); + for (int i = 1; i <= directorLevel; i++) { + User user = userMapper.selectById(startUserId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(i > 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + if(CollectionUtils.isEmpty(list)){ + break; + } + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + assigneeList.add(id); + startUserId = id; + } + // TODO: 2023/1/13 以上逻辑需联调测试验证 } } diff --git a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java index 7f7118a..4fb4b6c 100644 --- a/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java +++ b/casic-metering-common/src/main/java/com/casic/missiles/listeners/flowable/TaskCreatedListener.java @@ -1,5 +1,7 @@ package com.casic.missiles.listeners.flowable; +import com.casic.missiles.redis.RedisUtil; +import com.casic.missiles.redis.key.CacheKeys; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.HistoryService; import org.flowable.engine.RuntimeService; @@ -10,6 +12,8 @@ import org.springframework.stereotype.Component; import javax.annotation.Resource; +import java.text.MessageFormat; +import java.util.Objects; /** @@ -31,6 +35,8 @@ private RuntimeService runtimeService; @Resource private HistoryService historyService; + @Resource + private RedisUtil redisUtil; //每个任务创建完成后就会执行,在userTask和根节点设置该监听器,保证根节点任务(发起人)和用户空任务完成 @Override @@ -38,8 +44,11 @@ //审批人为空,任务自动通过/自动驳回执行 //任务定义唯一标识,通过id("userTask")方法生成,即代码中设置的userTask.setId(id); String taskDefinitionKey = delegateTask.getTaskDefinitionKey(); - if (taskDefinitionKey.startsWith("root_")) { + + if (taskDefinitionKey.startsWith("root_") && Objects.isNull(redisUtil.get(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey)))) { taskService.complete(delegateTask.getId()); + //保证流程驳回到发起人后不自动审批通过 + redisUtil.set(MessageFormat.format(CacheKeys.TASK_DEFINITION_KEY, taskDefinitionKey), taskDefinitionKey); } else { if ("100000".equals(delegateTask.getAssignee())) { Object autoRefuse = delegateTask.getVariable("autoRefuse");//CounterSignListener中设置的变量 diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java new file mode 100644 index 0000000..423e69b --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/FastJson2JsonRedisSerializer.java @@ -0,0 +1,47 @@ +package com.casic.missiles.redis; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.parser.ParserConfig; +import com.alibaba.fastjson.serializer.SerializerFeature; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.SerializationException; + +import java.nio.charset.Charset; + +/** + * @Description: + * @Author: wangpeng + * @Date: 2022/8/8 10:10 + */ +public class FastJson2JsonRedisSerializer implements RedisSerializer { + + public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); + + private Class clazz; + + static { + ParserConfig.getGlobalInstance().addAccept("com.casic.missiles.modular.model"); + } + + public FastJson2JsonRedisSerializer(Class clazz) { + super(); + this.clazz = clazz; + } + + public byte[] serialize(T t) throws SerializationException { + if (t == null) { + return new byte[0]; + } + return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); + } + + public T deserialize(byte[] bytes) throws SerializationException { + if (bytes == null || bytes.length <= 0) { + return null; + } + String str = new String(bytes, DEFAULT_CHARSET); + + return (T) JSON.parseObject(str, clazz); + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java new file mode 100644 index 0000000..3a3c6e2 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisConfig.java @@ -0,0 +1,49 @@ +package com.casic.missiles.redis; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * @Description: Redis配置类 + * @Author: wangpeng + * @Date: 2022/8/8 10:06 + */ +@Configuration +public class RedisConfig { + @Bean + public RedisSerializer fastJsonJsonRedisSerializer() { + return new FastJson2JsonRedisSerializer(Object.class); + } + + @Bean + @SuppressWarnings("all") + public RedisTemplate redisTemplate(RedisConnectionFactory factory) { + RedisTemplate template = new RedisTemplate(); + template.setConnectionFactory(factory); + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); + // key采用String的序列化方式 + template.setKeySerializer(stringRedisSerializer); + // hash的key也采用String的序列化方式 + template.setHashKeySerializer(stringRedisSerializer); + // value序列化方式采用jackson + template.setValueSerializer(jackson2JsonRedisSerializer); + // hash的value序列化方式采用jackson + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.afterPropertiesSet(); + return template; + + } +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java new file mode 100644 index 0000000..9c4a980 --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/RedisUtil.java @@ -0,0 +1,319 @@ +package com.casic.missiles.redis; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.CollectionUtils; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +/** + * @Description: Redis调用工具类 + * @Author: wangpeng + * @Date: 2022/8/8 10:15 + */ +@Component +public class RedisUtil { + @Autowired + private RedisTemplate redisTemplate; + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public Object get(String key) { + return key == null ? null : redisTemplate.opsForValue().get(key); + } + + /** + * 普通缓存放入 + * + * @param key 键 + * @param value 值 + * @return true成功 false失败 + */ + public boolean set(String key, Object value) { + try { + redisTemplate.opsForValue().set(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 普通缓存放入并设置时间 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 + * @return true成功 false 失败 + */ + public boolean set(String key, Object value, long time) { + try { + if (time > 0) { + redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); + } else { + set(key, value); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void del(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + try { + redisTemplate.expire(key, time, TimeUnit.SECONDS); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + try { + return redisTemplate.hasKey(key); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashGet + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return 值 + */ + public Object hget(String key, String item) { + return redisTemplate.opsForHash().get(key, item); + } + + /** + * 获取hashKey对应的所有键值 + * + * @param key 键 + * @return 对应的多个键值 + */ + public Map hmget(String key) { + return redisTemplate.opsForHash().entries(key); + } + + /** + * HashSet + * + * @param key 键 + * @param map 对应多个键值 + * @return true 成功 false 失败 + */ + public boolean hmset(String key, Map map) { + try { + redisTemplate.opsForHash().putAll(key, map); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * HashSet 并设置时间 + * + * @param key 键 + * @param map 对应多个键值 + * @param time 时间(秒) + * @return true成功 false失败 + */ + public boolean hmset(String key, Map map, long time) { + try { + redisTemplate.opsForHash().putAll(key, map); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value) { + try { + redisTemplate.opsForHash().put(key, item, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 向一张hash表中放入数据,如果不存在将创建 + * + * @param key 键 + * @param item 项 + * @param value 值 + * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 + * @return true 成功 false失败 + */ + public boolean hset(String key, String item, Object value, long time) { + try { + redisTemplate.opsForHash().put(key, item, value); + if (time > 0) { + expire(key, time); + } + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 删除hash表中的值 + * + * @param key 键 不能为null + * @param item 项 可以使多个 不能为null + */ + public void hdel(String key, Object... item) { + redisTemplate.opsForHash().delete(key, item); + } + + /** + * 判断hash表中是否有该项的值 + * + * @param key 键 不能为null + * @param item 项 不能为null + * @return true 存在 false不存在 + */ + public boolean hHasKey(String key, String item) { + return redisTemplate.opsForHash().hasKey(key, item); + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @return + */ + public boolean lSet(String key, List value) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 将list放入缓存 + * + * @param key 键 + * @param value 值 + * @param time 时间(秒) + * @return + */ + public boolean lSet(String key, List value, long time) { + try { + redisTemplate.opsForList().rightPushAll(key, value); + if (time > 0) + expire(key, time); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * 获取list缓存的内容 + * + * @param key 键 + * @param start 开始 + * @param end 结束 0 到 -1代表所有值 + * @return + */ + public List lGet(String key, long start, long end) { + try { + return redisTemplate.opsForList().range(key, start, end); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + /** + * 获取list缓存的长度 + * + * @param key 键 + * @return + */ + public long lGetListSize(String key) { + try { + return redisTemplate.opsForList().size(key); + } catch (Exception e) { + e.printStackTrace(); + return 0; + } + } + +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java new file mode 100644 index 0000000..8d9482f --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/redis/key/CacheKeys.java @@ -0,0 +1,10 @@ +package com.casic.missiles.redis.key; + +/** + * @Description: Redis key + * @Author: wangpeng + * @Date: 2022/8/8 10:26 + */ +public interface CacheKeys { + String TASK_DEFINITION_KEY = "missiles:metering:taskDefinitionKey:{0}"; +} diff --git a/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java new file mode 100644 index 0000000..3db6a7d --- /dev/null +++ b/casic-metering-common/src/main/java/com/casic/missiles/utils/ExUtils.java @@ -0,0 +1,19 @@ +package com.casic.missiles.utils; + +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * @Description: flowable条件表达式(setConditionExpression)执行的bean + * @Author: wangpeng + * @Date: 2023/1/8 14:27 + */ +@Component +public class ExUtils { + public Boolean strContains(String controlId,String...values){ + List list = Arrays.asList(values); + return list.contains(controlId); + } +} diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java index bd486bc..8a42257 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterFileMapper.java @@ -24,7 +24,7 @@ int updateEffectiveStatusByTime(); - List selectApprovalList(Page page, FileApprovalListRequest request); + List selectApprovalList(Page page, @Param("request") FileApprovalListRequest request); List selectDraftListForApproval(@Param("request") FileApprovalListRequest request); diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java index 561c0ad..8b7b2a7 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterStaffMapper.java @@ -29,5 +29,5 @@ void addStaffList(@Param("list") List list); - List meterStaffStatistic(@Param("startTime")String startTime,@Param("endTime")String endTime); + List meterStaffStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java index b536351..80bdddb 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTraceSupplierMapper.java @@ -5,6 +5,7 @@ import com.casic.missiles.dto.meter.TraceSupplierApprovalListRequest; import com.casic.missiles.dto.meter.TraceSupplierDetailResponse; import com.casic.missiles.model.MeterTraceSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -20,9 +21,9 @@ Long selectMaxSupplierNo(); - TraceSupplierDetailResponse selectTraceSupplierById(Long id); + TraceSupplierDetailResponse selectTraceSupplierById(@Param("id") Long id); - List selectDraftListForApproval(TraceSupplierApprovalListRequest request); + List selectDraftListForApproval(@Param("request") TraceSupplierApprovalListRequest request); - List selectBatchForApproval(TraceSupplierApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request") TraceSupplierApprovalListRequest request, @Param("businessKey") List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java index 7dcc79c..0dccfc6 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainLogMapper.java @@ -3,6 +3,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.casic.missiles.dto.meter.TrainLogDetailResponse; import com.casic.missiles.model.MeterTrainLog; +import org.apache.ibatis.annotations.Param; /** *

@@ -16,5 +17,5 @@ Long selectMaxTrainLogNo(); - TrainLogDetailResponse selectTrainLogById(Long id); + TrainLogDetailResponse selectTrainLogById(@Param("id") Long id); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java index 26d24b7..a3f80ba 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/meter/MeterTrainPlanMapper.java @@ -26,7 +26,7 @@ List meterTrainStatistic(@Param("startTime")String startTime, @Param("endTime")String endTime); - List selectDraftListForApproval(TrainPlanApprovalListRequest request); + List selectDraftListForApproval(@Param("request")TrainPlanApprovalListRequest request); - List selectBatchForApproval(TrainPlanApprovalListRequest request, List businessKey); + List selectBatchForApproval(@Param("request")TrainPlanApprovalListRequest request, @Param("businessKey")List businessKey); } diff --git a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java index ac4ff15..30b8331 100644 --- a/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java +++ b/casic-metering-dao/src/main/java/com/casic/missiles/mapper/system/FlowDefMapper.java @@ -13,7 +13,7 @@ * @Date: 2022/12/12 18:19 */ public interface FlowDefMapper { - List selectDeployListPage(Page page, FlowListRequest request); + List selectDeployListPage(@Param("page") Page page, @Param("request") FlowListRequest request); List selectDeployList(@Param("request") FlowListRequest request); } diff --git a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml index f79552f..77ebaa9 100644 --- a/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml +++ b/casic-metering-dao/src/main/resources/mapper/meter/MeterTraceSupplierMapper.xml @@ -18,9 +18,13 @@ + + + + @@ -49,7 +53,8 @@ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java index a20721b..4e63576 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/FileListRequest.java @@ -4,6 +4,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -63,4 +64,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java index c79bd12..c488f9f 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierApprovalListResponse.java @@ -61,23 +61,41 @@ private String businessScope; /** + * 公司地址-国家 + */ + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") + private String companyCountry; + + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + @ApiModelProperty(value = "创建时间", dataType = "String") private String createTime; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java index 82c56e5..2966854 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierDetailResponse.java @@ -107,27 +107,39 @@ /** * 公司地址-国家 */ - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") private String companyCountry; + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + private String companyCountryName; + /** * 公司地址-省 */ - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") private String companyProvince; + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + private String companyProvinceName; + /** * 公司地址-市 */ - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") private String companyCity; + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + private String companyCityName; + /** * 公司地址-区 */ - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") private String companyArea; + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + private String companyAreaName; + /** * 公司地址-详细地址 */ diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java index 237641c..1143280 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TraceSupplierListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -34,4 +35,8 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; + } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java index 1c22d1b..b168e8c 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/meter/TrainPlanListRequest.java @@ -3,6 +3,7 @@ import io.swagger.annotations.ApiModelProperty; import lombok.Data; +import javax.validation.constraints.NotBlank; import java.util.List; /** @@ -49,4 +50,7 @@ @ApiModelProperty(value = "筛选ids", dataType = "List") private List ids; + @NotBlank(message = "表单id不能为空") + @ApiModelProperty(value = "表单id(流程定义对应的表单id,等价于业务id)", dataType = "String") + private String formId; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java new file mode 100644 index 0000000..6b28ddf --- /dev/null +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowFormListResponse.java @@ -0,0 +1,19 @@ +package com.casic.missiles.dto.system; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Description: 表单列表请求响应 + * @Author: wangpeng + * @Date: 2023/1/12 8:52 + */ +@ApiModel +@Data +public class FlowFormListResponse { + @ApiModelProperty(value = "配置表单id", dataType = "String") + private String formId; + @ApiModelProperty(value = "配置表单名称", dataType = "String") + private String formName; +} diff --git a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java index 6dff546..6ed94f1 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/dto/system/FlowListRequest.java @@ -30,9 +30,12 @@ @ApiModelProperty("配置表单id") private String formId; +// +// @ApiModelProperty("流程负责人id") +// private Long directorId; - @ApiModelProperty("流程负责人id") - private Long directorId; + @ApiModelProperty("流程负责人名字") + private String directorName; // @ApiModelProperty("版本") // private int version; @@ -43,7 +46,11 @@ @ApiModelProperty("流程定义状态: 1:激活,2:中止") private Integer suspensionState; - @ApiModelProperty("部署时间") + @ApiModelProperty("部署时间(开始)") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") - private String deploymentTime; + private String deploymentStartTime; + + @ApiModelProperty("部署时间(结束)") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private String deploymentEndTime; } diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java index 94ca3a2..32da756 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterFile.java @@ -152,7 +152,7 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java index f279e08..ffded71 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTraceSupplier.java @@ -157,35 +157,51 @@ /** * 公司地址-国家 */ - @ExcelProperty("公司地址-国家") - @ApiModelProperty(value = "公司地址-国家", dataType = "String") + @ApiModelProperty(value = "公司地址-国家(code)", dataType = "String") @TableField("company_country") private String companyCountry; + @ExcelProperty("公司地址-国家") + @ApiModelProperty(value = "公司地址-国家(名称)", dataType = "String") + @TableField("company_country_name") + private String companyCountryName; + /** * 公司地址-省 */ - @ExcelProperty("公司地址-省") - @ApiModelProperty(value = "公司地址-省", dataType = "String") + @ApiModelProperty(value = "公司地址-省(code)", dataType = "String") @TableField("company_province") private String companyProvince; + @ExcelProperty("公司地址-省") + @ApiModelProperty(value = "公司地址-省(名称)", dataType = "String") + @TableField("company_province_name") + private String companyProvinceName; + /** * 公司地址-市 */ - @ExcelProperty("公司地址-市") - @ApiModelProperty(value = "公司地址-市", dataType = "String") + @ApiModelProperty(value = "公司地址-市(code)", dataType = "String") @TableField("company_city") private String companyCity; + @ExcelProperty("公司地址-市") + @ApiModelProperty(value = "公司地址-市(名称)", dataType = "String") + @TableField("company_city_name") + private String companyCityName; + /** * 公司地址-区 */ - @ExcelProperty("公司地址-区") - @ApiModelProperty(value = "公司地址-区", dataType = "String") + @ApiModelProperty(value = "公司地址-区(code)", dataType = "String") @TableField("company_area") private String companyArea; + @ExcelProperty("公司地址-区") + @ApiModelProperty(value = "公司地址-区(名称)", dataType = "String") + @TableField("company_area_name") + private String companyAreaName; + /** * 公司地址-详细地址 */ @@ -197,31 +213,47 @@ /** * 开票地址-国家 */ - @ApiModelProperty(value = "开票地址-国家", dataType = "String") + @ApiModelProperty(value = "开票地址-国家(code)", dataType = "String") @TableField("invoice_country") private String invoiceCountry; + @ApiModelProperty(value = "开票地址-国家(名称)", dataType = "String") + @TableField("invoice_country_name") + private String invoiceCountryName; + /** * 开票地址-省 */ - @ApiModelProperty(value = "开票地址-省", dataType = "String") - @TableField("invoice_province") + @ApiModelProperty(value = "开票地址-省(code)", dataType = "String") + @TableField("invoice_province_name") private String invoiceProvince; + @ApiModelProperty(value = "开票地址-省(名称)", dataType = "String") + @TableField("invoice_province") + private String invoiceProvinceName; + /** * 开票地址-市 */ - @ApiModelProperty(value = "开票地址-市", dataType = "String") + @ApiModelProperty(value = "开票地址-市(code)", dataType = "String") @TableField("invoice_city") private String invoiceCity; + @ApiModelProperty(value = "开票地址-市(名称)", dataType = "String") + @TableField("invoice_city_name") + private String invoiceCityName; + /** * 开票地址-区 */ - @ApiModelProperty(value = "开票地址-区", dataType = "String") + @ApiModelProperty(value = "开票地址-区(code)", dataType = "String") @TableField("invoice_area") private String invoiceArea; + @ApiModelProperty(value = "开票地址-区(名称)", dataType = "String") + @TableField("invoice_area_name") + private String invoiceAreaName; + /** * 开票地址-详细地址 */ @@ -257,11 +289,18 @@ /** * 流程实例id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过文件编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; /** + * 登录者用户id(保证流程发起人为登录用户),接口中获取,工作流中使用 + */ + @ApiModelProperty(hidden = true) + @TableField("create_user_id") + private Long createUserId; + + /** * 备注 */ @ExcelProperty("备注") diff --git a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java index d2225e8..012cf43 100644 --- a/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java +++ b/casic-metering-model/src/main/java/com/casic/missiles/model/MeterTrainPlan.java @@ -148,7 +148,7 @@ /** * 流程定义id */ - @ApiModelProperty(hidden = true) + @ApiModelProperty(value = "流程实例id(未通过培训计划编辑接口必传参数)", dataType = "String") @TableField("process_id") private String processId; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java index d6b34b9..67b11d2 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/BaseApprovalServiceImpl.java @@ -250,7 +250,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .orderByProcessInstanceStartTime().desc() .list(); @@ -264,7 +264,7 @@ .deploymentId(flowForm.getDeployId()) .or() .unfinished() - .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回操作中设置为该状态 + .processInstanceBusinessStatus(ApprovalStatusEnum.IN_APPROVED) //查询审批中状态,因为驳回后的编辑操作中设置为该状态 .endOr() .startedBy(String.valueOf(user.getId())) .orderByProcessInstanceStartTime().desc() diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java index 1c288a3..1207b86 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/flowable/ApprovalOperateServiceImpl.java @@ -135,10 +135,10 @@ //3驳回意见 taskService.addComment(task.getId(), task.getProcessInstanceId(),"3", request.getComments()); } - //设置驳回状态为审批中 - runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + //设置驳回状态为未通过 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.FAILED); - //驳回至指定节点 + //驳回至指定节点,现驳回到起始节点 HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .orderByHistoricTaskInstanceStartTime() @@ -184,7 +184,8 @@ //设置发起人 Authentication.setAuthenticatedUserId(String.valueOf(user.getId())); - Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); + HistoricTaskInstance task = historyService.createHistoricTaskInstanceQuery().taskId(request.getTaskId()).singleResult(); +// Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); //只有发起者才能撤回 HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() @@ -217,7 +218,7 @@ Task task = taskService.createTaskQuery().taskId(request.getTaskId()).singleResult(); - // TODO: 2022/12/29 测试删除后查询时的deleted + // TODO: 2022/12/29 需联调测试删除后查询时的deleted runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"删除"); return ReturnUtil.success(); diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java index ca6998d..928f4e4 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterFileServiceImpl.java @@ -31,7 +31,10 @@ import com.casic.missiles.utils.NumberGeneratorUtil; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -62,6 +65,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, FileListRequest request) { @@ -137,7 +144,6 @@ return ReturnUtil.success(); } throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); - } @Override @@ -195,6 +201,27 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + @Transactional + public ReturnDTO failUpdate(MeterFile file) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (meterFileMapper.updateById(file) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(file.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(FileApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -274,6 +301,9 @@ } private QueryWrapper getWrapper(FileListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getFileNo()), "file_no", request.getFileNo()); wrapper.like(StringUtils.isNotBlank(request.getFileName()), "file_name", request.getFileName()); @@ -288,7 +318,7 @@ "{0} <= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getEffectiveEndTime()), "{0} >= DATE_FORMAT(effective_time,'%Y-%m-%d')", request.getEffectiveEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByAsc("effective_status").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java index 7f07600..fea55b7 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTraceSupplierServiceImpl.java @@ -28,7 +28,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +63,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TraceSupplierListRequest request) { @@ -85,6 +92,10 @@ String supplierNo = NumberGeneratorUtil.getContactNo("sygf", maxNo); traceSupplier.setSupplierNo(supplierNo); traceSupplier.setApprovalStatus(ApprovalStatusEnum.DRAFT); //草稿箱状态 + Assert.isFalse(Objects.isNull(ShiroKit.getUser()), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + traceSupplier.setCreateUserId(ShiroKit.getUser().getId()); //登录者用户id int insertFlag = traceSupplierMapper.insert(traceSupplier); Assert.isFalse(insertFlag <= 0, () -> { throw new BusinessException(BusinessExceptionEnum.TRACE_SUPPLIER_SAVE_FAILED); @@ -173,6 +184,26 @@ throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); } + @Override + public ReturnDTO failUpdate(MeterTraceSupplier traceSupplier) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (traceSupplierMapper.updateById(traceSupplier) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(traceSupplier.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + private List handleApprovalStatus(TraceSupplierApprovalListRequest request) { List approvalList = new ArrayList<>(); List businessKey = new ArrayList<>(); @@ -273,11 +304,14 @@ private QueryWrapper getWrapper(TraceSupplierListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getSupplierNo()), "supplier_no", request.getSupplierNo()); wrapper.like(StringUtils.isNotBlank(request.getSupplierName()), "supplier_name", request.getSupplierName()); wrapper.like(StringUtils.isNotBlank(request.getBusinessContent()), "business_content", request.getBusinessContent()); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java index 516ff34..7c3bf41 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/meter/MeterTrainPlanServiceImpl.java @@ -30,7 +30,10 @@ import com.casic.missiles.utils.ConvertUtils; import com.casic.missiles.utils.NumberGeneratorUtil; import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.RuntimeService; +import org.flowable.engine.TaskService; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -64,6 +67,10 @@ private IBaseApprovalService baseApprovalService; @Autowired private ApprovalOperateService approvalOperateService; + @Resource + private TaskService taskService; + @Resource + private RuntimeService runtimeService; @Override public Page listPage(Page page, TrainPlanListRequest request) { @@ -162,6 +169,26 @@ } @Override + public ReturnDTO failUpdate(MeterTrainPlan trainPlan) { + AuthUser user = ShiroKit.getUser(); + Assert.isFalse(Objects.isNull(user), () -> { + throw new BusinessException(BusinessExceptionEnum.LOGIN_USER_ACQUIRE_FAILED); + }); + if (trainPlanMapper.updateById(trainPlan) > 0) { + //发起人审批通过 + Task task = taskService.createTaskQuery() + .processInstanceId(trainPlan.getProcessId()) + .active() + .singleResult(); + taskService.complete(task.getId()); + //更新状态为审批中 + runtimeService.updateBusinessStatus(task.getProcessInstanceId(), ApprovalStatusEnum.IN_APPROVED); + return ReturnUtil.success(); + } + throw new BusinessException(BusinessExceptionEnum.HANDLE_FAILED); + } + + @Override @Transactional public ReturnDTO submitTrainPlan(BaseApprovalSubmitRequest request) { //1.根据表单id获取流程定义id @@ -299,6 +326,9 @@ } private QueryWrapper getWrapper(TrainPlanListRequest request) { + //flowable中已通过状态的业务id列表 + List passedList = baseApprovalService.getPassedList(request.getFormId()); + QueryWrapper wrapper = new QueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(request.getDirector()), "director", request.getDirector()); wrapper.like(StringUtils.isNotBlank(request.getEffectiveCompany()), "effective_company", request.getEffectiveCompany()); @@ -311,7 +341,7 @@ "{0} <= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateStartTime().split(" ")[0]); wrapper.apply(StringUtils.isNotBlank(request.getCreateEndTime()), "{0} >= DATE_FORMAT(create_time,'%Y-%m-%d')", request.getCreateEndTime().split(" ")[0]); - wrapper.eq("approval_status", ApprovalStatusEnum.PASSED); //审批状态:已通过 + wrapper.in("id", passedList); wrapper.eq("is_del", 0); wrapper.orderByDesc("train_time").orderByDesc("create_time"); return wrapper; diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java index c994e8c..243321f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/FlowDefDefServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.casic.missiles.dto.ReturnDTO; import com.casic.missiles.dto.ReturnUtil; @@ -14,8 +15,13 @@ import com.casic.missiles.mapper.system.FlowDefMapper; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.RuRelation; +import com.casic.missiles.modular.system.model.User; +import com.casic.missiles.modular.system.service.IUserRoleRelationService; import com.casic.missiles.service.system.IFlowDefService; import com.casic.missiles.utils.SnowflakeUtil; +import com.casic.missiles.utils.SpringContextUtil; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import lombok.extern.slf4j.Slf4j; @@ -33,6 +39,7 @@ import org.flowable.validation.ProcessValidatorFactory; import org.flowable.validation.ValidationError; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -139,7 +146,12 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义保存失败"); } - }catch (Exception e){ + } catch (DuplicateKeyException e) { + log.error("该表单已保存过流程定义,异常信息:{}", e.getMessage()); + //新增异常则删除刚部署的流程 + repositoryService.deleteDeployment(deploy.getId(), true); + return ReturnUtil.failed("流程定义保存异常,该表单已存在流程定义"); + } catch (Exception e) { log.error("流程定义保存异常,异常信息:{}", e.getMessage()); //新增异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -196,7 +208,7 @@ new BpmnAutoLayout(bpmnModel).execute(); // System.err.println(new String(new BpmnXMLConverter().convertToXML(bpmnModel))); - //流程部署 + //流程部署,更新 Deployment deploy = repositoryService.createDeployment() .tenantId(directorId)//租户标识符,这是一个字符串,可以是UUID、部门id .addBpmnModel(name + ".bpmn", bpmnModel) @@ -225,7 +237,7 @@ repositoryService.deleteDeployment(deploy.getId(), true); return ReturnUtil.failed("流程定义更新失败"); } - }catch (Exception e){ + } catch (Exception e) { log.error("流程定义更新异常,异常信息:{}", e.getMessage()); //更新异常则删除刚部署的流程 repositoryService.deleteDeployment(deploy.getId(), true); @@ -266,7 +278,7 @@ //流程定义表单表删除 QueryWrapper wrapper = new QueryWrapper<>(); wrapper.eq("deploy_id", request.getDeployId()); - if(flowFormMapper.delete(wrapper) <= 0){ + if (flowFormMapper.delete(wrapper) <= 0) { log.error("流程定义删除失败,deployId:{}", request.getDeployId()); return ReturnUtil.failed("流程定义删除失败"); } @@ -381,30 +393,50 @@ //一个分支的子节点 JSONObject childNode = element.getJSONObject("childNode"); //一个分支的名字和表达式 - String nodeName = element.getString("nodeName");String expression = ""; + String nodeName = element.getString("nodeName"); + String expression = ""; expression = element.getString("conditionExpression"); - if(StringUtils.isEmpty(expression)){ + if (StringUtils.isEmpty(expression)) { JSONArray nodeUserList = element.getJSONArray("nodeUserList"); //1具体人员 2角色 3部门 //构造条件表达式 Iterator iterator = nodeUserList.stream().iterator(); List userIds = new ArrayList<>(); - while(iterator.hasNext()){ - HashMap map = (HashMap)iterator.next(); - if("1".equals(String.valueOf(map.get("type")))){ + while (iterator.hasNext()) { + HashMap map = (HashMap) iterator.next(); + if ("1".equals(String.valueOf(map.get("type")))) { + //用户id String targetId = String.valueOf(map.get("targetId")); userIds.add(targetId); - }else if("2".equals(String.valueOf(map.get("type")))){ - - }else if("3".equals(String.valueOf(map.get("type")))){ - + } else if ("2".equals(String.valueOf(map.get("type")))) { + //角色id + String targetId = String.valueOf(map.get("targetId")); + IUserRoleRelationService relationService = SpringContextUtil.getBean(IUserRoleRelationService.class); + BaseMapper baseMapper = relationService.getBaseMapper(); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("ROLEID", targetId); + List ruRelations = baseMapper.selectList(wrapper); + ruRelations.forEach(ruRelation -> { + userIds.add(String.valueOf(ruRelation.getUserId())); + }); + } else if ("3".equals(String.valueOf(map.get("type")))) { + //部门id + String targetId = String.valueOf(map.get("targetId")); + UserMapper userMapper = SpringContextUtil.getBean(UserMapper.class); + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("DEPT_ID", targetId); + List users = userMapper.selectList(wrapper); + users.forEach(user -> { + userIds.add(String.valueOf(user.getId())); + }); } } String str = StringUtils.join(userIds, ","); - // TODO: 2022/12/26 此处nodeName应为实例的发起人,但json不知对应何字段 - // TODO: 2022/12/26 ExUtils为bean实例方法,待添加 - expression = "exUtils."+"strContains("+nodeName+","+str+")"; - + // todo: 以下需验证,若不行,采用:流程实例的发起人通过TaskCreatedListener监听器设置,这里再获取,或者可能需要再加个监听器获取 + // ExUtils为bean实例方法,已添加 + // flowable表达式会自动识别流程变量,以下root也可识别为实例创建时的具体值,比如:${price < 100},price就是一个流程变量的值,UEL表达式的结果为布尔值 + String starterId = "root"; + expression = "exUtils." + "strContains(" + starterId + "," + str + ")"; } if (Objects.isNull(childNode)) { @@ -668,7 +700,7 @@ //多实例,在业务流程中,为特定步骤定义重复的方式 MultiInstanceLoopCharacteristics multiInstanceLoopCharacteristics = new MultiInstanceLoopCharacteristics(); String examineMode = flowNode.getString("examineMode"); - // 审批人集合参数,会签集合变量名称,flowable:collection=“assigneeList” + // 审批人集合参数,会签集合变量名称,flowable:collection=“id+assigneeList” //collection 赋值使用原因: // 通过上面的配置,当指定了 collection 的流程变量后,在引擎自动生成多任务时每个任务的assign都有值了。 // 就不再需要增加业务逻辑处理(遍历多任务后然后拿到审批人,依次给每个任务塞 处理人) diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java index d1266ae..8d70f8f 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/Impl/system/SystemFlowFormServiceImpl.java @@ -1,11 +1,24 @@ package com.casic.missiles.service.Impl.system; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.baomidou.mybatisplus.extension.toolkit.SqlRunner; import com.casic.missiles.mapper.system.SystemFlowFormMapper; import com.casic.missiles.model.SystemFlowForm; +import com.casic.missiles.modular.system.dao.DeptMapper; +import com.casic.missiles.modular.system.dao.UserMapper; +import com.casic.missiles.modular.system.model.Dept; +import com.casic.missiles.modular.system.model.User; import com.casic.missiles.service.system.ISystemFlowFormService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + /** *

* 服务实现类 @@ -16,5 +29,47 @@ */ @Service public class SystemFlowFormServiceImpl extends ServiceImpl implements ISystemFlowFormService { + @Resource + private UserMapper userMapper; + @Resource + private DeptMapper deptMapper; + @Override + public int getDirectorLevel(Long userId) { + //需要保证用户所在组织机构一定要有个角色的TIPS为director的角色的人 + int level = 0; + return getDirectorList(level, userId); + } + + private int getDirectorList(int level, Long userId) { + User user = userMapper.selectById(userId); + Long deptId = user.getDeptId(); + Dept dept = deptMapper.selectById(deptId); + String pids = dept.getPids(); + List deptIds = new ArrayList<>(); + if(StringUtils.isNotEmpty(pids)){ + String replace = pids.replace("[", "").replace("]", ""); + pids = replace.substring(0, replace.length() - 1); + //在角色管理中配置的角色所在组织机构,要保证该机构的子组织结构使用该角色也可以生效 + deptIds = Arrays.asList(pids.split(",")); + } + if(level >= 1){ + //主管获取所在的上级部门 + deptId = dept.getPid(); + } + List> list = SqlRunner.db().selectList("select su.ID as id from sys_role sr " + + "JOIN sys_ru_relation srr ON sr.ID = srr.ROLEID " + + "JOIN sys_user su ON srr.USERID = su.ID " + + "WHERE (sr.DEPT_ID = {2} or sr.DEPT_ID in {0})" + + "AND sr.TIPS = {1}" + + "AND su.DEPT_ID = {2}", deptIds, "director", String.valueOf(deptId)); + + if(CollectionUtils.isEmpty(list)){ + return level; + } + level += 1; + Map idMap = list.get(0); + String id = String.valueOf(idMap.get("id")); + return getDirectorList(level, Long.valueOf(id)); + } } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java index b1f17a9..a36ae80 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterFileService.java @@ -39,4 +39,6 @@ List approvalListPage(Page page, FileApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterFile meterFile); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java index 5d114a6..2d7de64 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTraceSupplierService.java @@ -42,4 +42,6 @@ List approvalListPage(Page page, TraceSupplierApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterTraceSupplier traceSupplier); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java index 47131aa..5043880 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/meter/IMeterTrainPlanService.java @@ -41,4 +41,6 @@ List approvalListPage(Page page, TrainPlanApprovalListRequest request); ReturnDTO approvalDelete(ApprovalDeleteRequest request); + + ReturnDTO failUpdate(MeterTrainPlan trainPlan); } diff --git a/casic-metering-service/src/main/java/com/casic/missiles/service/system/ISystemFlowFormService.java b/casic-metering-service/src/main/java/com/casic/missiles/service/system/ISystemFlowFormService.java index 5e3ab7b..70d391b 100644 --- a/casic-metering-service/src/main/java/com/casic/missiles/service/system/ISystemFlowFormService.java +++ b/casic-metering-service/src/main/java/com/casic/missiles/service/system/ISystemFlowFormService.java @@ -13,4 +13,5 @@ */ public interface ISystemFlowFormService extends IService { + int getDirectorLevel(Long userId); } diff --git a/pom.xml b/pom.xml index b67aad3..6c8ea53 100644 --- a/pom.xml +++ b/pom.xml @@ -87,38 +87,6 @@ fastjson ${fastjson.version} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.flowable