Browse Source

1、领用审批接口

dongpo 7 tháng trước cách đây
mục cha
commit
2b64f3cc95
17 tập tin đã thay đổi với 1616 bổ sung15 xóa
  1. 5 0
      yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java
  2. 224 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/receive/OaReceiveController.java
  3. 80 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/receive/vo/OaReceivePageReqVO.java
  4. 119 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/receive/vo/OaReceiveRespVO.java
  5. 38 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/receive/vo/OaReceiveSaveReqVO.java
  6. 132 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/receive/OaReceiveDO.java
  7. 54 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/receive/OaReceiveObjDO.java
  8. 39 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/receive/OaReceiveMapper.java
  9. 25 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/receive/OaReceiveObjMapper.java
  10. 3 3
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/business/OaBusinessServiceImpl.java
  11. 3 3
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/leave/OaLeaveServiceImpl.java
  12. 3 3
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/out/OaOutServiceImpl.java
  13. 93 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/receive/OaReceiveService.java
  14. 780 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/receive/OaReceiveServiceImpl.java
  15. 3 3
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/renew/OaRenewServiceImpl.java
  16. 3 3
      yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/turnover/OaTurnoverServiceImpl.java
  17. 12 0
      yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/receive/OaReceiveMapper.xml

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

@@ -105,6 +105,9 @@ public interface ErrorCodeConstants {
     ErrorCode OA_BUSINESS_NOT_EXISTS = new ErrorCode(1_009_017_006, "出差信息不存在");
     // ========== 公务外出流程信息 1_009_017_007 ==========
     ErrorCode OA_OUT_NOT_EXISTS = new ErrorCode(1_009_017_007, "公务外出信息不存在");
+    // ========== 领用流程信息 1_009_017_008 ==========
+    ErrorCode OA_RECEIVE_NOT_EXISTS = new ErrorCode(1_009_017_008, "领用流程信息不存在");
+
 
     // ========== 员工信息 1_009_018_000 ==========
     ErrorCode OA_EMPLOYEE_NOT_EXISTS = new ErrorCode(1_009_018_000, "员工信息不存在");
@@ -112,4 +115,6 @@ public interface ErrorCodeConstants {
     // ========== 登录用户信息 1_009_018_001 ==========
     ErrorCode OA_LOGIN_USER_NOT_EXISTS = new ErrorCode(1_009_018_001, "登录用户不存在");
 
+    ErrorCode OA_RECEIVE_OBJ_NAME_BLANK = new ErrorCode(1_009_018_002, "领用子项领用物品名字不能为空");
+    ErrorCode OA_RECEIVE_OBJ_AMOUNT_ZERO = new ErrorCode(1_009_018_003, "领用子项领用物品数量必须为大于0的自然数");
 }

+ 224 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/receive/OaReceiveController.java

@@ -0,0 +1,224 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.oa.receive;
+
+import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+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;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceivePageReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceiveRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceiveSaveReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskReturnReqVO;
+import cn.iocoder.yudao.module.bpm.service.oa.receive.OaReceiveService;
+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.springdoc.api.annotations.ParameterObject;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.Valid;
+import java.io.IOException;
+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;
+
+@Tag(name = "管理后台 - 领用流程信息")
+@RestController
+@RequestMapping("/bpm/oa-receive")
+@Validated
+public class OaReceiveController {
+
+
+    @Resource
+    private OaReceiveService oaReceiveService;
+
+    @PostMapping("/staging")
+    @Operation(summary = "暂存领用审批流程信息")
+    @ApiOperationSupport(order = 1)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:staging')")
+    public CommonResult<Long> stagingOaReceive(@RequestBody OaReceiveSaveReqVO stagingReqVO) {
+        Long oaReceiveId = oaReceiveService.stagingOaReceive(stagingReqVO);
+        return success(oaReceiveId, "暂存成功");
+    }
+
+    @PostMapping("/commit")
+    @Operation(summary = "提交领用审批流程信息")
+    @ApiOperationSupport(order = 2)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:commit')")
+    public CommonResult<Long> commitOaReceive(@Valid @RequestBody OaReceiveSaveReqVO commitReqVO) {
+        Long oaReceiveId = oaReceiveService.commitOaReceive(commitReqVO);
+        return success(oaReceiveId, "提交成功");
+    }
+
+    @PostMapping("/agree")
+    @Operation(summary = "审批同意领用审批流程信息")
+    @ApiOperationSupport(order = 3)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:agree')")
+    public CommonResult<Long> agreeOaReceive(@Valid @RequestBody BpmTaskApproveReqVO agreeReqVO) {
+        Long result = oaReceiveService.agreeOaReceive(agreeReqVO);
+        return success(result, "审批成功");
+    }
+
+    @PostMapping("/disagree")
+    @Operation(summary = "驳回领用审批流程信息")
+    @ApiOperationSupport(order = 4)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:disagree')")
+    public CommonResult<Long> disagreeOaReceive(@Valid @RequestBody BpmTaskReturnReqVO disagreeReqVO) {
+        Long result = oaReceiveService.disagreeOaReceive(disagreeReqVO);
+        return success(result, "驳回成功");
+    }
+
+    @PostMapping("/revocation")
+    @Operation(summary = "撤回领用审批流程信息")
+    @ApiOperationSupport(order = 5)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:revocation')")
+    public CommonResult<Long> revocationOaReceive(@Valid @RequestBody BpmTaskApproveReqVO revocationReqVO) {
+        Long result = oaReceiveService.revocationOaReceive(revocationReqVO);
+        return success(result, "撤回成功");
+    }
+
+    @PostMapping("/reCommit")
+    @Operation(summary = "驳回或撤回后再次提交领用审批流程信息")
+    @ApiOperationSupport(order = 6)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:re-commit')")
+    public CommonResult<Long> reCommitOaReceive(@Valid @RequestBody OaReceiveSaveReqVO reCommitReqVO) {
+        Long result = oaReceiveService.reCommitOaReceive(reCommitReqVO);
+        return success(result, "再次提交成功");
+    }
+
+    @DeleteMapping("/close")
+    @Operation(summary = "驳回或撤回后关闭领用审批流程信息")
+    @ApiOperationSupport(order = 7)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-entry:close')")
+    public CommonResult<Long> closeOaReceive(@RequestParam("id") Long id) {
+        Long result = oaReceiveService.closeOaReceive(id);
+
+        return success(result, "关闭成功");
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除领用审批流程信息")
+    @ApiOperationSupport(order = 8)
+    @Parameter(name = "id", description = "编号", required = true)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:delete')")
+    public CommonResult<Boolean> deleteOaReceive(@RequestParam("id") Long id) {
+        oaReceiveService.deleteOaReceive(id);
+        return success(true, "删除成功");
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "根据id获得领用审批流程信息")
+    @Parameter(name = "id", description = "编号", required = true, example = "1")
+    @ApiOperationSupport(order = 9)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:query-id')")
+    public CommonResult<OaReceiveRespVO> getOaReceive(@RequestParam("id") Long id) {
+        OaReceiveRespVO respVO = oaReceiveService.getOaReceive(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-receive:query-proc-inst-id')")
+    public CommonResult<OaReceiveRespVO> getOaReceiveByProcInstId(@RequestParam("procInstId") String procInstId) {
+        OaReceiveRespVO respVO = oaReceiveService.getOaReceiveByProcInstId(procInstId);
+        return success(respVO, "查询对象成功");
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得领用审批流程信息分页")
+    @ApiOperationSupport(order = 11)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:query-page')")
+    public CommonResult<PageResult<OaReceiveRespVO>> getOaReceivePage(@Valid @ParameterObject OaReceivePageReqVO pageReqVO) {
+        return success(oaReceiveService.getOaReceivePage(pageReqVO), "查询列表成功");
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出领用审批流程信息 Excel")
+    @ApiOperationSupport(order = 12)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:export')")
+    @ApiAccessLog(operateType = EXPORT)
+    public void exportOaReceiveExcel(@ParameterObject OaReceivePageReqVO pageReqVO,
+                                 HttpServletResponse response) throws IOException {
+        PageResult<OaReceiveRespVO> pageResult = oaReceiveService.exportOaReceiveExcel(pageReqVO);
+        List<OaReceiveRespVO> list = pageResult.getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "领用审批流程信息.xls", "数据", OaReceiveRespVO.class,
+                BeanUtils.toBean(list, OaReceiveRespVO.class));
+    }
+
+    // @Resource
+    // private OaReceiveService oaReceiveService;
+    //
+    // @PostMapping("/create")
+    // @Operation(summary = "创建领用流程信息")
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:create')")
+    // public CommonResult<Long> createOaReceive(@Valid @RequestBody OaReceiveSaveReqVO createReqVO) {
+    //     return success(oaReceiveService.createOaReceive(createReqVO));
+    // }
+    //
+    // @PutMapping("/update")
+    // @Operation(summary = "更新领用流程信息")
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:update')")
+    // public CommonResult<Boolean> updateOaReceive(@Valid @RequestBody OaReceiveSaveReqVO updateReqVO) {
+    //     oaReceiveService.updateOaReceive(updateReqVO);
+    //     return success(true);
+    // }
+    //
+    // @DeleteMapping("/delete")
+    // @Operation(summary = "删除领用流程信息")
+    // @Parameter(name = "id", description = "编号", required = true)
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:delete')")
+    // public CommonResult<Boolean> deleteOaReceive(@RequestParam("id") Long id) {
+    //     oaReceiveService.deleteOaReceive(id);
+    //     return success(true);
+    // }
+    //
+    // @GetMapping("/get")
+    // @Operation(summary = "获得领用流程信息")
+    // @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:query')")
+    // public CommonResult<OaReceiveRespVO> getOaReceive(@RequestParam("id") Long id) {
+    //     OaReceiveDO oaReceive = oaReceiveService.getOaReceive(id);
+    //     return success(BeanUtils.toBean(oaReceive, OaReceiveRespVO.class));
+    // }
+    //
+    // @GetMapping("/page")
+    // @Operation(summary = "获得领用流程信息分页")
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:query')")
+    // public CommonResult<PageResult<OaReceiveRespVO>> getOaReceivePage(@Valid OaReceivePageReqVO pageReqVO) {
+    //     PageResult<OaReceiveDO> pageResult = oaReceiveService.getOaReceivePage(pageReqVO);
+    //     return success(BeanUtils.toBean(pageResult, OaReceiveRespVO.class));
+    // }
+    //
+    // @GetMapping("/export-excel")
+    // @Operation(summary = "导出领用流程信息 Excel")
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:export')")
+    // @ApiAccessLog(operateType = EXPORT)
+    // public void exportOaReceiveExcel(@Valid OaReceivePageReqVO pageReqVO,
+    //           HttpServletResponse response) throws IOException {
+    //     pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+    //     List<OaReceiveDO> list = oaReceiveService.getOaReceivePage(pageReqVO).getList();
+    //     // 导出 Excel
+    //     ExcelUtils.write(response, "领用流程信息.xls", "数据", OaReceiveRespVO.class,
+    //                     BeanUtils.toBean(list, OaReceiveRespVO.class));
+    // }
+    //
+    // // ==================== 子表(领用流程信息子表) ====================
+    //
+    // @GetMapping("/oa-receive-obj/list-by-receive-id")
+    // @Operation(summary = "获得领用流程信息子表列表")
+    // @Parameter(name = "receiveId", description = "领用主表id")
+    // @PreAuthorize("@ss.hasPermission('bpm:oa-receive:query')")
+    // public CommonResult<List<OaReceiveObjDO>> getOaReceiveObjListByReceiveId(@RequestParam("receiveId") Long receiveId) {
+    //     return success(oaReceiveService.getOaReceiveObjListByReceiveId(receiveId));
+    // }
+
+}

+ 80 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/receive/vo/OaReceivePageReqVO.java

@@ -0,0 +1,80 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.*;
+import java.util.*;
+import io.swagger.v3.oas.annotations.media.Schema;
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
+import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 领用流程信息分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class OaReceivePageReqVO extends PageParam {
+
+    @Schema(description = "领用人id", example = "1")
+    private Long employeeId;
+
+    @Schema(description = "领用员工姓名", example = "赵六")
+    private String employeeName;
+
+    @Schema(description = "领用员工手机号")
+    private String employeePhone;
+
+    @Schema(description = "用户账号id", example = "13756")
+    private Long userId;
+
+    @Schema(description = "部门id", example = "17336")
+    private Long deptId;
+
+    @Schema(description = "部门名称")
+    private String deptName;
+
+    @Schema(description = "员工职位")
+    private String position;
+
+    @Schema(description = "领用日期")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
+    private String[] receiveDate;
+
+    @Schema(description = "领用原因", example = "不喜欢")
+    private String reason;
+
+    @Schema(description = "备注")
+    private String remarks;
+
+    @Schema(description = "流程实例id", example = "13073")
+    private String procInstId;
+
+    @Schema(description = "审核状态(0暂存、1已提交、2审核中、3已审核、4已关闭、5已驳回)", example = "2")
+    private String auditStatus;
+
+    @Schema(description = "当前审核人员工id", example = "10618")
+    private Long currentAuditEmployeeId;
+
+    @Schema(description = "当前审核人员工姓名", example = "王五")
+    private String currentAuditEmployeeName;
+
+    @Schema(description = "当前审核人用户id", example = "744")
+    private Long currentAuditUserId;
+
+    @Schema(description = "最后审核时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] finalAuditDate;
+
+    @Schema(description = "申请人员工id", example = "1")
+    private Long applyEmployeeId;
+
+    @Schema(description = "申请人员工姓名", example = "李四")
+    private String applyEmployeeName;
+
+    @Schema(description = "创建时间")
+    @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+    private LocalDateTime[] createTime;
+
+}

+ 119 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/receive/vo/OaReceiveRespVO.java

@@ -0,0 +1,119 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo;
+
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.receive.OaReceiveObjDO;
+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.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - 领用流程信息 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class OaReceiveRespVO {
+
+    @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @ExcelProperty("主键")
+    private Long id;
+
+    @Schema(description = "uuid", requiredMode = Schema.RequiredMode.REQUIRED, example = "28035")
+    @ExcelProperty("uuid")
+    private String receiveUuid;
+
+    @Schema(description = "领用人id", example = "1")
+    @ExcelProperty("领用人id")
+    private Long employeeId;
+
+    @Schema(description = "领用员工姓名", example = "赵六")
+    @ExcelProperty("领用员工姓名")
+    private String employeeName;
+
+    @Schema(description = "领用员工手机号")
+    @ExcelProperty("领用员工手机号")
+    private String employeePhone;
+
+    @Schema(description = "用户账号id", example = "13756")
+    @ExcelProperty("用户账号id")
+    private Long userId;
+
+    @Schema(description = "部门id", example = "17336")
+    @ExcelProperty("部门id")
+    private Long deptId;
+
+    @Schema(description = "部门名称")
+    @ExcelProperty("部门名称")
+    private String deptName;
+
+    @Schema(description = "员工职位")
+    @ExcelProperty("员工职位")
+    private String position;
+
+    @Schema(description = "领用日期", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("领用日期")
+    private String receiveDate;
+
+    @Schema(description = "领用原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "不喜欢")
+    @ExcelProperty("领用原因")
+    private String reason;
+
+    @Schema(description = "流程实例id", example = "13073")
+    @ExcelProperty("流程实例id")
+    private String procInstId;
+
+    @Schema(description = "审核状态(0暂存、1已提交、2审核中、3已审核、4已关闭、5已驳回)", example = "2")
+    @ExcelProperty("审核状态(0暂存、1已提交、2审核中、3已审核、4已关闭、5已驳回)")
+    private String auditStatus;
+
+    @Schema(description = "当前审核人员工id", example = "10618")
+    @ExcelProperty("当前审核人员工id")
+    private Long currentAuditEmployeeId;
+
+    @Schema(description = "当前审核人员工姓名", example = "王五")
+    @ExcelProperty("当前审核人员工姓名")
+    private String currentAuditEmployeeName;
+
+    @Schema(description = "当前审核人用户id", example = "744")
+    @ExcelProperty("当前审核人用户id")
+    private Long currentAuditUserId;
+
+    @Schema(description = "最后审核时间")
+    @ExcelProperty("最后审核时间")
+    private LocalDateTime finalAuditDate;
+
+    @Schema(description = "申请人员工id", example = "1")
+    @ExcelProperty("申请人员工id")
+    private Long applyEmployeeId;
+
+    @Schema(description = "申请人员工姓名", example = "李四")
+    @ExcelProperty("申请人员工姓名")
+    private String applyEmployeeName;
+
+    @Schema(description = "数据来源,0流程添加、1手动添加")
+    @ExcelProperty("数据来源,0流程添加、1手动添加")
+    private String infoSource;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "领用流程信息子表列表")
+    private List<OaReceiveObjDO> oaReceiveObjs;
+
+    @Schema(description = "附件列表")
+    private List<FileDTO> fileList;
+
+    @Schema(description = "审批记录列表")
+    private List<BpmTaskRespVO> auditRecordList;
+
+    @Schema(description = "审批人员列表")
+    private List<AdminUserRespDTO> auditUserList;
+
+    @Schema(description = "当前用户待处理的任务id")
+    private String taskId;
+
+}

+ 38 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/oa/receive/vo/OaReceiveSaveReqVO.java

@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import javax.validation.constraints.*;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.receive.OaReceiveObjDO;
+
+@Schema(description = "管理后台 - 领用流程信息新增/修改 Request VO")
+@Data
+public class OaReceiveSaveReqVO {
+
+    @Schema(description = "主键", example = "1")
+    private Long id;
+
+    @Schema(description = "领用日期")
+    @NotEmpty(message = "领用日期不能为空")
+    private String receiveDate;
+
+    @Schema(description = "领用原因", example = "喜欢")
+    @NotEmpty(message = "领用原因不能为空")
+    private String reason;
+
+    @Schema(description = "备注")
+    private String remarks;
+
+    @Schema(description = "领用流程信息子项列表")
+    @NotEmpty(message = "领用流程信息子项列表不能为空")
+    private List<OaReceiveObjDO> oaReceiveObjs;
+
+    @Schema(description = "发起人自选审批人", example = " [100, 1]")
+    @NotEmpty(message = "发起人自选审批人不能为空")
+    private List<Long> startUserSelectAssignees;
+
+    @Schema(description = "附件主键id", example = "[1, 2]")
+    private List<Long> fileIdList;
+
+}

+ 132 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/receive/OaReceiveDO.java

@@ -0,0 +1,132 @@
+package cn.iocoder.yudao.module.bpm.dal.dataobject.oa.receive;
+
+import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * 领用流程信息 DO
+ *
+ * @author dp
+ */
+@TableName("bpm_oa_receive")
+@KeySequence("bpm_oa_receive_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OaReceiveDO extends BaseDO {
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * uuid
+     */
+    private String receiveUuid;
+    /**
+     * 领用人id
+     */
+    private Long employeeId;
+    /**
+     * 领用人uuid
+     */
+    private String employeeUuid;
+    /**
+     * 领用员工姓名
+     */
+    private String employeeName;
+    /**
+     * 领用员工手机号
+     */
+    private String employeePhone;
+    /**
+     * 用户账号id
+     */
+    private Long userId;
+    /**
+     * 用户账号uuid
+     */
+    private String userUuid;
+    /**
+     * 部门id
+     */
+    private Long deptId;
+    /**
+     * 部门uuid
+     */
+    private String deptUuid;
+    /**
+     * 员工职位
+     */
+    private String position;
+    /**
+     * 领用日期
+     */
+    private String receiveDate;
+    /**
+     * 领用原因
+     */
+    private String reason;
+    /**
+     * 备注
+     */
+    private String remarks;
+    /**
+     * 流程实例id
+     */
+    private String procInstId;
+    /**
+     * 审核状态(0暂存、1已提交、2审核中、3已审核、4已关闭、5已驳回)
+     */
+    private String auditStatus;
+    /**
+     * 当前审核人员工id
+     */
+    private Long currentAuditEmployeeId;
+    /**
+     * 当前审核人员工uuid
+     */
+    private String currentAuditEmployeeUuid;
+    /**
+     * 当前审核人员工姓名
+     */
+    private String currentAuditEmployeeName;
+    /**
+     * 当前审核人用户id
+     */
+    private Long currentAuditUserId;
+    /**
+     * 当前审核人用户uuid
+     */
+    private String currentAuditUserUuid;
+    /**
+     * 最后审核时间
+     */
+    private LocalDateTime finalAuditDate;
+    /**
+     * 发起人选择的审批人
+     */
+    private String startUserSelectAssignees;
+    /**
+     * 申请人员工id
+     */
+    private Long applyEmployeeId;
+    /**
+     * 申请人员工姓名
+     */
+    private String applyEmployeeName;
+    /**
+     * 数据来源,0流程添加、1手动添加
+     */
+    private String infoSource;
+
+}

+ 54 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/oa/receive/OaReceiveObjDO.java

@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.bpm.dal.dataobject.oa.receive;
+
+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.*;
+
+/**
+ * 领用流程信息子表 DO
+ *
+ * @author dp
+ */
+@TableName("bpm_oa_receive_obj")
+@KeySequence("bpm_oa_receive_obj_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OaReceiveObjDO extends BaseDO {
+
+    /**
+     * 主键
+     */
+    @TableId
+    private Long id;
+    /**
+     * 领用主表id
+     */
+    private Long receiveId;
+    /**
+     * 领用主表uuid
+     */
+    private String receiveUuid;
+    /**
+     * 领用子表uuid
+     */
+    private String receiveObjId;
+    /**
+     * 领用物品名称
+     */
+    private String name;
+    /**
+     * 领用数量
+     */
+    private Integer amount;
+    /**
+     * 规格型号
+     */
+    private String config;
+
+}

+ 39 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/receive/OaReceiveMapper.java

@@ -0,0 +1,39 @@
+package cn.iocoder.yudao.module.bpm.dal.mysql.oa.receive;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceivePageReqVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.receive.OaReceiveDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 领用流程信息 Mapper
+ *
+ * @author dp
+ */
+@Mapper
+public interface OaReceiveMapper extends BaseMapperX<OaReceiveDO> {
+
+    default PageResult<OaReceiveDO> selectPage(OaReceivePageReqVO reqVO) {
+        return selectPage(reqVO, new LambdaQueryWrapperX<OaReceiveDO>()
+                .eqIfPresent(OaReceiveDO::getEmployeeId, reqVO.getEmployeeId())
+                .likeIfPresent(OaReceiveDO::getEmployeeName, reqVO.getEmployeeName())
+                .eqIfPresent(OaReceiveDO::getEmployeePhone, reqVO.getEmployeePhone())
+                .eqIfPresent(OaReceiveDO::getUserId, reqVO.getUserId())
+                .eqIfPresent(OaReceiveDO::getDeptId, reqVO.getDeptId())
+                .eqIfPresent(OaReceiveDO::getPosition, reqVO.getPosition())
+                .betweenIfPresent(OaReceiveDO::getReceiveDate, reqVO.getReceiveDate())
+                .eqIfPresent(OaReceiveDO::getProcInstId, reqVO.getProcInstId())
+                .eqIfPresent(OaReceiveDO::getAuditStatus, reqVO.getAuditStatus())
+                .eqIfPresent(OaReceiveDO::getCurrentAuditEmployeeId, reqVO.getCurrentAuditEmployeeId())
+                .likeIfPresent(OaReceiveDO::getCurrentAuditEmployeeName, reqVO.getCurrentAuditEmployeeName())
+                .eqIfPresent(OaReceiveDO::getCurrentAuditUserId, reqVO.getCurrentAuditUserId())
+                .betweenIfPresent(OaReceiveDO::getFinalAuditDate, reqVO.getFinalAuditDate())
+                .eqIfPresent(OaReceiveDO::getApplyEmployeeId, reqVO.getApplyEmployeeId())
+                .likeIfPresent(OaReceiveDO::getApplyEmployeeName, reqVO.getApplyEmployeeName())
+                .betweenIfPresent(OaReceiveDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(OaReceiveDO::getId));
+    }
+
+}

+ 25 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/oa/receive/OaReceiveObjMapper.java

@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.bpm.dal.mysql.oa.receive;
+
+import java.util.*;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.receive.OaReceiveObjDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 领用流程信息子表 Mapper
+ *
+ * @author dp
+ */
+@Mapper
+public interface OaReceiveObjMapper extends BaseMapperX<OaReceiveObjDO> {
+
+    default List<OaReceiveObjDO> selectListByReceiveId(Long receiveId) {
+        return selectList(OaReceiveObjDO::getReceiveId, receiveId);
+    }
+
+    default int deleteByReceiveId(Long receiveId) {
+        return delete(OaReceiveObjDO::getReceiveId, receiveId);
+    }
+
+}

+ 3 - 3
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/business/OaBusinessServiceImpl.java

@@ -87,7 +87,7 @@ public class OaBusinessServiceImpl implements OaBusinessService {
         Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
         AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
         Objects.requireNonNull(loginUser, "登录用户不能为空");
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(stagingReqVO.getEmployeeId());
 
         OaBusinessDO oaBusiness = BeanUtils.toBean(stagingReqVO, OaBusinessDO.class);
@@ -135,7 +135,7 @@ public class OaBusinessServiceImpl implements OaBusinessService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(commitReqVO.getEmployeeId());
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);
@@ -377,7 +377,7 @@ public class OaBusinessServiceImpl implements OaBusinessService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(reCommitReqVO.getEmployeeId());
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);

+ 3 - 3
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/leave/OaLeaveServiceImpl.java

@@ -89,7 +89,7 @@ public class OaLeaveServiceImpl implements OaLeaveService {
         Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
         AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
         Objects.requireNonNull(loginUser, "登录用户不能为空");
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
 
         OaLeaveDO oaLeave = BeanUtils.toBean(stagingReqVO, OaLeaveDO.class);
@@ -136,7 +136,7 @@ public class OaLeaveServiceImpl implements OaLeaveService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);
@@ -378,7 +378,7 @@ public class OaLeaveServiceImpl implements OaLeaveService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);

+ 3 - 3
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/out/OaOutServiceImpl.java

@@ -88,7 +88,7 @@ public class OaOutServiceImpl implements OaOutService {
         Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
         AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
         Objects.requireNonNull(loginUser, "登录用户不能为空");
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
 
         OaOutDO oaOut = BeanUtils.toBean(stagingReqVO, OaOutDO.class);
@@ -136,7 +136,7 @@ public class OaOutServiceImpl implements OaOutService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);
@@ -378,7 +378,7 @@ public class OaOutServiceImpl implements OaOutService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);

+ 93 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/receive/OaReceiveService.java

@@ -0,0 +1,93 @@
+package cn.iocoder.yudao.module.bpm.service.oa.receive;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceivePageReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceiveRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceiveSaveReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskApproveReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskReturnReqVO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.receive.OaReceiveObjDO;
+
+import java.util.List;
+
+/**
+ * 领用流程信息 Service 接口
+ *
+ * @author dp
+ */
+public interface OaReceiveService {
+
+
+    Long stagingOaReceive(OaReceiveSaveReqVO stagingReqVO);
+
+    Long commitOaReceive(OaReceiveSaveReqVO commitReqVO);
+
+    Long agreeOaReceive(BpmTaskApproveReqVO agreeReqVO);
+
+    Long disagreeOaReceive(BpmTaskReturnReqVO disagreeReqVO);
+
+    Long revocationOaReceive(BpmTaskApproveReqVO revocationReqVO);
+
+    Long reCommitOaReceive(OaReceiveSaveReqVO reCommitReqVO);
+
+    Long closeOaReceive(Long id);
+
+    void deleteOaReceive(Long id);
+
+    OaReceiveRespVO getOaReceive(Long id);
+
+    OaReceiveRespVO getOaReceiveByProcInstId(String procInstId);
+
+    PageResult<OaReceiveRespVO> getOaReceivePage(OaReceivePageReqVO pageReqVO);
+
+    PageResult<OaReceiveRespVO> exportOaReceiveExcel(OaReceivePageReqVO pageReqVO);
+
+    // /**
+    //  * 创建领用流程信息
+    //  *
+    //  * @param createReqVO 创建信息
+    //  * @return 编号
+    //  */
+    // Long createOaReceive(@Valid OaReceiveSaveReqVO createReqVO);
+    //
+    // /**
+    //  * 更新领用流程信息
+    //  *
+    //  * @param updateReqVO 更新信息
+    //  */
+    // void updateOaReceive(@Valid OaReceiveSaveReqVO updateReqVO);
+    //
+    // /**
+    //  * 删除领用流程信息
+    //  *
+    //  * @param id 编号
+    //  */
+    // void deleteOaReceive(Long id);
+    //
+    // /**
+    //  * 获得领用流程信息
+    //  *
+    //  * @param id 编号
+    //  * @return 领用流程信息
+    //  */
+    // OaReceiveDO getOaReceive(Long id);
+    //
+    // /**
+    //  * 获得领用流程信息分页
+    //  *
+    //  * @param pageReqVO 分页查询
+    //  * @return 领用流程信息分页
+    //  */
+    // PageResult<OaReceiveDO> getOaReceivePage(OaReceivePageReqVO pageReqVO);
+
+    // ==================== 子表(领用流程信息子表) ====================
+
+    /**
+     * 获得领用流程信息子表列表
+     *
+     * @param receiveId 领用主表id
+     * @return 领用流程信息子表列表
+     */
+    List<OaReceiveObjDO> getOaReceiveObjListByReceiveId(Long receiveId);
+
+}

+ 780 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/receive/OaReceiveServiceImpl.java

@@ -0,0 +1,780 @@
+package cn.iocoder.yudao.module.bpm.service.oa.receive;
+
+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.receive.vo.OaReceivePageReqVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceiveRespVO;
+import cn.iocoder.yudao.module.bpm.controller.admin.oa.receive.vo.OaReceiveSaveReqVO;
+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.receive.OaReceiveDO;
+import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.receive.OaReceiveObjDO;
+import cn.iocoder.yudao.module.bpm.dal.mysql.oa.receive.OaReceiveMapper;
+import cn.iocoder.yudao.module.bpm.dal.mysql.oa.receive.OaReceiveObjMapper;
+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 org.apache.commons.lang3.StringUtils;
+import org.flowable.engine.TaskService;
+import org.flowable.task.api.Task;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+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_RECEIVE_NOT_EXISTS;
+
+/**
+ * 领用流程信息 Service 实现类
+ *
+ * @author dp
+ */
+@Service
+@Validated
+public class OaReceiveServiceImpl implements OaReceiveService {
+
+
+    /**
+     * 对应的流程定义 KEY
+     */
+    public static final String PROCESS_KEY = "oa_receive";
+
+
+    @Resource
+    private OaReceiveMapper oaReceiveMapper;
+
+    @Resource
+    private OaReceiveObjMapper oaReceiveObjMapper;
+
+    @Resource
+    private BpmProcessInstanceApi processInstanceApi;
+
+    @Resource
+    private BpmTaskService bpmTaskService;
+
+    @Resource
+    private TaskService taskService;
+
+    @Resource
+    private FileApi fileApi;
+
+    @Resource
+    private AdminUserApi adminUserApi;
+
+    @Resource
+    private DeptApi deptApi;
+
+    @Override
+    @Transactional
+    public Long stagingOaReceive(OaReceiveSaveReqVO stagingReqVO) {
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
+        Objects.requireNonNull(loginUser, "登录用户不能为空");
+        // 人信息
+        AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
+
+        OaReceiveDO oaReceive = BeanUtils.toBean(stagingReqVO, OaReceiveDO.class);
+        if (StringUtils.isBlank(oaReceive.getReceiveUuid())) {
+            // 创建单据uuid
+            String uuid = IdUtil.fastSimpleUUID();
+            oaReceive.setReceiveUuid(uuid);
+        }
+        if (employee != null) {
+            oaReceive.setEmployeeId(loginUser.getId());
+            oaReceive.setEmployeeName(loginUser.getNickname());
+            oaReceive.setEmployeePhone(loginUser.getMobile());
+            oaReceive.setDeptId(loginUser.getDeptId());
+            oaReceive.setPosition("员工职位");
+            oaReceive.setUserId(loginUser.getId());
+        }
+        oaReceive.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_STAGING);
+        oaReceive.setInfoSource("0");
+        oaReceive.setApplyEmployeeId(loginUser.getId());
+        oaReceive.setApplyEmployeeName(loginUser.getNickname());
+        // 暂存不保存审批人信息
+        oaReceive.setStartUserSelectAssignees(null);
+
+        // 保存或更新表单信息
+        if (oaReceive.getId() == null) {
+            oaReceiveMapper.insert(oaReceive);
+        } else {
+            validateOaReceiveExists(oaReceive.getId());
+            oaReceiveMapper.updateById(oaReceive);
+        }
+        // 保存子表信息
+        List<OaReceiveObjDO> oaReceiveObjs = stagingReqVO.getOaReceiveObjs();
+        if (CollectionUtil.isNotEmpty(oaReceiveObjs)) {
+            updateOaReceiveObjList(oaReceive.getId(), oaReceiveObjs);
+        }
+
+        // 保存业务uuid到附件中
+        saveFileList(stagingReqVO.getFileIdList(), oaReceive.getReceiveUuid());
+
+        return oaReceive.getId();
+    }
+
+    @Override
+    @Transactional
+    public Long commitOaReceive(OaReceiveSaveReqVO 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);
+        if (loginUser == null) {
+            throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
+        }
+        // 人信息
+        AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
+        if (employee == null) {
+            throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);
+        }
+
+
+        OaReceiveDO oaReceive = BeanUtils.toBean(commitReqVO, OaReceiveDO.class);
+        if (StringUtils.isBlank(oaReceive.getReceiveUuid())) {
+            // 创建单据uuid
+            String uuid = IdUtil.fastSimpleUUID();
+            oaReceive.setReceiveUuid(uuid);
+        }
+        oaReceive.setEmployeeId(employee.getId());
+        oaReceive.setEmployeeName(employee.getNickname());
+        oaReceive.setEmployeePhone(employee.getMobile());
+        oaReceive.setDeptId(employee.getDeptId());
+        oaReceive.setPosition("员工职位");
+        oaReceive.setUserId(loginUser.getId());
+        oaReceive.setInfoSource("0");
+        oaReceive.setApplyEmployeeId(loginUser.getId());
+        oaReceive.setApplyEmployeeName(loginUser.getNickname());
+
+        // 子表信息
+        List<OaReceiveObjDO> oaReceiveObjs = commitReqVO.getOaReceiveObjs();
+        for (OaReceiveObjDO oaReceiveObj : oaReceiveObjs) {
+            if (StrUtil.isBlank(oaReceiveObj.getName())) {
+                throw exception(ErrorCodeConstants.OA_RECEIVE_OBJ_NAME_BLANK);
+            }
+            if (oaReceiveObj.getAmount() == null || oaReceiveObj.getAmount() == 0) {
+                throw exception(ErrorCodeConstants.OA_RECEIVE_OBJ_AMOUNT_ZERO);
+            }
+        }
+
+        // 保存或更新表单信息
+        if (oaReceive.getId() == null) {
+            oaReceiveMapper.insert(oaReceive);
+        } else {
+            OaReceiveDO oaReceiveDO = validateOaReceiveExists(oaReceive.getId());
+            if (StrUtil.isNotBlank(oaReceiveDO.getProcInstId())) {
+                throw exception(ErrorCodeConstants.PROCESS_INSTANCE_CREATE_FAIL_HAS_PROCESS);
+            }
+            oaReceiveMapper.updateById(oaReceive);
+        }
+        // 保存子表
+        if (CollectionUtil.isNotEmpty(oaReceiveObjs)) {
+            updateOaReceiveObjList(oaReceive.getId(), oaReceiveObjs);
+        }
+
+        // 发起流程
+        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(oaReceive.getId()))
+                                .setStartUserSelectAssignees(startUserSelectAssignees));
+
+        //获取下一个审批人
+        Task task = taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
+
+        // 审批同意
+        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);
+        }
+        Long currentAuditEmployeeId = Long.valueOf(nextTask.getAssignee());
+        AdminUserRespDTO currentAuditEmployee = adminUserApi.getUser(currentAuditEmployeeId);
+
+
+        // 将工作流的流程实例ID、单据状态、最后一次审批时间、当前审批人更新到单据信息中
+        oaReceiveMapper.updateById(new OaReceiveDO()
+                .setId(oaReceive.getId())
+                .setProcInstId(processInstanceId)
+                .setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_COMMITTED)
+                .setFinalAuditDate(LocalDateTime.now())
+                .setCurrentAuditEmployeeId(currentAuditEmployeeId)
+                .setCurrentAuditEmployeeName(currentAuditEmployee.getNickname())
+                .setStartUserSelectAssignees(selectAssignees.stream().map(String::valueOf).collect(Collectors.joining(","))));
+        // 保存业务uuid到附件中
+        saveFileList(commitReqVO.getFileIdList(), oaReceive.getReceiveUuid());
+        // TODO DP 发送提交成功站内信
+        return oaReceive.getId();
+    }
+
+    @Override
+    @Transactional
+    public Long agreeOaReceive(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<OaReceiveDO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+        lambdaQueryWrapper.eq(OaReceiveDO::getProcInstId, currentTask.getProcessInstanceId());
+        OaReceiveDO oaReceive = oaReceiveMapper.selectOne(lambdaQueryWrapper);
+        // 如果是最后一个人审批同意,设置流程审批状态为已审核
+        String[] auditPersons = oaReceive.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);
+        }
+        // 审批同意
+        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();
+        OaReceiveDO oaReceiveDO = new OaReceiveDO();
+        if (nextTask != null) {
+            Long currentAuditEmployeeId = Long.valueOf(nextTask.getAssignee());
+            AdminUserRespDTO currentAuditEmployee = adminUserApi.getUser(currentAuditEmployeeId);
+
+            // 如果审批人重复,实际未结束,再次更新为审核中
+            taskService.setVariable(nextTask.getId(), BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, DictDataConstants.OA_AUDIT_STATUS_AUDITING);
+            oaReceiveDO.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_AUDITING)
+                    .setCurrentAuditEmployeeId(currentAuditEmployeeId)
+                    .setCurrentAuditEmployeeName(currentAuditEmployee.getNickname())
+                    .setFinalAuditDate(LocalDateTime.now())
+                    .setId(oaReceive.getId());
+
+        } else {
+            oaReceiveDO.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_AUDITED)
+                    .setCurrentAuditEmployeeId(null)
+                    .setCurrentAuditEmployeeName(null)
+                    .setFinalAuditDate(LocalDateTime.now())
+                    .setId(oaReceive.getId());
+
+            // TODO 复制业务单据信息到业务模块单据表
+
+        }
+        oaReceiveMapper.updateById(oaReceiveDO);
+        // 发送通知
+
+        // 返回
+        return 1L;
+    }
+
+    @Override
+    @Transactional
+    public Long disagreeOaReceive(BpmTaskReturnReqVO disagreeReqVO) {
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        Task currentTask = bpmTaskService.getTask(disagreeReqVO.getId());
+
+        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();
+        Long currentAuditEmployeeId = Long.valueOf(nextTask.getAssignee());
+        AdminUserRespDTO currentAuditEmployee = adminUserApi.getUser(currentAuditEmployeeId);
+
+        // 更新单据状态,当前处理人,最后处理时间
+        LambdaUpdateWrapper<OaReceiveDO> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.set(OaReceiveDO::getCurrentAuditEmployeeId, currentAuditEmployeeId)
+                .set(OaReceiveDO::getCurrentAuditEmployeeName, currentAuditEmployee.getNickname())
+                .set(OaReceiveDO::getFinalAuditDate, LocalDateTime.now())
+                .set(OaReceiveDO::getAuditStatus, DictDataConstants.OA_AUDIT_STATUS_RETURNED)
+                .eq(OaReceiveDO::getProcInstId, currentTask.getProcessInstanceId());
+        oaReceiveMapper.update(updateWrapper);
+
+        // 发送通知
+
+        return 1L;
+    }
+
+    @Override
+    @Transactional
+    public Long revocationOaReceive(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<OaReceiveDO> lambdaQueryWrapper = new LambdaQueryWrapper<OaReceiveDO>()
+                .eq(OaReceiveDO::getProcInstId, currentTask.getProcessInstanceId());
+        OaReceiveDO oaReceiveDO = oaReceiveMapper.selectOne(lambdaQueryWrapper);
+        if (!DictDataConstants.OA_AUDIT_STATUS_COMMITTED.equals(oaReceiveDO.getAuditStatus())
+                || !Objects.equals(String.valueOf(loginUserId), oaReceiveDO.getCreator())) {
+            throw ServiceExceptionUtil.exception(ErrorCodeConstants.TASK_REVOCATION_NOT_ALLOWED);
+        }
+
+        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 nextTask = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
+        Long currentAuditEmployeeId = Long.valueOf(nextTask.getAssignee());
+        AdminUserRespDTO currentAuditEmployee = adminUserApi.getUser(currentAuditEmployeeId);
+
+        // 更新单据状态,当前处理人,最后处理时间
+        LambdaUpdateWrapper<OaReceiveDO> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.set(OaReceiveDO::getCurrentAuditEmployeeId, currentAuditEmployeeId)
+                .set(OaReceiveDO::getCurrentAuditEmployeeName, currentAuditEmployee.getNickname())
+                .set(OaReceiveDO::getFinalAuditDate, LocalDateTime.now())
+                .set(OaReceiveDO::getAuditStatus, DictDataConstants.OA_AUDIT_STATUS_RECALLED)
+                .eq(OaReceiveDO::getProcInstId, currentTask.getProcessInstanceId());
+        oaReceiveMapper.update(updateWrapper);
+
+        // 发送通知
+
+        return 1L;
+    }
+
+    @Override
+    @Transactional
+    public Long reCommitOaReceive(OaReceiveSaveReqVO reCommitReqVO) {
+        if (reCommitReqVO.getId() == null) {
+            throw exception(ErrorCodeConstants.SERVICE_ID_NOT_EXISTS);
+        }
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
+        if (loginUser == null) {
+            throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
+        }
+        // 人信息
+        AdminUserRespDTO employee = adminUserApi.getUser(loginUserId);
+        if (employee == null) {
+            throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);
+        }
+
+        OaReceiveDO oaReceiveNew = BeanUtils.toBean(reCommitReqVO, OaReceiveDO.class);
+        OaReceiveDO oaReceiveOld = validateOaReceiveExists(oaReceiveNew.getId());
+        oaReceiveNew.setReceiveUuid(oaReceiveOld.getReceiveUuid())
+                .setProcInstId(oaReceiveOld.getProcInstId());
+
+        oaReceiveNew.setEmployeeId(employee.getId());
+        oaReceiveNew.setEmployeeName(employee.getNickname());
+        oaReceiveNew.setEmployeePhone(employee.getMobile());
+        oaReceiveNew.setDeptId(employee.getDeptId());
+        oaReceiveNew.setPosition("员工职位");
+        oaReceiveNew.setUserId(loginUser.getId());
+        oaReceiveNew.setApplyEmployeeId(loginUser.getId());
+        oaReceiveNew.setApplyEmployeeName(loginUser.getNickname());
+
+        // 子表信息
+        List<OaReceiveObjDO> oaReceiveObjs = reCommitReqVO.getOaReceiveObjs();
+        for (OaReceiveObjDO oaReceiveObj : oaReceiveObjs) {
+            if (StrUtil.isBlank(oaReceiveObj.getName())) {
+                throw exception(ErrorCodeConstants.OA_RECEIVE_OBJ_NAME_BLANK);
+            }
+            if (oaReceiveObj.getAmount() == null || oaReceiveObj.getAmount() == 0) {
+                throw exception(ErrorCodeConstants.OA_RECEIVE_OBJ_AMOUNT_ZERO);
+            }
+        }
+
+        Task currentTask = taskService.createTaskQuery().processInstanceId(oaReceiveNew.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);
+            // 保存审批人信息
+            oaReceiveNew.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);
+
+        Task nextTask = taskService.createTaskQuery().processInstanceId(currentTask.getProcessInstanceId()).singleResult();
+        Long currentAuditEmployeeId = Long.valueOf(nextTask.getAssignee());
+        AdminUserRespDTO currentAuditEmployee = adminUserApi.getUser(currentAuditEmployeeId);
+        oaReceiveNew.setAuditStatus(DictDataConstants.OA_AUDIT_STATUS_COMMITTED)
+                .setCurrentAuditEmployeeId(currentAuditEmployeeId)
+                .setCurrentAuditEmployeeName(currentAuditEmployee.getNickname())
+                .setFinalAuditDate(LocalDateTime.now());
+        oaReceiveMapper.updateById(oaReceiveNew);
+
+        // 保存子表信息
+        if (CollectionUtil.isNotEmpty(oaReceiveObjs)) {
+            updateOaReceiveObjList(oaReceiveNew.getId(), oaReceiveObjs);
+        }
+
+        // 保存业务uuid到附件中
+        saveFileList(reCommitReqVO.getFileIdList(), oaReceiveNew.getReceiveUuid());
+
+        return 1L;
+    }
+
+    @Override
+    @Transactional
+    public Long closeOaReceive(Long id) {
+        if (id == null) {
+            throw exception(ErrorCodeConstants.SERVICE_ID_NOT_EXISTS);
+        }
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        OaReceiveDO oaReceiveDO = oaReceiveMapper.selectById(id);
+        if (!DictDataConstants.OA_AUDIT_STATUS_RETURNED.equals(oaReceiveDO.getAuditStatus())
+                && !DictDataConstants.OA_AUDIT_STATUS_RECALLED.equals(oaReceiveDO.getAuditStatus())) {
+            throw exception(ErrorCodeConstants.TASK_CLOSE_NOT_ALLOWED);
+        }
+
+        Task currentTask = taskService.createTaskQuery().processInstanceId(oaReceiveDO.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);
+
+        LambdaUpdateWrapper<OaReceiveDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+        lambdaUpdateWrapper.set(OaReceiveDO::getAuditStatus, DictDataConstants.OA_AUDIT_STATUS_CLOSED)
+                .set(OaReceiveDO::getCurrentAuditEmployeeId, null)
+                .set(OaReceiveDO::getCurrentAuditEmployeeName, null)
+                .set(OaReceiveDO::getFinalAuditDate, LocalDateTime.now())
+                .eq(OaReceiveDO::getId, id);
+        oaReceiveMapper.update(lambdaUpdateWrapper);
+        return 1L;
+    }
+
+    @Override
+    @Transactional
+    public void deleteOaReceive(Long id) {
+        // 校验存在
+        validateOaReceiveDelete(id);
+        // 删除
+        oaReceiveMapper.deleteById(id);
+        // 删除子表数据
+        deleteOaReceiveObjByReceiveId(id);
+    }
+
+    @Override
+    public OaReceiveRespVO getOaReceive(Long id) {
+        // 登录人信息
+        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
+        // TODO DP 根据登录人查询出对应的员工信息
+
+        OaReceiveDO oaReceiveDO = validateOaReceiveExists(id);
+        OaReceiveRespVO oaReceiveRespVO = BeanUtils.toBean(oaReceiveDO, OaReceiveRespVO.class);
+        if (oaReceiveDO.getDeptId() != null) {
+            DeptRespDTO dept = deptApi.getDept(oaReceiveDO.getDeptId());
+            if (dept != null) {
+                oaReceiveRespVO.setDeptName(dept.getName());
+            }
+        }
+        // 子表数据
+        List<OaReceiveObjDO> oaReceiveObjDOS = getOaReceiveObjListByReceiveId(oaReceiveDO.getId());
+        oaReceiveRespVO.setOaReceiveObjs(oaReceiveObjDOS);
+
+        String procInstId = oaReceiveDO.getProcInstId();
+        if (StrUtil.isNotBlank(procInstId)) {
+            Task task = taskService.createTaskQuery()
+                    .processInstanceId(procInstId)
+                    .taskAssignee(String.valueOf(loginUserId))
+                    .singleResult();
+            if (DictDataConstants.OA_AUDIT_STATUS_COMMITTED.equals(oaReceiveDO.getAuditStatus())) {
+                // 如果是已提交,不限制任务处理人是当前登录人,用于直接撤回
+                task = taskService.createTaskQuery()
+                        .processInstanceId(procInstId)
+                        .singleResult();
+            }
+            if (task != null) {
+                oaReceiveRespVO.setTaskId(task.getId());
+            }
+        }
+
+        // 附件列表
+        List<FileDTO> fileList = fileApi.getFileDTOListByBiz(oaReceiveDO.getReceiveUuid());
+        oaReceiveRespVO.setFileList(fileList);
+
+        // 审批记录
+        if (StrUtil.isNotBlank(oaReceiveDO.getProcInstId())) {
+            List<BpmTaskRespVO> auditRecordList = bpmTaskService.getAuditRecordListByProcessInstanceId(oaReceiveDO.getProcInstId());
+            oaReceiveRespVO.setAuditRecordList(auditRecordList);
+        }
+
+        // 审批人
+        String startUserSelectAssignees = oaReceiveDO.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;
+                    }
+                }
+            }
+            oaReceiveRespVO.setAuditUserList(auditUserList);
+        }
+
+        return oaReceiveRespVO;
+    }
+
+    @Override
+    public OaReceiveRespVO getOaReceiveByProcInstId(String procInstId) {
+        OaReceiveDO oaReceiveDO = oaReceiveMapper.selectOne(OaReceiveDO::getProcInstId, procInstId);
+        OaReceiveRespVO oaReceiveRespVO = BeanUtils.toBean(oaReceiveDO, OaReceiveRespVO.class);
+        if (oaReceiveDO.getDeptId() != null) {
+            DeptRespDTO dept = deptApi.getDept(oaReceiveDO.getDeptId());
+            if (dept != null) {
+                oaReceiveRespVO.setDeptName(dept.getName());
+            }
+        }
+
+        // 附件列表
+        List<FileDTO> fileList = fileApi.getFileDTOListByBiz(oaReceiveDO.getReceiveUuid());
+        oaReceiveRespVO.setFileList(fileList);
+
+        // 审批记录
+        if (StrUtil.isNotBlank(oaReceiveDO.getProcInstId())) {
+            List<BpmTaskRespVO> auditRecordList = bpmTaskService.getAuditRecordListByProcessInstanceId(oaReceiveDO.getProcInstId());
+            oaReceiveRespVO.setAuditRecordList(auditRecordList);
+        }
+
+        // 审批人
+        String startUserSelectAssignees = oaReceiveDO.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;
+                    }
+                }
+            }
+            oaReceiveRespVO.setAuditUserList(auditUserList);
+        }
+
+        return oaReceiveRespVO;
+    }
+
+    @Override
+    public PageResult<OaReceiveRespVO> getOaReceivePage(OaReceivePageReqVO pageReqVO) {
+        PageResult<OaReceiveDO> oaReceiveDOPageResult = oaReceiveMapper.selectPage(pageReqVO);
+        PageResult<OaReceiveRespVO> oaReceiveRespVOPageResult = BeanUtils.toBean(oaReceiveDOPageResult, OaReceiveRespVO.class);
+
+        List<OaReceiveRespVO> oaReceiveRespVOList = oaReceiveRespVOPageResult.getList();
+        if (CollectionUtil.isNotEmpty(oaReceiveRespVOList)) {
+            List<Long> employeeIdList = oaReceiveRespVOList.stream().map(OaReceiveRespVO::getCurrentAuditEmployeeId).collect(Collectors.toList());
+            List<AdminUserRespDTO> employeeList = adminUserApi.getUserList(employeeIdList);
+            for (OaReceiveRespVO respVO : oaReceiveRespVOList) {
+                for (AdminUserRespDTO employee : employeeList) {
+                    if (employee.getId() != null && employee.getId().equals(respVO.getCurrentAuditEmployeeId())) {
+                        respVO.setCurrentAuditEmployeeName(employee.getNickname());
+                        break;
+                    }
+                }
+            }
+
+            List<Long> deptIdList = oaReceiveRespVOList.stream().map(OaReceiveRespVO::getDeptId).collect(Collectors.toList());
+            List<DeptRespDTO> deptList = deptApi.getDeptList(deptIdList);
+            for (OaReceiveRespVO respVO : oaReceiveRespVOList) {
+                for (DeptRespDTO dept : deptList) {
+                    if (dept.getId() != null && dept.getId().equals(respVO.getDeptId())) {
+                        respVO.setDeptName(dept.getName());
+                        break;
+                    }
+                }
+            }
+        }
+
+        return oaReceiveRespVOPageResult;
+    }
+
+    @Override
+    public PageResult<OaReceiveRespVO> exportOaReceiveExcel(OaReceivePageReqVO pageReqVO) {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        return getOaReceivePage(pageReqVO);
+    }
+
+    private void validateOaReceiveDelete(Long id) {
+        OaReceiveDO oaReceiveDO = validateOaReceiveExists(id);
+        if (!DictDataConstants.OA_AUDIT_STATUS_STAGING.equals(oaReceiveDO.getAuditStatus())) {
+            throw exception(ErrorCodeConstants.DELETE_FAIL_NOT_STAGING);
+        }
+    }
+
+    private OaReceiveDO validateOaReceiveExists(Long id) {
+        OaReceiveDO oaReceiveDO = oaReceiveMapper.selectById(id);
+        if (oaReceiveDO == null) {
+            throw exception(OA_RECEIVE_NOT_EXISTS);
+        }
+        return oaReceiveDO;
+    }
+
+    /**
+     * 保存业务uuid到附件中
+     */
+    private void saveFileList(List<Long> fileIdList, String serviceId) {
+        if (CollectionUtil.isNotEmpty(fileIdList) && StrUtil.isNotEmpty(serviceId)) {
+            fileApi.updateFileBiz(fileIdList, serviceId);
+        }
+    }
+
+    // @Resource
+    // private OaReceiveMapper oaReceiveMapper;
+    // @Resource
+    // private OaReceiveObjMapper oaReceiveObjMapper;
+    //
+    // @Override
+    // @Transactional(rollbackFor = Exception.class)
+    // public Long createOaReceive(OaReceiveSaveReqVO createReqVO) {
+    //     // 插入
+    //     OaReceiveDO oaReceive = BeanUtils.toBean(createReqVO, OaReceiveDO.class);
+    //     oaReceiveMapper.insert(oaReceive);
+    //
+    //     // 插入子表
+    //     createOaReceiveObjList(oaReceive.getId(), createReqVO.getOaReceiveObjs());
+    //     // 返回
+    //     return oaReceive.getId();
+    // }
+    //
+    // @Override
+    // @Transactional(rollbackFor = Exception.class)
+    // public void updateOaReceive(OaReceiveSaveReqVO updateReqVO) {
+    //     // 校验存在
+    //     validateOaReceiveExists(updateReqVO.getId());
+    //     // 更新
+    //     OaReceiveDO updateObj = BeanUtils.toBean(updateReqVO, OaReceiveDO.class);
+    //     oaReceiveMapper.updateById(updateObj);
+    //
+    //     // 更新子表
+    //     updateOaReceiveObjList(updateReqVO.getId(), updateReqVO.getOaReceiveObjs());
+    // }
+    //
+    // @Override
+    // @Transactional(rollbackFor = Exception.class)
+    // public void deleteOaReceive(Long id) {
+    //     // 校验存在
+    //     validateOaReceiveExists(id);
+    //     // 删除
+    //     oaReceiveMapper.deleteById(id);
+    //
+    //     // 删除子表
+    //     deleteOaReceiveObjByReceiveId(id);
+    // }
+    //
+    // private void validateOaReceiveExists(Long id) {
+    //     if (oaReceiveMapper.selectById(id) == null) {
+    //         throw exception(OA_RECEIVE_NOT_EXISTS);
+    //     }
+    // }
+    //
+    // @Override
+    // public OaReceiveDO getOaReceive(Long id) {
+    //     return oaReceiveMapper.selectById(id);
+    // }
+    //
+    // @Override
+    // public PageResult<OaReceiveDO> getOaReceivePage(OaReceivePageReqVO pageReqVO) {
+    //     return oaReceiveMapper.selectPage(pageReqVO);
+    // }
+    //
+    // ==================== 子表(领用流程信息子表) ====================
+
+    @Override
+    public List<OaReceiveObjDO> getOaReceiveObjListByReceiveId(Long receiveId) {
+        return oaReceiveObjMapper.selectListByReceiveId(receiveId);
+    }
+
+    private void createOaReceiveObjList(Long receiveId, List<OaReceiveObjDO> list) {
+        list.forEach(o -> o.setReceiveId(receiveId));
+        oaReceiveObjMapper.insertBatch(list);
+    }
+
+    private void updateOaReceiveObjList(Long receiveId, List<OaReceiveObjDO> list) {
+        deleteOaReceiveObjByReceiveId(receiveId);
+		list.forEach(o -> o.setId(null).setCreator(null).setCreateTime(null).setUpdater(null).setUpdateTime(null).setDeleted(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新
+        createOaReceiveObjList(receiveId, list);
+    }
+
+    private void deleteOaReceiveObjByReceiveId(Long receiveId) {
+        oaReceiveObjMapper.deleteByReceiveId(receiveId);
+    }
+
+}

+ 3 - 3
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/renew/OaRenewServiceImpl.java

@@ -88,7 +88,7 @@ public class OaRenewServiceImpl implements OaRenewService {
         Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
         AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
         Objects.requireNonNull(loginUser, "登录用户不能为空");
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(stagingReqVO.getEmployeeId());
 
         OaRenewDO oaRenew = BeanUtils.toBean(stagingReqVO, OaRenewDO.class);
@@ -138,7 +138,7 @@ public class OaRenewServiceImpl implements OaRenewService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(commitReqVO.getEmployeeId());
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);
@@ -382,7 +382,7 @@ public class OaRenewServiceImpl implements OaRenewService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(reCommitReqVO.getEmployeeId());
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);

+ 3 - 3
yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/oa/turnover/OaTurnoverServiceImpl.java

@@ -89,7 +89,7 @@ public class OaTurnoverServiceImpl implements OaTurnoverService {
         Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
         AdminUserRespDTO loginUser = adminUserApi.getUser(loginUserId);
         Objects.requireNonNull(loginUser, "登录用户不能为空");
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(stagingReqVO.getEmployeeId());
 
         OaTurnoverDO oaTurnover = BeanUtils.toBean(stagingReqVO, OaTurnoverDO.class);
@@ -138,7 +138,7 @@ public class OaTurnoverServiceImpl implements OaTurnoverService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(commitReqVO.getEmployeeId());
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);
@@ -381,7 +381,7 @@ public class OaTurnoverServiceImpl implements OaTurnoverService {
         if (loginUser == null) {
             throw exception(ErrorCodeConstants.OA_LOGIN_USER_NOT_EXISTS);
         }
-        // 转正人信息
+        // 人信息
         AdminUserRespDTO employee = adminUserApi.getUser(reCommitReqVO.getEmployeeId());
         if (employee == null) {
             throw exception(ErrorCodeConstants.OA_EMPLOYEE_NOT_EXISTS);

+ 12 - 0
yudao-module-bpm/yudao-module-bpm-biz/src/main/resources/mapper/oa/receive/OaReceiveMapper.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.bpm.dal.mysql.oa.receive.OaReceiveMapper">
+
+    <!--
+        一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
+        无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
+        代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
+        文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
+     -->
+
+</mapper>