Browse Source

入职审批接口

dongpo 1 year ago
parent
commit
59e391759a

+ 1 - 0
yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java

@@ -86,6 +86,7 @@ public interface ErrorCodeConstants {
 
 
     ErrorCode SERVICE_ID_NOT_EXISTS = new ErrorCode(1009011000, "业务单据ID不能为空");
+    ErrorCode DELETE_FAIL_NOT_STAGING = new ErrorCode(1009011001, "非暂存状态不能删除");
     // ========== 入职流程信息 1-009-012-000 ==========
     ErrorCode OA_ENTRY_NOT_EXISTS = new ErrorCode(1009012000, "入职流程信息不存在");
 

+ 92 - 61
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/entry/OaEntryController.java

@@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.bpm.controller.admin.oa.entry;
 
 import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
@@ -10,12 +9,12 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntryPageReqVO
 import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntryRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntrySaveReqVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
-import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.entry.OaEntryDO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskReturnReqVO;
 import cn.iocoder.yudao.module.bpm.service.oa.entry.OaEntryService;
+import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
@@ -27,10 +26,9 @@ import java.util.List;
 
 import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
 
-@Tag(name = "管理后台 - 入职流程信息")
+@Tag(name = "管理后台 - 入职审批流程信息")
 @RestController
 @RequestMapping("/bpm/oa-entry")
 @Validated
@@ -39,86 +37,119 @@ public class OaEntryController {
     @Resource
     private OaEntryService oaEntryService;
 
-    @PostMapping("/start")
-    @Operation(summary = "提交或暂存入职流程信息")
-    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:start')")
-    public CommonResult<Integer> startOaEntry(@Valid @RequestBody OaEntrySaveReqVO createReqVO) {
-        return success(oaEntryService.startOaEntry(getLoginUserId(), createReqVO));
+    @PostMapping("/staging")
+    @Operation(summary = "暂存入职审批流程信息")
+    @ApiOperationSupport(order = 1)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:staging')")
+    public CommonResult<Long> startOaEntry(@RequestBody OaEntrySaveReqVO stagingReqVO) {
+        Long oaEntryId = oaEntryService.stagingOaEntry(stagingReqVO);
+        return success(oaEntryId, "暂存成功");
     }
 
-    @PostMapping("/completeTure")
-    @Operation(summary = "审批同意入职流程信息")
-    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:complete-true')")
-    public CommonResult<Integer> completeTrueOaEntry(@Valid @RequestBody BpmTaskApproveReqVO reqVO) {
-        return success(oaEntryService.completeTrueOaEntry(getLoginUserId(), reqVO));
+    @PostMapping("/commit")
+    @Operation(summary = "提交入职审批流程信息")
+    @ApiOperationSupport(order = 2)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:commit')")
+    public CommonResult<Long> commitOaEntry(@Valid @RequestBody OaEntrySaveReqVO commitReqVO) {
+        Long oaEntryId = oaEntryService.commitOaEntry(commitReqVO);
+        return success(oaEntryId, "提交成功");
     }
 
-    @PostMapping("/completeFalse")
-    @Operation(summary = "驳回或撤回入职流程信息")
-    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:complete-false')")
-    public CommonResult<Integer> completeFalseOaEntry(@Valid @RequestBody BpmTaskApproveReqVO reqVO) {
-        return success(oaEntryService.completeFalseOaEntry(getLoginUserId(), reqVO));
+    @PostMapping("/agree")
+    @Operation(summary = "审批同意入职审批流程信息")
+    @ApiOperationSupport(order = 3)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:agree')")
+    public CommonResult<Long> agreeOaEntry(@Valid @RequestBody BpmTaskApproveReqVO agreeReqVO) {
+        Long result = oaEntryService.agreeOaEntry(agreeReqVO);
+        return success(result, "审批成功");
     }
 
-    @PostMapping("/updateComplete")
-    @Operation(summary = "驳回和撤回后再次提交或关闭入职流程信息")
-    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:update-complete')")
-    public CommonResult<Integer> updateCompleteOaEntry(@Valid @RequestBody OaEntrySaveReqVO createReqVO) {
-        return success(oaEntryService.updateCompleteOaEntry(getLoginUserId(), createReqVO, createReqVO.getBpmTaskApproveReqVO()));
+    @PostMapping("/disagree")
+    @Operation(summary = "驳回入职审批流程信息")
+    @ApiOperationSupport(order = 4)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:disagree')")
+    public CommonResult<Long> disagreeOaEntry(@Valid @RequestBody BpmTaskReturnReqVO disagreeReqVO) {
+        Long result = oaEntryService.disagreeOaEntry(disagreeReqVO);
+        return success(result, "驳回成功");
     }
 
-//    @PostMapping("/return")
-//    @Operation(summary = "撤回入职流程信息")
-//    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:start')")
-//    public CommonResult<Integer> returnCompelete(@Valid @RequestBody OaEntrySaveReqVO createReqVO,@Valid @RequestBody BpmTaskApproveReqVO reqVO) {
-//        return success(oaEntryService.completeOaEntry(getLoginUserId(),createReqVO,reqVO));
-//    }
-
-//    @PutMapping("/update")
-//    @Operation(summary = "更新入职流程信息")
-//    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:update')")
-//    public CommonResult<Boolean> updateOaEntry(@Valid @RequestBody OaEntrySaveReqVO updateReqVO) {
-//        oaEntryService.updateOaEntry(updateReqVO);
-//        return success(true);
-//    }
+    @PostMapping("/revocation")
+    @Operation(summary = "撤回入职审批流程信息")
+    @ApiOperationSupport(order = 5)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:revocation')")
+    public CommonResult<Long> revocationOaEntry(@Valid @RequestBody BpmTaskApproveReqVO revocationReqVO) {
+        Long result = oaEntryService.revocationOaEntry(revocationReqVO);
+        return success(result, "撤回成功");
+    }
+
+    @PostMapping("/reCommit")
+    @Operation(summary = "驳回或撤回后再次提交入职审批流程信息")
+    @ApiOperationSupport(order = 6)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:re-commit')")
+    public CommonResult<Long> reCommitOaEntry(@Valid @RequestBody OaEntrySaveReqVO reCommitReqVO) {
+        Long result = oaEntryService.reCommitOaEntry(reCommitReqVO);
+        return success(result, "再次提交成功");
+    }
+
+    @PostMapping("/close")
+    @Operation(summary = "驳回或撤回后关闭入职审批流程信息")
+    @ApiOperationSupport(order = 7)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:close')")
+    public CommonResult<Long> updateCompleteOaEntry(@RequestBody OaEntrySaveReqVO closeReqVO) {
+        Long result = oaEntryService.closeOaEntry(closeReqVO);
+
+        return success(result, "关闭成功");
+    }
 
     @DeleteMapping("/delete")
-    @Operation(summary = "删除入职流程信息")
+    @Operation(summary = "删除入职审批流程信息")
+    @ApiOperationSupport(order = 8)
     @Parameter(name = "id", description = "编号", required = true)
-    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:delete')")
-    public CommonResult<Boolean> deleteOaEntry(@RequestParam("id") Integer id) {
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:delete')")
+    public CommonResult<Boolean> deleteOaEntry(@RequestParam("id") Long id) {
         oaEntryService.deleteOaEntry(id);
-        return success(true);
+        return success(true, "删除成功");
     }
 
     @GetMapping("/get")
-    @Operation(summary = "获得入职流程信息")
-    @Parameter(name = "id", description = "编号", required = true, example = "1024")
-    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:query')")
-    public CommonResult<OaEntryRespVO> getOaEntry(@RequestParam("id") Integer id) {
-        OaEntryDO oaEntry = oaEntryService.getOaEntry(id);
-        return success(BeanUtils.toBean(oaEntry, OaEntryRespVO.class));
+    @Operation(summary = "根据id获得入职审批流程信息")
+    @Parameter(name = "id", description = "编号", required = true, example = "1")
+    @ApiOperationSupport(order = 9)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:query-id')")
+    public CommonResult<OaEntryRespVO> getOaEntry(@RequestParam("id") Long id) {
+        OaEntryRespVO respVO = oaEntryService.getOaEntry(id);
+        return success(respVO, "查询对象成功");
+    }
+
+    @GetMapping("/getByProcInstId")
+    @Operation(summary = "根据流程实例id获得入职审批流程信息")
+    @Parameter(name = "procInstId", description = "流程实例id", required = true, example = "9528a78d-457e-11ef-853c-4c034fce6445")
+    @ApiOperationSupport(order = 10)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:query-proc-inst-id')")
+    public CommonResult<OaEntryRespVO> getOaEntryByProcInstId(@RequestParam("procInstId") String procInstId) {
+        OaEntryRespVO respVO = oaEntryService.getOaEntryByProcInstId(procInstId);
+        return success(respVO, "查询对象成功");
     }
 
     @GetMapping("/page")
-    @Operation(summary = "获得入职流程信息分页")
-    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:query')")
+    @Operation(summary = "获得入职审批流程信息分页")
+    @ApiOperationSupport(order = 11)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:query-page')")
     public CommonResult<PageResult<OaEntryRespVO>> getOaEntryPage(@Valid OaEntryPageReqVO pageReqVO) {
-        PageResult<OaEntryDO> pageResult = oaEntryService.getOaEntryPage(pageReqVO);
-        return success(BeanUtils.toBean(pageResult, OaEntryRespVO.class));
+        return success(oaEntryService.getOaEntryPage(pageReqVO), "查询列表成功");
     }
 
     @GetMapping("/export-excel")
-    @Operation(summary = "导出入职流程信息 Excel")
-    @PreAuthorize("@ss.hasPermission('bpm:oa-entry:export')")
+    @Operation(summary = "导出入职审批流程信息 Excel")
+    @ApiOperationSupport(order = 12)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:export')")
     @ApiAccessLog(operateType = EXPORT)
     public void exportOaEntryExcel(@Valid OaEntryPageReqVO pageReqVO,
-              HttpServletResponse response) throws IOException {
-        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
-        List<OaEntryDO> list = oaEntryService.getOaEntryPage(pageReqVO).getList();
+                                       HttpServletResponse response) throws IOException {
+        PageResult<OaEntryRespVO> pageResult = oaEntryService.exportOaEntryExcel(pageReqVO);
+        List<OaEntryRespVO> list = pageResult.getList();
         // 导出 Excel
-        ExcelUtils.write(response, "入职流程信息.xls", "数据", OaEntryRespVO.class,
-                        BeanUtils.toBean(list, OaEntryRespVO.class));
+        ExcelUtils.write(response, "入职审批流程信息.xls", "数据", OaEntryRespVO.class,
+                BeanUtils.toBean(list, OaEntryRespVO.class));
     }
-
 }

+ 8 - 7
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/entry/vo/OaEntryPageReqVO.java

@@ -17,6 +17,9 @@ public class OaEntryPageReqVO extends PageParam {
     @Schema(description = "uuid", example = "13471")
     private String entryId;
 
+    @Schema(description = "入职人", example = "李四")
+    private String entryName;
+
     @Schema(description = "部门", example = "2937")
     private String deptId;
 
@@ -29,7 +32,7 @@ public class OaEntryPageReqVO extends PageParam {
     @Schema(description = "性别")
     private String gender;
 
-    @Schema(description = "出日期")
+    @Schema(description = "出日期")
     private String birthday;
 
     @Schema(description = "联系电话")
@@ -44,6 +47,10 @@ public class OaEntryPageReqVO extends PageParam {
     @Schema(description = "工作经验")
     private String workExperience;
 
+    @Schema(description = "入职日期")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private String[] entryDate;
+
     @Schema(description = "备注")
     private String remarks;
 
@@ -55,12 +62,6 @@ public class OaEntryPageReqVO extends PageParam {
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;
 
-    @Schema(description = "入职人", example = "李四")
-    private String entryName;
-
-    @Schema(description = "入职日期")
-    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
-    private String[] entryDate;
 
     @Schema(description = "流程实例id", example = "9407")
     private String procInstId;

+ 62 - 18
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/entry/vo/OaEntryRespVO.java

@@ -1,23 +1,42 @@
 package cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo;
 
+import cn.iocoder.yudao.framework.common.util.date.DateUtils;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
+import cn.iocoder.yudao.module.infra.api.file.dto.FileDTO;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
 
 import java.time.LocalDateTime;
+import java.util.List;
+
 import com.alibaba.excel.annotation.*;
+import org.springframework.format.annotation.DateTimeFormat;
 
 @Schema(description = "管理后台 - 入职流程信息 Response VO")
 @Data
 @ExcelIgnoreUnannotated
 public class OaEntryRespVO {
 
+    @Schema(description = "入职表单主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "27428")
+    @ExcelProperty("入职表单主键")
+    private Integer id;
+
     @Schema(description = "uuid", example = "13471")
     @ExcelProperty("uuid")
     private String entryId;
 
+    @Schema(description = "入职人", example = "李四")
+    @ExcelProperty("入职人")
+    private String entryName;
+
     @Schema(description = "部门", example = "2937")
     @ExcelProperty("部门")
-    private String deptId;
+    private Long deptId;
+
+    @Schema(description = "部门名称")
+    @ExcelProperty("部门名称")
+    private String deptName;
 
     @Schema(description = "职位")
     @ExcelProperty("职位")
@@ -31,8 +50,8 @@ public class OaEntryRespVO {
     @ExcelProperty("性别")
     private String gender;
 
-    @Schema(description = "出日期")
-    @ExcelProperty("出日期")
+    @Schema(description = "出日期")
+    @ExcelProperty("出日期")
     private String birthday;
 
     @Schema(description = "联系电话")
@@ -59,18 +78,6 @@ public class OaEntryRespVO {
     @ExcelProperty("最后审核时间")
     private String finalAuditDate;
 
-    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("创建时间")
-    private LocalDateTime createTime;
-
-    @Schema(description = "入职表单主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "27428")
-    @ExcelProperty("入职表单主键")
-    private Integer id;
-
-    @Schema(description = "入职人", example = "李四")
-    @ExcelProperty("入职人")
-    private String entryName;
-
     @Schema(description = "入职日期")
     @ExcelProperty("入职日期")
     private String entryDate;
@@ -83,12 +90,49 @@ public class OaEntryRespVO {
     @ExcelProperty("审核状态(0暂存、1已提交、2审核中、3已审核、4已关闭、5驳回)")
     private String auditStatus;
 
-    @Schema(description = "当前审核人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29870")
-    @ExcelProperty("当前审核人编号")
-    private String currentAuditEmployeeId;
+    @Schema(description = "当前审核人用户id")
+    @ExcelProperty("当前审核人用户id")
+    private Long currentAuditUserId;
+
+    @Schema(description = "当前审核人用户uuid")
+    @ExcelProperty("当前审核人用户uuid")
+    private String currentAuditUserUuid;
+
+    @Schema(description = "当前审核人员工id")
+    @ExcelProperty("当前审核人员工id")
+    private Long currentAuditEmployeeId;
+
+    @Schema(description = "当前审核人员工uuid")
+    @ExcelProperty("当前审核人员工uuid")
+    private String currentAuditEmployeeUuid;
+
+    @Schema(description = "当前审核人员工uuid")
+    @ExcelProperty("当前审核人员工uuid")
+    private String currentAuditEmployeeName;
 
     @Schema(description = "数据来源,0流程添加、1手动添加", requiredMode = Schema.RequiredMode.REQUIRED)
     @ExcelProperty("数据来源,0流程添加、1手动添加")
     private String infoSource;
 
+    @Schema(description = "创建者")
+    @ExcelProperty("创建者")
+    private String creator;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "附件列表")
+    private List<FileDTO> fileList;
+
+    @Schema(description = "审批记录列表")
+    private List<BpmTaskRespVO> auditRecordList;
+
+    @Schema(description = "审批人员列表")
+    private List<AdminUserRespDTO> auditUserList;
+
+    @Schema(description = "当前用户待处理的任务id")
+    private String taskId;
+
 }

+ 15 - 32
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/entry/vo/OaEntrySaveReqVO.java

@@ -4,37 +4,46 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveR
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import javax.validation.constraints.NotBlank;
 import java.util.List;
 
 @Schema(description = "管理后台 - 入职流程信息新增/修改 Request VO")
 @Data
 public class OaEntrySaveReqVO {
 
+    @Schema(description = "入职表单主键", example = "1")
+    private Long id;
+
     @Schema(description = "入职人", example = "李四")
+    @NotBlank(message = "入职人不能为空")
     private String entryName;
 
-    @Schema(description = "uuid", example = "13471")
-    private String entryId;
-
     @Schema(description = "部门", example = "2937")
+    @NotBlank(message = "部门不能为空")
     private String deptId;
 
     @Schema(description = "职位")
+    @NotBlank(message = "职位不能为空")
     private String position;
 
     @Schema(description = "员工类型", example = "1")
+    @NotBlank(message = "员工类型不能为空")
     private String employeeType;
 
     @Schema(description = "性别")
+    @NotBlank(message = "性别不能为空")
     private String gender;
 
-    @Schema(description = "出身日期")
+    @Schema(description = "出生日期")
+    @NotBlank(message = "出生日期不能为空")
     private String birthday;
 
     @Schema(description = "联系电话")
+    @NotBlank(message = "联系电话不能为空")
     private String contactNumber;
 
     @Schema(description = "电子邮箱")
+    @NotBlank(message = "电子邮箱不能为空")
     private String email;
 
     @Schema(description = "教育背景", example = "本科")
@@ -46,40 +55,14 @@ public class OaEntrySaveReqVO {
     @Schema(description = "备注")
     private String remarks;
 
-    @Schema(description = "最后审核时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    // @NotEmpty(message = "最后审核时间不能为空")
-    private String finalAuditDate;
-
-    @Schema(description = "入职表单主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
-    private Integer id;
-
     @Schema(description = "入职日期")
+    @NotBlank(message = "入职日期不能为空")
     private String entryDate;
 
-    @Schema(description = "流程实例id", example = "9407")
-    private String procInstId;
-
-    @Schema(description = "审核状态(0暂存、1已提交、2审核中、3已审核、4已关闭、5驳回)", example = "2")
-    private String auditStatus;
-
-    @Schema(description = "当前审核人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29870")
-    // @NotEmpty(message = "当前审核人编号不能为空")
-    private String currentAuditEmployeeId;
-
-    @Schema(description = "数据来源,0流程添加、1手动添加", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
-    // @NotEmpty(message = "数据来源,0流程添加、1手动添加不能为空")
-    private String infoSource;
-
-    @Schema(description = "审批,true 通过,false 驳回", example = "true")
-    private Boolean auditPass;
-
-    @Schema(description = "发起人自选审批人 Map", example = " [1, 1]")
+    @Schema(description = "发起人自选审批人 Map", example = " [100, 1]")
     private List<Long> startUserSelectAssignees;
 
     @Schema(description = "附件主键id", example = "[1, 2]")
     private List<Long> fileIdList;
 
-    @Schema(description = "审批信息")
-    private BpmTaskApproveReqVO bpmTaskApproveReqVO;
-
 }

+ 27 - 10
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/entry/OaEntryDO.java

@@ -1,11 +1,12 @@
 package cn.iocoder.yudao.module.bpm.dal.dataobject.oa.entry;
 
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
-import java.util.*;
-import java.time.LocalDateTime;
+
 import java.time.LocalDateTime;
-import com.baomidou.mybatisplus.annotation.*;
-import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
 
 /**
  * 入职流程信息 DO
@@ -25,7 +26,7 @@ public class OaEntryDO extends BaseDO {
      * 入职表单主键
      */
     @TableId
-    private Integer id;
+    private Long id;
 
     /**
      * uuid
@@ -38,7 +39,7 @@ public class OaEntryDO extends BaseDO {
     /**
      * 部门
      */
-    private String deptId;
+    private Long deptId;
     /**
      * 职位
      */
@@ -52,7 +53,7 @@ public class OaEntryDO extends BaseDO {
      */
     private String gender;
     /**
-     * 出日期
+     * 出日期
      */
     private String birthday;
     /**
@@ -92,11 +93,27 @@ public class OaEntryDO extends BaseDO {
     /**
      * 最后审核时间
      */
-    private Date finalAuditDate;
+    private LocalDateTime finalAuditDate;
+    /**
+     * 当前审核人用户id
+     */
+    private Long currentAuditUserId;
+    /**
+     * 当前审核人用户uuid
+     */
+    private String currentAuditUserUuid;
+    /**
+     * 当前审核人员工id
+     */
+    private Long currentAuditEmployeeId;
+    /**
+     * 当前审核人员工uuid
+     */
+    private String currentAuditEmployeeUuid;
     /**
-     * 当前审核人编号
+     * 申请人选择的审批人
      */
-    private String currentAuditEmployeeId;
+    private String startUserSelectAssignees;
     /**
      * 数据来源,0流程添加、1手动添加
      */

+ 1 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java

@@ -68,7 +68,7 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener {
             if (StrUtil.isEmpty(activity.getTaskId())) {
                 return;
             }
-            taskService.updateTaskStatusWhenCanceled(activity.getTaskId());
+            // taskService.updateTaskStatusWhenCanceled(activity.getTaskId());
         });
     }
 

+ 18 - 64
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/entry/OaEntryService.java

@@ -2,85 +2,39 @@ package cn.iocoder.yudao.module.bpm.service.oa.entry;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntryPageReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntryRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntrySaveReqVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
-import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.entry.OaEntryDO;
-import com.baomidou.mybatisplus.extension.service.IService;
-
-import javax.validation.Valid;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskReturnReqVO;
 
 /**
  * 入职流程信息 Service 接口
  *
  * @author 芋道源码
  */
-public interface OaEntryService extends IService<OaEntryDO> {
+public interface OaEntryService {
+
+    Long stagingOaEntry(OaEntrySaveReqVO stagingReqVO);
+
+    Long commitOaEntry(OaEntrySaveReqVO commitReqVO);
+
+    Long agreeOaEntry(BpmTaskApproveReqVO agreeReqVO);
 
-    /**
-     * 发起入职流程信息
-     *
-     * @param userId
-     * @param createReqVO 创建信息
-     * @return 编号
-     */
-    Integer startOaEntry(Long userId, @Valid OaEntrySaveReqVO createReqVO);
+    Long disagreeOaEntry(BpmTaskReturnReqVO disagreeReqVO);
 
-    /**
-     * 审批同意入职流程信息
-     *
-     * @param userId
-     * @param reqVO  通过请求
-     * @return 编号
-     */
-    Integer completeTrueOaEntry(Long userId, BpmTaskApproveReqVO reqVO);
+    Long revocationOaEntry(BpmTaskApproveReqVO revocationReqVO);
 
-    /**
-     * 驳回或撤回入职流程信息
-     *
-     * @param userId
-     * @param reqVO  驳回或撤回
-     * @return 编号
-     */
-    Integer completeFalseOaEntry(Long userId, BpmTaskApproveReqVO reqVO);
+    Long reCommitOaEntry(OaEntrySaveReqVO reCommitReqVO);
 
-    /**
-     * 驳回和撤回后再次提交或关闭入职流程信息
-     *
-     * @param userId
-     * @param createReqVO 创建信息
-     * @param reqVO       通过请求
-     * @return 编号
-     */
-    Integer updateCompleteOaEntry(Long userId, @Valid OaEntrySaveReqVO createReqVO, @Valid BpmTaskApproveReqVO reqVO);
+    Long closeOaEntry(OaEntrySaveReqVO closeReqVO);
 
-    /**
-     * 更新入职流程信息
-     *
-     * @param updateReqVO 更新信息
-     */
-    void updateOaEntry(@Valid OaEntrySaveReqVO updateReqVO);
+    void deleteOaEntry(Long id);
 
-    /**
-     * 删除入职流程信息
-     *
-     * @param id 编号
-     */
-    void deleteOaEntry(Integer id);
+    OaEntryRespVO getOaEntry(Long id);
 
-    /**
-     * 获得入职流程信息
-     *
-     * @param id 编号
-     * @return 入职流程信息
-     */
-    OaEntryDO getOaEntry(Integer id);
+    OaEntryRespVO getOaEntryByProcInstId(String procInstId);
 
-    /**
-     * 获得入职流程信息分页
-     *
-     * @param pageReqVO 分页查询
-     * @return 入职流程信息分页
-     */
-    PageResult<OaEntryDO> getOaEntryPage(OaEntryPageReqVO pageReqVO);
+    PageResult<OaEntryRespVO> getOaEntryPage(OaEntryPageReqVO pageReqVO);
 
+    PageResult<OaEntryRespVO> exportOaEntryExcel(OaEntryPageReqVO pageReqVO);
 }

+ 443 - 116
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/entry/OaEntryServiceImpl.java

@@ -2,33 +2,45 @@ package cn.iocoder.yudao.module.bpm.service.oa.entry;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
 import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
 import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntryPageReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntryRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.oa.entry.vo.OaEntrySaveReqVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
 import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskReturnReqVO;
 import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.entry.OaEntryDO;
 import cn.iocoder.yudao.module.bpm.dal.mysql.oa.entry.OaEntryMapper;
+import cn.iocoder.yudao.module.bpm.enums.DictDataConstants;
+import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants;
+import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
 import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
+import cn.iocoder.yudao.module.infra.api.file.FileApi;
+import cn.iocoder.yudao.module.infra.api.file.dto.FileDTO;
+import cn.iocoder.yudao.module.system.api.dept.DeptApi;
+import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
+import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
+import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.apache.commons.lang3.StringUtils;
-import org.flowable.engine.RuntimeService;
 import org.flowable.engine.TaskService;
 import org.flowable.task.api.Task;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_ENTRY_NOT_EXISTS;
@@ -40,12 +52,12 @@ import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_ENTRY_NOT_
  */
 @Service
 @Validated
-public class OaEntryServiceImpl extends ServiceImpl<OaEntryMapper, OaEntryDO> implements OaEntryService {
+public class OaEntryServiceImpl implements OaEntryService {
 
     /**
      * OA 入职对应的流程定义 KEY
      */
-    public static final String PROCESS_KEY = "oa_entry_workflow";
+    public static final String PROCESS_KEY = "oa_entry";
 
     @Resource
     private OaEntryMapper oaEntryMapper;
@@ -59,189 +71,504 @@ public class OaEntryServiceImpl extends ServiceImpl<OaEntryMapper, OaEntryDO> im
     @Resource
     private TaskService taskService;
 
-    @Autowired
-    private RuntimeService runtimeService;
+    @Resource
+    private FileApi fileApi;
+
+    @Resource
+    private AdminUserApi adminUserApi;
+
+    @Resource
+    private DeptApi deptApi;
 
     @Override
     @Transactional
-    public Integer startOaEntry(Long userId, OaEntrySaveReqVO createReqVO) {
-        //判断是否已经发起流程
-        Boolean auditPass = createReqVO.getAuditPass();
-        // 创建单据uuid
-        String uuid = IdUtil.fastSimpleUUID();
-        OaEntryDO oaEntry = BeanUtils.toBean(createReqVO, OaEntryDO.class);
+    public Long stagingOaEntry(OaEntrySaveReqVO stagingReqVO) {
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
+        Objects.requireNonNull(loginUser, "登录用户不能为空");
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        OaEntryDO oaEntry = BeanUtils.toBean(stagingReqVO, OaEntryDO.class);
         if (StringUtils.isBlank(oaEntry.getEntryId())) {
+            // 创建单据uuid
+            String uuid = IdUtil.fastSimpleUUID();
             oaEntry.setEntryId(uuid);
         }
+        oaEntry.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_STAGING);
+        oaEntry.setInfoSource("0");
+        // 暂存不保存审批人信息
+        oaEntry.setStartUserSelectAssignees(null);
         // 保存或更新表单信息
-        this.saveOrUpdate(oaEntry);
-
-        // 提交
-        if (auditPass) {
-            // 发起 BPM 流程
-            Map<String, Object> processInstanceVariables = new HashMap<>();
-            processInstanceVariables.put("auditPass", auditPass);
-            //添加审批人信息
-            Map<String, List<Long>> startUserSelectAssignees = new HashMap<>();
-            startUserSelectAssignees.put("approver", createReqVO.getStartUserSelectAssignees());
-            String processInstanceId = processInstanceApi
-                    .createProcessInstance(userId,
-                            new BpmProcessInstanceCreateReqDTO()
-                                    .setProcessDefinitionKey(PROCESS_KEY)
-                                    .setVariables(processInstanceVariables)
-                                    .setBusinessKey(String.valueOf(oaEntry.getId()))
-                                    .setStartUserSelectAssignees(startUserSelectAssignees));
-
-            //获取下一个审批人
-            Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
+        if (oaEntry.getId() == null) {
+            oaEntryMapper.insert(oaEntry);
+        } else {
+            oaEntryMapper.updateById(oaEntry);
+        }
+        // 保存业务uuid到附件中
+        saveFileList(stagingReqVO.getFileIdList(), oaEntry.getEntryId());
 
-            // 将工作流的编号,单据状态 最后一次审批时间 当前审批人  更新到 OA 入职中
-            oaEntryMapper.updateById(new OaEntryDO()
-                    .setId(oaEntry.getId())
-                    .setProcInstId(processInstanceId)
-                    .setAuditStatus("1")
-                    .setEntryId(uuid)
-                    .setFinalAuditDate(new Date())
-                    .setCurrentAuditEmployeeId(task.getAssignee()));
+        return oaEntry.getId();
+    }
 
-            // TODO 发送通知
+    @Override
+    @Transactional
+    public Long commitOaEntry(OaEntrySaveReqVO commitReqVO) {
+        if (CollectionUtil.isEmpty(commitReqVO.getStartUserSelectAssignees())) {
+            throw exception(ErrorCodeConstants.TASK_CREATE_FAIL_NO_START_SELECT_ASSIGNEE);
+        }
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
+        Objects.requireNonNull(loginUser, "登录用户不能为空");
+        // TODO DP 根据登录人查询出对应的员工信息
 
-        }else {
-            // 暂存,不发起流程
-            // 将单据状态 更新到 OA入职中
-            oaEntryMapper.updateById(new OaEntryDO()
-                    .setId(oaEntry.getId())
-                    .setAuditStatus("0"));
+        OaEntryDO oaEntry = BeanUtils.toBean(commitReqVO, OaEntryDO.class);
+        if (StringUtils.isBlank(oaEntry.getEntryId())) {
+            // 创建单据uuid
+            String uuid = IdUtil.fastSimpleUUID();
+            oaEntry.setEntryId(uuid);
         }
+        oaEntry.setInfoSource("0");
+        // 保存或更新表单信息
+        if (oaEntry.getId() == null) {
+            oaEntryMapper.insert(oaEntry);
+        } else {
+            OaEntryDO oaEntryDO = oaEntryMapper.selectById(oaEntry.getId());
+            if (StrUtil.isNotBlank(oaEntryDO.getProcInstId())) {
+                throw exception(ErrorCodeConstants.PROCESS_INSTANCE_CREATE_FAIL_HAS_PROCESS);
+            }
+            oaEntryMapper.updateById(oaEntry);
+        }
+        // 发起流程
+        Map<String, Object> processInstanceVariables = new HashMap<>();
+        processInstanceVariables.put("auditPass", "true");
+        // 添加审批人信息
+        Map<String, List<Long>> startUserSelectAssignees = new HashMap<>();
+        List<Long> selectAssignees = commitReqVO.getStartUserSelectAssignees();
+        startUserSelectAssignees.put("approver", selectAssignees);
+        String processInstanceId = processInstanceApi
+                .createProcessInstance(loginUser.getId(),
+                        new BpmProcessInstanceCreateReqDTO()
+                                .setProcessDefinitionKey(PROCESS_KEY)
+                                .setVariables(processInstanceVariables)
+                                .setBusinessKey(String.valueOf(oaEntry.getId()))
+                                .setStartUserSelectAssignees(startUserSelectAssignees));
+
+        //获取下一个审批人
+        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
 
-        // TODO 保存或更新附件uuid
-        if (CollectionUtil.isNotEmpty(createReqVO.getFileIdList())) {
+        // 审批同意
+        BpmTaskApproveReqVO agreeReqVO = new BpmTaskApproveReqVO();
+        agreeReqVO.setId(task.getId());
+        agreeReqVO.setReason("[首次提交]");
+        agreeReqVO.setTaskStatus(Integer.valueOf(DictDataConstants.OA_AUDIT_STATUS_COMMITTED));
+        taskService.setVariable(task.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_COMMITTED);
+        taskService.setVariable(task.getId(), "auditPass", "true");
+        bpmTaskService.approveTask(loginUserId, agreeReqVO);
+
+        Task nextTask = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
+        if (nextTask == null) {
+            throw exception(ErrorCodeConstants.TASK_CREATE_FAIL_NO_START_SELECT_ASSIGNEE);
         }
 
-        // 返回
+        // 将工作流的流程实例ID、单据状态、最后一次审批时间、当前审批人更新到单据信息中
+        oaEntryMapper.updateById(new OaEntryDO()
+                .setId(oaEntry.getId())
+                .setProcInstId(processInstanceId)
+                .setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_COMMITTED)
+                .setFinalAuditDate(LocalDateTime.now())
+                .setCurrentAuditEmployeeId(Long.valueOf(nextTask.getAssignee()))
+                .setStartUserSelectAssignees(selectAssignees.stream().map(String::valueOf).collect(Collectors.joining(","))));
+        // 保存业务uuid到附件中
+        saveFileList(commitReqVO.getFileIdList(), oaEntry.getEntryId());
+        // TODO DP 发送提交成功站内信
         return oaEntry.getId();
     }
 
     @Override
-    public Integer completeTrueOaEntry(Long userId, BpmTaskApproveReqVO reqVO) {
-        Task currentTask = bpmTaskService.getTask(reqVO.getId());
+    @Transactional
+    public Long agreeOaEntry(BpmTaskApproveReqVO agreeReqVO) {
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        Task currentTask = bpmTaskService.getTask(agreeReqVO.getId());
+        if (currentTask == null) {
+            throw exception(ErrorCodeConstants.TASK_NOT_EXISTS);
+        }
+        // 先更新为审批中
+        taskService.setVariable(currentTask.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_AUDITING);
+        LambdaQueryWrapper<OaEntryDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lambdaQueryWrapper.eq(OaEntryDO::getProcInstId, currentTask.getProcessInstanceId());
+        OaEntryDO oaEntry = oaEntryMapper.selectOne(lambdaQueryWrapper);
+        // 如果是最后一个人审批同意,设置流程审批状态为已审核
+        String[] auditPersons = oaEntry.getStartUserSelectAssignees().split(",");
+        String lastAuditPerson = Arrays.stream(auditPersons)
+                .reduce((first, second) -> second)
+                .orElse(null);
+        if (currentTask.getAssignee().equals(lastAuditPerson)) {
+            // 更新为已审核(暂时未生效,未找到原因,先不处理)
+            taskService.setVariable(agreeReqVO.getId(),BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_AUDITED);
+        }
         // 审批同意
-        bpmTaskService.approveTask(userId, reqVO);
+        String reason = "[同意]";
+        if (StrUtil.isNotBlank(agreeReqVO.getReason())) {
+            reason = reason + agreeReqVO.getReason();
+        }
+        agreeReqVO.setReason(reason);
+        agreeReqVO.setTaskStatus(Integer.valueOf(DictDataConstants.OA_AUDIT_STATUS_AUDITING));
+        taskService.setVariable(agreeReqVO.getId(), "auditPass", "true");
+        bpmTaskService.approveTask(loginUserId, agreeReqVO);
 
         Task nextTask = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
+        OaEntryDO oaEntryDO = new OaEntryDO();
         if (nextTask != null) {
-            LambdaUpdateWrapper<OaEntryDO> updateWrapper = new LambdaUpdateWrapper<>();
-            updateWrapper.set(OaEntryDO::getAuditStatus, "2")
-                    .set(OaEntryDO::getCurrentAuditEmployeeId, nextTask.getAssignee())
-                    .set(OaEntryDO::getFinalAuditDate, new Date())
-                    .eq(OaEntryDO::getProcInstId, currentTask.getProcessInstanceId());
-            oaEntryMapper.update(updateWrapper);
+            // 如果审批人重复,实际未结束,再次更新为审核中
+            taskService.setVariable(nextTask.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_AUDITING);
+            oaEntryDO.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_AUDITING)
+                    .setCurrentAuditEmployeeId(Long.valueOf(nextTask.getAssignee()))
+                    .setFinalAuditDate(LocalDateTime.now())
+                    .setId(oaEntry.getId());
+
         } else {
-            LambdaUpdateWrapper<OaEntryDO> updateWrapper = new LambdaUpdateWrapper<>();
-            updateWrapper.set(OaEntryDO::getAuditStatus, "3")
-                    .set(OaEntryDO::getCurrentAuditEmployeeId, null)
-                    .set(OaEntryDO::getFinalAuditDate, new Date())
-                    .eq(OaEntryDO::getProcInstId, currentTask.getProcessInstanceId());
-            oaEntryMapper.update(updateWrapper);
+            oaEntryDO.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_AUDITED)
+                    .setCurrentAuditEmployeeId(null)
+                    .setFinalAuditDate(LocalDateTime.now())
+                    .setId(oaEntry.getId());
 
             // TODO 复制业务单据信息到业务模块单据表
 
         }
+        oaEntryMapper.updateById(oaEntryDO);
         // 发送通知
 
         // 返回
-        return 1;
+        return 1L;
     }
 
     @Override
-    public Integer completeFalseOaEntry(Long userId, BpmTaskApproveReqVO reqVO) {
+    @Transactional
+    public Long disagreeOaEntry(BpmTaskReturnReqVO disagreeReqVO) {
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
 
-        Task currentTask = bpmTaskService.getTask(reqVO.getId());
+        Task currentTask = bpmTaskService.getTask(disagreeReqVO.getId());
 
-        BpmTaskReturnReqVO reqVO2 = BeanUtils.toBean(reqVO, BpmTaskReturnReqVO.class);
-        reqVO2.setTargetTaskDefinitionKey("modifyApply");
-        bpmTaskService.returnTask(userId, reqVO2);
+        disagreeReqVO.setTargetTaskDefinitionKey("modifyApply");
+        disagreeReqVO.setReason("[驳回]" + disagreeReqVO.getReason());
+        disagreeReqVO.setTaskStatus(Integer.valueOf(DictDataConstants.OA_AUDIT_STATUS_RETURNED));
+        taskService.setVariable(disagreeReqVO.getId(), "auditPass", "false");
+        taskService.setVariable(disagreeReqVO.getId(),BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_RETURNED);
+        bpmTaskService.returnTask(loginUserId, disagreeReqVO);
 
         Task nextTask = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
 
         // 更新单据状态,当前处理人,最后处理时间
         LambdaUpdateWrapper<OaEntryDO> updateWrapper = new LambdaUpdateWrapper<>();
         updateWrapper.set(OaEntryDO::getCurrentAuditEmployeeId, nextTask.getAssignee())
-                .set(OaEntryDO::getFinalAuditDate, new Date())
-                .set(OaEntryDO::getAuditStatus, "0")
+                .set(OaEntryDO::getFinalAuditDate, LocalDateTime.now())
+                .set(OaEntryDO::getAuditStatus, DictDataConstants.OA_AUDIT_STATUS_RETURNED)
                 .eq(OaEntryDO::getProcInstId, currentTask.getProcessInstanceId());
         oaEntryMapper.update(updateWrapper);
 
         // 发送通知
 
-        // 返回
-        return 1;
+        return 1L;
     }
 
     @Override
-    public Integer updateCompleteOaEntry(Long userId, OaEntrySaveReqVO createReqVO, BpmTaskApproveReqVO reqVO) {
-        // 判断是否已经发起流程
-        Boolean auditPass = createReqVO.getAuditPass();
+    @Transactional
+    public Long revocationOaEntry(BpmTaskApproveReqVO revocationReqVO) {
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        Task currentTask = bpmTaskService.getTask(revocationReqVO.getId());
+        if (currentTask == null) {
+            throw ServiceExceptionUtil.exception(ErrorCodeConstants.TASK_NOT_EXISTS);
+        }
+        LambdaQueryWrapper<OaEntryDO> lambdaQueryWrapper = new LambdaQueryWrapper<OaEntryDO>()
+                .eq(OaEntryDO::getProcInstId, currentTask.getProcessInstanceId());
+        OaEntryDO oaEntryDO = oaEntryMapper.selectOne(lambdaQueryWrapper);
+        if (!DictDataConstants.OA_AUDIT_STATUS_COMMITTED.equals(oaEntryDO.getAuditStatus())
+                || !Objects.equals(String.valueOf(loginUserId), oaEntryDO.getCreator())) {
+            throw ServiceExceptionUtil.exception(ErrorCodeConstants.TASK_REVOCATION_NO_ALLOWED);
+        }
 
-        OaEntryDO oaEntry = BeanUtils.toBean(createReqVO, OaEntryDO.class);
+        BpmTaskReturnReqVO returnReqVO = BeanUtils.toBean(revocationReqVO, BpmTaskReturnReqVO.class);
+        returnReqVO.setTargetTaskDefinitionKey("modifyApply");
+        String reason = "[撤回]";
+        if (StrUtil.isNotBlank(returnReqVO.getReason())) {
+            reason = reason + returnReqVO.getReason();
+        }
+        returnReqVO.setReason(reason);
+        returnReqVO.setTaskStatus(Integer.valueOf(DictDataConstants.OA_AUDIT_STATUS_RECALLED));
+        taskService.setVariable(currentTask.getId(),BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_RECALLED);
+        bpmTaskService.revocationTask(loginUserId, returnReqVO);
 
-        Task currentTask = taskService.createTaskQuery().processInstanceId(oaEntry.getProcInstId()).singleResult();
+        Task nextTask = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
 
-        //审批通过
-        bpmTaskService.approveTask(userId, reqVO);
+        // 更新单据状态,当前处理人,最后处理时间
+        LambdaUpdateWrapper<OaEntryDO> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.set(OaEntryDO::getCurrentAuditEmployeeId, nextTask.getAssignee())
+                .set(OaEntryDO::getFinalAuditDate, LocalDateTime.now())
+                .set(OaEntryDO::getAuditStatus, DictDataConstants.OA_AUDIT_STATUS_RECALLED)
+                .eq(OaEntryDO::getProcInstId, currentTask.getProcessInstanceId());
+        oaEntryMapper.update(updateWrapper);
 
-        // 提交
-        if (auditPass) {
-            Task nextTask = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
+        // 发送通知
 
-            oaEntry.setAuditStatus("1");
-            oaEntry.setCurrentAuditEmployeeId(nextTask.getAssignee());
-            oaEntry.setFinalAuditDate(new Date());
-            oaEntryMapper.updateById(oaEntry);
+        return 1L;
+    }
 
-        } else {
-            OaEntryDO oaEntryClose = new OaEntryDO();
-            oaEntryClose.setId(oaEntry.getId());
-            oaEntryClose.setAuditStatus("4");
-            oaEntryClose.setCurrentAuditEmployeeId(null);
-            oaEntryClose.setFinalAuditDate(new Date());
-            oaEntryMapper.updateById(oaEntryClose);
+    @Override
+    @Transactional
+    public Long reCommitOaEntry(OaEntrySaveReqVO reCommitReqVO) {
+        if (reCommitReqVO.getId() == null) {
+            throw exception(ErrorCodeConstants.SERVICE_ID_NOT_EXISTS);
         }
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        OaEntryDO oaEntryNew = BeanUtils.toBean(reCommitReqVO, OaEntryDO.class);
+        OaEntryDO oaEntryOld = oaEntryMapper.selectById(oaEntryNew.getId());
+        oaEntryNew.setEntryId(oaEntryOld.getEntryId())
+                .setProcInstId(oaEntryOld.getProcInstId());
+
+        Task currentTask = taskService.createTaskQuery().processInstanceId(oaEntryNew.getProcInstId()).singleResult();
+        BpmTaskApproveReqVO approveReqVO = new BpmTaskApproveReqVO();
+        approveReqVO.setId(currentTask.getId())
+                .setReason("[再次提交]");
+        approveReqVO.setTaskStatus(Integer.valueOf(DictDataConstants.OA_AUDIT_STATUS_COMMITTED));
+        if (CollectionUtil.isNotEmpty(reCommitReqVO.getStartUserSelectAssignees())) {
+            // 添加审批人信息到流程参数中
+            Map<String, List<Long>> startUserSelectAssignees = new HashMap<>();
+            List<Long> selectAssignees = reCommitReqVO.getStartUserSelectAssignees();
+            startUserSelectAssignees.put("approver", selectAssignees);
+            taskService.setVariable(currentTask.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_START_USER_SELECT_ASSIGNEES, startUserSelectAssignees);
+            // 保存审批人信息
+            oaEntryNew.setStartUserSelectAssignees(selectAssignees.stream().map(String::valueOf).collect(Collectors.joining(",")));
+        }
+        taskService.setVariable(currentTask.getId(), "auditPass", "true");
+        taskService.setVariable(currentTask.getId(),BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_COMMITTED);
+        // 再次提交,和审批通过逻辑相同
+        bpmTaskService.approveTask(loginUserId, approveReqVO);
 
-        return oaEntry.getId();
+        Task nextTask = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
+        oaEntryNew.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_COMMITTED)
+                .setCurrentAuditEmployeeId(Long.valueOf(nextTask.getAssignee()))
+                .setFinalAuditDate(LocalDateTime.now());
+        oaEntryMapper.updateById(oaEntryNew);
+
+        // 保存业务uuid到附件中
+        saveFileList(reCommitReqVO.getFileIdList(), oaEntryNew.getEntryId());
+
+        return 1L;
     }
 
     @Override
-    public void updateOaEntry(OaEntrySaveReqVO updateReqVO) {
-        // 校验存在
-        validateOaEntryExists(updateReqVO.getId());
-        // 更新
-        OaEntryDO updateObj = BeanUtils.toBean(updateReqVO, OaEntryDO.class);
-        oaEntryMapper.updateById(updateObj);
+    @Transactional
+    public Long closeOaEntry(OaEntrySaveReqVO closeReqVO) {
+        if (closeReqVO.getId() == null) {
+            throw exception(ErrorCodeConstants.SERVICE_ID_NOT_EXISTS);
+        }
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        OaEntryDO oaEntryNew = BeanUtils.toBean(closeReqVO, OaEntryDO.class);
+        OaEntryDO oaEntryOld = oaEntryMapper.selectById(oaEntryNew.getId());
+
+        Task currentTask = taskService.createTaskQuery().processInstanceId(oaEntryOld.getProcInstId()).singleResult();
+        BpmTaskApproveReqVO approveReqVO = new BpmTaskApproveReqVO();
+        approveReqVO.setId(currentTask.getId())
+                .setReason("[关闭]");
+        approveReqVO.setTaskStatus(Integer.valueOf(DictDataConstants.OA_AUDIT_STATUS_CLOSED));
+        taskService.setVariable(currentTask.getId(), "auditPass", "false");
+        taskService.setVariable(currentTask.getId(),BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_CLOSED);
+        // 关闭,使用审批通过的方法实现
+        bpmTaskService.approveTask(loginUserId, approveReqVO);
+
+        oaEntryOld.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_CLOSED)
+                .setCurrentAuditEmployeeId(-1L)
+                .setFinalAuditDate(LocalDateTime.now());
+        oaEntryMapper.updateById(oaEntryOld);
+
+        return 1L;
     }
 
     @Override
-    public void deleteOaEntry(Integer id) {
+    public void deleteOaEntry(Long id) {
         // 校验存在
         validateOaEntryExists(id);
         // 删除
         oaEntryMapper.deleteById(id);
     }
 
-    private void validateOaEntryExists(Integer id) {
-        if (oaEntryMapper.selectById(id) == null) {
-            throw exception(OA_ENTRY_NOT_EXISTS);
+    @Override
+    public OaEntryRespVO getOaEntry(Long id) {
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        OaEntryDO oaEntryDO = oaEntryMapper.selectById(id);
+        OaEntryRespVO oaEntryRespVO = BeanUtils.toBean(oaEntryDO, OaEntryRespVO.class);
+        if (oaEntryDO.getDeptId() != null) {
+            DeptRespDTO dept = deptApi.getDept(oaEntryDO.getDeptId());
+            if (dept != null) {
+                oaEntryRespVO.setDeptName(dept.getName());
+            }
+        }
+
+        String procInstId = oaEntryDO.getProcInstId();
+        if (StrUtil.isNotBlank(procInstId)) {
+            Task task = taskService.createTaskQuery()
+                    .processInstanceId(procInstId)
+                    .taskAssignee(String.valueOf(loginUserId))
+                    .singleResult();
+            if (DictDataConstants.OA_AUDIT_STATUS_COMMITTED.equals(oaEntryDO.getAuditStatus())) {
+                // 如果是已提交,不限制任务处理人是当前登录人,用于直接撤回
+                task = taskService.createTaskQuery()
+                        .processInstanceId(procInstId)
+                        .singleResult();
+            }
+            if (task != null) {
+                oaEntryRespVO.setTaskId(task.getId());
+            }
+        }
+
+        // 附件列表
+        List<FileDTO> fileList = fileApi.getFileDTOListByBiz(oaEntryDO.getEntryId());
+        oaEntryRespVO.setFileList(fileList);
+
+        // 审批记录
+        if (StrUtil.isNotBlank(oaEntryDO.getProcInstId())) {
+            List<BpmTaskRespVO> auditRecordList = bpmTaskService.getAuditRecordListByProcessInstanceId(oaEntryDO.getProcInstId());
+            oaEntryRespVO.setAuditRecordList(auditRecordList);
+        }
+
+        // 审批人
+        String startUserSelectAssignees = oaEntryDO.getStartUserSelectAssignees();
+        if (StrUtil.isNotEmpty(startUserSelectAssignees)) {
+            List<Long> userIdList = Arrays.stream(startUserSelectAssignees.split(","))
+                    .map(Long::valueOf).collect(Collectors.toList());
+            List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIdList);
+            List<AdminUserRespDTO> auditUserList = new ArrayList<>();
+            for (Long userId : userIdList) {
+                for (AdminUserRespDTO adminUserRespDTO : userList) {
+                    if (Objects.equals(userId, adminUserRespDTO.getId())) {
+                        auditUserList.add(adminUserRespDTO);
+                        break;
+                    }
+                }
+            }
+            oaEntryRespVO.setAuditUserList(auditUserList);
+        }
+
+        return oaEntryRespVO;
+    }
+
+    @Override
+    public OaEntryRespVO getOaEntryByProcInstId(String procInstId) {
+        OaEntryDO oaEntryDO = oaEntryMapper.selectOne(OaEntryDO::getProcInstId, procInstId);
+        OaEntryRespVO oaEntryRespVO = BeanUtils.toBean(oaEntryDO, OaEntryRespVO.class);
+        if (oaEntryDO.getDeptId() != null) {
+            DeptRespDTO dept = deptApi.getDept(oaEntryDO.getDeptId());
+            if (dept != null) {
+                oaEntryRespVO.setDeptName(dept.getName());
+            }
         }
+
+        // 附件列表
+        List<FileDTO> fileList = fileApi.getFileDTOListByBiz(oaEntryDO.getEntryId());
+        oaEntryRespVO.setFileList(fileList);
+
+        // 审批记录
+        if (StrUtil.isNotBlank(oaEntryDO.getProcInstId())) {
+            List<BpmTaskRespVO> auditRecordList = bpmTaskService.getAuditRecordListByProcessInstanceId(oaEntryDO.getProcInstId());
+            oaEntryRespVO.setAuditRecordList(auditRecordList);
+        }
+
+        // 审批人
+        String startUserSelectAssignees = oaEntryDO.getStartUserSelectAssignees();
+        if (StrUtil.isNotEmpty(startUserSelectAssignees)) {
+            List<Long> userIdList = Arrays.stream(startUserSelectAssignees.split(","))
+                    .map(Long::valueOf).collect(Collectors.toList());
+            List<AdminUserRespDTO> userList = adminUserApi.getUserList(userIdList);
+            List<AdminUserRespDTO> auditUserList = new ArrayList<>();
+            for (Long userId : userIdList) {
+                for (AdminUserRespDTO adminUserRespDTO : userList) {
+                    if (Objects.equals(userId, adminUserRespDTO.getId())) {
+                        auditUserList.add(adminUserRespDTO);
+                        break;
+                    }
+                }
+            }
+            oaEntryRespVO.setAuditUserList(auditUserList);
+        }
+
+        return oaEntryRespVO;
     }
 
     @Override
-    public OaEntryDO getOaEntry(Integer id) {
-        return oaEntryMapper.selectById(id);
+    public PageResult<OaEntryRespVO> getOaEntryPage(OaEntryPageReqVO pageReqVO) {
+        PageResult<OaEntryDO> oaEntryDOPageResult = oaEntryMapper.selectPage(pageReqVO);
+        PageResult<OaEntryRespVO> oaEntryRespVOPageResult = BeanUtils.toBean(oaEntryDOPageResult, OaEntryRespVO.class);
+
+        List<OaEntryRespVO> oaEntryRespVOList = oaEntryRespVOPageResult.getList();
+        if (CollectionUtil.isNotEmpty(oaEntryRespVOList)) {
+            List<Long> employeeIdList = oaEntryRespVOList.stream().map(OaEntryRespVO::getCurrentAuditEmployeeId).collect(Collectors.toList());
+            List<AdminUserRespDTO> employeeList = adminUserApi.getUserList(employeeIdList);
+            for (OaEntryRespVO respVO : oaEntryRespVOList) {
+                for (AdminUserRespDTO employee : employeeList) {
+                    if (respVO.getCurrentAuditEmployeeId() == employee.getId()) {
+                        respVO.setCurrentAuditEmployeeName(employee.getNickname());
+                        break;
+                    }
+                }
+            }
+
+            List<Long> deptIdList = oaEntryRespVOList.stream().map(OaEntryRespVO::getDeptId).collect(Collectors.toList());
+            List<DeptRespDTO> deptList = deptApi.getDeptList(deptIdList);
+            for (OaEntryRespVO respVO : oaEntryRespVOList) {
+                for (DeptRespDTO dept : deptList) {
+                    if (respVO.getDeptId() == dept.getId()) {
+                        respVO.setDeptName(dept.getName());
+                        break;
+                    }
+                }
+            }
+        }
+
+        return oaEntryRespVOPageResult;
     }
 
     @Override
-    public PageResult<OaEntryDO> getOaEntryPage(OaEntryPageReqVO pageReqVO) {
-        return oaEntryMapper.selectPage(pageReqVO);
+    public PageResult<OaEntryRespVO> exportOaEntryExcel(OaEntryPageReqVO pageReqVO) {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        return getOaEntryPage(pageReqVO);
+    }
+
+    private void validateOaEntryExists(Long id) {
+        OaEntryDO oaEntryDO = oaEntryMapper.selectById(id);
+        if (oaEntryDO == null) {
+            throw exception(OA_ENTRY_NOT_EXISTS);
+        }
+        if (!DictDataConstants.OA_AUDIT_STATUS_STAGING.equals(oaEntryDO.getAuditStatus())) {
+            throw exception(ErrorCodeConstants.DELETE_FAIL_NOT_STAGING);
+        }
+    }
+
+    /**
+     * 保存业务uuid到附件中
+     */
+    private void saveFileList(List<Long> fileIdList, String serviceId) {
+        if (CollectionUtil.isNotEmpty(fileIdList) && StrUtil.isNotEmpty(serviceId)) {
+            fileApi.updateFileBiz(fileIdList, serviceId);
+        }
     }
 
 }

+ 7 - 1
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/universal/OaUniversalServiceImpl.java

@@ -105,6 +105,8 @@ public class OaUniversalServiceImpl implements OaUniversalService {
         oaUniversal.setUserPhone(loginUser.getMobile());
         oaUniversal.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_STAGING);
         oaUniversal.setInfoSource("0");
+        // 暂存不保存审批人信息
+        oaUniversal.setStartUserSelectAssignees(null);
         // 保存或更新表单信息
         if (oaUniversal.getId() == null) {
             oaUniversalMapper.insert(oaUniversal);
@@ -566,9 +568,13 @@ public class OaUniversalServiceImpl implements OaUniversalService {
     }
 
     private void validateOaUniversalExists(Long id) {
-        if (oaUniversalMapper.selectById(id) == null) {
+        OaUniversalDO oaUniversalDO = oaUniversalMapper.selectById(id);
+        if (oaUniversalDO == null) {
             throw exception(OA_UNIVERSAL_NOT_EXISTS);
         }
+        if (!DictDataConstants.OA_AUDIT_STATUS_STAGING.equals(oaUniversalDO.getAuditStatus())) {
+            throw exception(ErrorCodeConstants.DELETE_FAIL_NOT_STAGING);
+        }
     }
 
     /**