feat(bpm): 添加 OA 生产开支功能

- 新增生产开支申请创建和审核功能
- 实现生产开支明细管理
- 添加与财务支付系统的集成
-优化与流程引擎的交互逻辑
This commit is contained in:
furongxin 2025-01-24 17:25:39 +08:00
parent 215a6c8028
commit de6b03f726
29 changed files with 1343 additions and 75 deletions

View File

@ -134,6 +134,12 @@
<groupId>cn.iocoder.cloud</groupId>
<artifactId>yudao-spring-boot-starter-protection</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.cloud</groupId>
<artifactId>zn-module-smartfactory-api</artifactId>
<version>2.0.0-jdk8-snapshot</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,65 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesDO;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAExpensesService;
import cn.iocoder.yudao.module.system.api.project.ProjectApi;
import cn.iocoder.yudao.module.system.api.project.dto.ProjectDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jodd.util.StringUtil;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
* OA 生产开支 Controller
*
* @author 符溶馨
*/
@Tag(name = "管理后台 - OA 生产开支")
@RestController
@RequestMapping("/bpm/oa/expenses")
@Validated
public class BpmOAExpensesController {
@Resource
private BpmOAExpensesService expensesService;
@PostMapping("/create")
@Operation(summary = "创建请求申请")
public CommonResult<Long> createExpenses(@Valid @RequestBody BpmOAExpensesCreateReqVO createReqVO) {
return success(expensesService.createExpenses(getLoginUserId(), createReqVO));
}
@GetMapping("/get")
@Operation(summary = "获得生产开支申请")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<BpmOAExpensesRespVO> getExpenses(@RequestParam("id") Long id) {
BpmOAExpensesDO expensesDO = expensesService.getExpenses(id);
BpmOAExpensesRespVO respVO = expensesService.convertExpenses(expensesDO);
return success(respVO);
}
@GetMapping("/getByProcessInstanceId")
@Operation(summary = "获得现金支出申请")
@Parameter(name = "processInstanceId", description = "流程实例编号", required = true, example = "1024")
public CommonResult<BpmOAExpensesRespVO> getExpensesByProcessInstanceId(@RequestParam("processInstanceId") String processInstanceId) {
BpmOAExpensesDO expensesDO = expensesService.getByProcessInstanceId(processInstanceId);
BpmOAExpensesRespVO respVO = expensesService.convertExpenses(expensesDO);
return success(respVO);
}
}

View File

@ -0,0 +1,173 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.loan.BpmOALoanCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.loan.BpmOALoanRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALoanDO;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOALoanService;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.FactoryInfoApi;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.dto.FactoryInfoDTO;
import cn.iocoder.yudao.module.smartfactory.api.staff.StaffApi;
import cn.iocoder.yudao.module.smartfactory.api.staff.dto.StaffDTO;
import cn.iocoder.yudao.module.system.api.bank.BankApi;
import cn.iocoder.yudao.module.system.api.bank.dto.BankRespDTO;
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 io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
* OA 借支申请 Controller
*
* @author 符溶馨
*/
@Tag(name = "管理后台 - OA 借支申请")
@RestController
@RequestMapping("/bpm/oa/loan")
@Validated
public class BpmOALoanController {
@Resource
private BpmOALoanService loanService;
@Resource
private BankApi bankApi;
@Resource
private DeptApi deptApi;
@Resource
private AdminUserApi userApi;
@Resource
private StaffApi staffApi;
@Resource
private FactoryInfoApi factoryInfoApi;
@PostMapping("/create")
@Operation(summary = "创建借支申请")
public CommonResult<Long> createLoan(@Valid @RequestBody BpmOALoanCreateReqVO createReqVO) {
return success(loanService.createLoan(getLoginUserId(), createReqVO));
}
@GetMapping("/get")
@Operation(summary = "获得借支申请")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<BpmOALoanRespVO> getLoan(@RequestParam("id") Long id) {
BpmOALoanDO loan = loanService.getLoan(id);
BpmOALoanRespVO respVO = BeanUtils.toBean(loan, BpmOALoanRespVO.class);
if (respVO != null) {
// 获取银行卡信息
BankRespDTO bankRespDTO = null;
if (loan.getBankId() != null) {
bankRespDTO = bankApi.getBank(loan.getBankId()).getCheckedData();
if (bankRespDTO != null) {
respVO.setBankNo(bankRespDTO.getBankNo());
respVO.setBankName(bankRespDTO.getBankName());
respVO.setPayeeName(bankRespDTO.getNickname());
}
}
// 获取工厂信息
DeptRespDTO dto = deptApi.getDeptByFactoryId(loan.getFactoryId()).getCheckedData();
// 设置工厂名称
respVO.setFactoryName(dto != null ? dto.getName() : null);
// 获取用户信息
StaffDTO staffDTO = staffApi.getStaff(loan.getSfUserId()).getCheckedData();
//设置员工名称
respVO.setSfUserName(staffDTO != null ? staffDTO.getNickName() : null);
}
return success(respVO);
}
@GetMapping("/getByProcessInstanceId")
@Operation(summary = "获得加班申请")
@Parameter(name = "processInstanceId", description = "流程实例编号", required = true, example = "1024")
public CommonResult<BpmOALoanRespVO> getByProcessInstanceId(@RequestParam("processInstanceId") String processInstanceId) {
BpmOALoanDO loan = loanService.getByProcessInstanceId(processInstanceId);
BpmOALoanRespVO respVO = BeanUtils.toBean(loan, BpmOALoanRespVO.class);
if (respVO != null) {
// 获取银行卡信息
BankRespDTO bankRespDTO = null;
if (loan.getBankId() != null) {
bankRespDTO = bankApi.getBank(loan.getBankId()).getCheckedData();
if (bankRespDTO != null) {
respVO.setBankNo(bankRespDTO.getBankNo());
respVO.setBankName(bankRespDTO.getBankName());
respVO.setPayeeName(bankRespDTO.getNickname());
}
}
// 获取工厂信息
DeptRespDTO dto = deptApi.getDeptByFactoryId(loan.getFactoryId()).getCheckedData();
// 设置工厂名称
respVO.setFactoryName(dto != null ? dto.getName() : null);
// 获取用户信息
StaffDTO staffDTO = staffApi.getStaff(loan.getSfUserId()).getCheckedData();
//设置员工名称
respVO.setSfUserName(staffDTO != null ? staffDTO.getNickName() : null);
}
return success(respVO);
}
@GetMapping("/get-list")
@Operation(summary = "获得指定用户的借支申请列表")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<List<BpmOALoanRespVO>> getLoanList(@RequestParam("staffId") Long staffId) {
List<BpmOALoanDO> loanList = loanService.getListByStaffId(staffId);
List<BpmOALoanRespVO> respVOS = BeanUtils.toBean(loanList, BpmOALoanRespVO.class);
if (CollUtil.isNotEmpty(respVOS)) {
// 获取申请人信息
Set<Long> userIds = convertSet(loanList, BpmOALoanDO::getUserId);
Map<Long, AdminUserRespDTO> userMap = userApi.getUserMap(userIds);
// 获取借支人信息
Set<Long> loanUserIds = convertSet(loanList, BpmOALoanDO::getSfUserId);
Map<Long, StaffDTO> loanUserMap = convertMap(staffApi.getStaffList(loanUserIds).getCheckedData(), StaffDTO::getId);
// 获取工厂信息
Set<Long> deptIds = convertSet(loanList, BpmOALoanDO::getFactoryId);
Map<Long, FactoryInfoDTO> factoryMap = factoryInfoApi.getFactoryMap(deptIds);
respVOS.forEach(item -> {
// 设置申请人名称
item.setUserName(userMap.get(item.getUserId()).getNickname());
// 设置借支用户名称
item.setSfUserName(loanUserMap.get(item.getSfUserId()).getNickName());
// 设置借支用户部门名称
item.setFactoryName(factoryMap.get(item.getFactoryId()).getName());
});
}
return success(respVOS);
}
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.cash.Cash;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
* 生产开支 创建 Request VO
*
* @author 符溶馨
*/
@Schema(description = "管理后台 - 生产开支创建 Request VO")
@Data
@EqualsAndHashCode()
@ToString(callSuper = true)
public class BpmOAExpensesCreateReqVO {
@Schema(description = "收款人信息")
private Long bankId;
@Schema(description = "开支明细")
private List<Expenses> expensesItem;
@Schema(description = "报销总金额", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "报销总金额不能为空")
private BigDecimal totalMoney;
@Schema(description = "流程实例编号")
private String processInstanceId;
@Schema(description = "状态-参见 bpm_process_instance_result 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer result;
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
private List<UploadUserFile> fileItems;
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOABaseRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.cash.Cash;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.math.BigDecimal;
import java.util.List;
/**
* @author 符溶馨
*/
@Schema(description = "管理后台 - 生产开支 请求Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BpmOAExpensesRespVO extends BpmOABaseRespVO {
@Schema(description = "收款人信息编号")
private Long bankId;
@Schema(description = "收款人名称")
private String payeeName;
@Schema(description = "银行卡号")
private String bankNo;
@Schema(description = "开户行名称")
private String bankName;
@Schema(description = "开支明细")
private List<Expenses> expensesItem;
@Schema(description = "报销总金额")
private BigDecimal totalMoney;
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
private List<UploadUserFile> fileItems;
}

View File

@ -0,0 +1,44 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDate;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
/**
* 功能描述 现金支出项目明细
*/
@Data
public class Expenses {
@Schema(description = "id")
private Long id;
@Schema(description = "费用类型 | 字典值参照bpm_oa_expenses_type", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "费用类型不能为空")
private Integer type;
@Schema(description = "费用产生部门", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "费用产生部门不能为空")
private Long deptId;
@Schema(description = "费用产生部门名称")
private String deptName;
@Schema(description = "支出金额", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "申请金额不能为空")
private BigDecimal totalMoney;
@Schema(description = "发生日期", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "发生日期不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
private LocalDate applicationDate;
@Schema(description = "费用明细")
private String detail;
}

View File

@ -0,0 +1,47 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.loan;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
/**
* 生产借支 创建 Request VO
*
* @author 符溶馨
*/
@Schema(description = "管理后台 - 生产借支创建 Request VO")
@Data
@EqualsAndHashCode()
@ToString(callSuper = true)
public class BpmOALoanCreateReqVO {
@Schema(description = "收款人信息")
private Long bankId;
@Schema(description = "借支工厂", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "借支工厂不能为空")
private Long factoryId;
@Schema(description = "借支厂区用户", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "借支用户不能为空")
private Long sfUserId;
@Schema(description = "借支金额", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "借支金额不能为空")
private BigDecimal totalMoney;
@Schema(description = "流程实例编号")
private String processInstanceId;
@Schema(description = "状态-参见 bpm_process_instance_result 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer result;
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
private List<UploadUserFile> fileItems;
}

View File

@ -0,0 +1,57 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.loan;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.BpmOABaseRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.math.BigDecimal;
import java.util.List;
/**
* @author 符溶馨
*/
@Schema(description = "管理后台 - 生产开支 请求Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class BpmOALoanRespVO extends BpmOABaseRespVO {
@Schema(description = "申请人用户编号")
private Long userId;
@Schema(description = "申请人名称")
private String userName;
@Schema(description = "收款人信息编号")
private Long bankId;
@Schema(description = "收款人名称")
private String payeeName;
@Schema(description = "银行卡号")
private String bankNo;
@Schema(description = "开户行名称")
private String bankName;
@Schema(description = "借支工厂")
private Long factoryId;
@Schema(description = "借支工厂名称")
private String factoryName;
@Schema(description = "借支用户")
private Long sfUserId;
@Schema(description = "借支用户名称")
private String sfUserName;
@Schema(description = "借支金额")
private BigDecimal totalMoney;
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
private List<UploadUserFile> fileItems;
}

View File

@ -0,0 +1,66 @@
package cn.iocoder.yudao.module.bpm.convert.oa;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.Expenses;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesItemDO;
import cn.iocoder.yudao.module.system.api.bank.dto.BankRespDTO;
import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
/**
* 生产开支 Convert
*
* @author 符溶馨
*/
@Mapper
public interface BpmOAExpensesConvert {
BpmOAExpensesConvert INSTANCE = Mappers.getMapper(BpmOAExpensesConvert.class);
BpmOAExpensesDO convert(BpmOAExpensesCreateReqVO bean);
BpmOAExpensesRespVO convert(BpmOAExpensesDO bean);
default BpmOAExpensesRespVO convert1(BpmOAExpensesDO expensesDO, List<BpmOAExpensesItemDO> expensesItemDOs,
Map<Long, DeptRespDTO> deptMap, BankRespDTO bankRespDTO) {
BpmOAExpensesRespVO respVO = BeanUtils.toBean(expensesDO, BpmOAExpensesRespVO.class);
List<Expenses> expensesItems = BeanUtils.toBean(expensesItemDOs, Expenses.class);
if (deptMap != null) {
expensesItems = convertList(expensesItems, deptMap);
}
if (bankRespDTO != null) {
respVO.setBankNo(bankRespDTO.getBankNo());
respVO.setBankName(bankRespDTO.getBankName());
respVO.setPayeeName(bankRespDTO.getNickname());
}
respVO.setExpensesItem(expensesItems);
return respVO;
}
default List<Expenses> convertList(List<Expenses> list, Map<Long, DeptRespDTO> deptMap) {
return CollectionUtils.convertList(list, expenses -> convert(expenses, deptMap.get(expenses.getDeptId())));
}
default Expenses convert(Expenses expensesItem, DeptRespDTO dept) {
if (dept != null) {
expensesItem.setDeptName(dept.getName());
}
return expensesItem;
}
}

View File

@ -55,7 +55,7 @@ public class FinancialPaymentDO extends BaseDO {
*/
private String reason;
/**
* 流程类型 1现金支出 2备用金 3采购付款 4报销 5供应商采购付款
* 流程类型 1现金支出 2备用金 3采购付款 4报销 5供应商采购付款 6开支日报
*/
private Integer type;
/**

View File

@ -0,0 +1,70 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
import java.math.BigDecimal;
import java.util.List;
/**
* OA 生产开支 DO
*
* @author 符溶馨
*/
@TableName(value ="bpm_oa_expenses", autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BpmOAExpensesDO extends BaseDO {
/**
* 出差表单主键
*/
@TableId
private Long id;
/**
* 申请人的用户编号
* 关联 AdminUserDO id 属性
*/
private Long userId;
/**
* 收款人信息
* system_bank 编号
*/
private Long bankId;
/**
* 支出总金额
*/
private BigDecimal totalMoney;
/**
* 申请结果
* 枚举 {@link BpmProcessInstanceResultEnum}
* 考虑到简单所以直接复用了 BpmProcessInstanceResultEnum 枚举也可以自己定义一个枚举哈
*/
private Integer result;
/**
* 对应的流程编号
* 关联 ProcessInstance id 属性
*/
private String processInstanceId;
/**
* 附件基本信息
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<UploadUserFile> fileItems;
}

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* OA 生产开支明细 DO
*
* @author 符溶馨
*/
@TableName(value ="bpm_oa_expenses_item", autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BpmOAExpensesItemDO extends BaseDO {
/**
* 表单主键
*/
@TableId
private Long id;
/**
* 生产开支业务编号
*/
private Long expensesId;
/**
* 费用类型 字典值参照 BPM_OA_EXPENSES_TYPE
*/
private Integer type;
/**
* 费用产生部门
*/
private Long deptId;
/**
* 金额
*/
private BigDecimal totalMoney;
/**
* 申请日期
*/
private LocalDate applicationDate;
/**
* 费用明细
*/
private String detail;
}

View File

@ -0,0 +1,80 @@
package cn.iocoder.yudao.module.bpm.dal.dataobject.oa;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import lombok.*;
import java.math.BigDecimal;
import java.util.List;
/**
* OA 生产开支 DO
*
* @author 符溶馨
*/
@TableName(value ="bpm_oa_loan", autoResultMap = true)
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BpmOALoanDO extends BaseDO {
/**
* 出差表单主键
*/
@TableId
private Long id;
/**
* 申请人的用户编号
* 关联 AdminUserDO id 属性
*/
private Long userId;
/**
* 收款人信息
* system_bank 编号
*/
private Long bankId;
/**
* 借支工厂
*/
private Long factoryId;
/**
* 借支用户编号
*/
private Long sfUserId;
/**
* 借出金额
*/
private BigDecimal totalMoney;
/**
* 申请结果
* 枚举 {@link BpmProcessInstanceResultEnum}
* 考虑到简单所以直接复用了 BpmProcessInstanceResultEnum 枚举也可以自己定义一个枚举哈
*/
private Integer result;
/**
* 对应的流程编号
* 关联 ProcessInstance id 属性
*/
private String processInstanceId;
/**
* 附件基本信息
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<UploadUserFile> fileItems;
}

View File

@ -24,6 +24,6 @@ public interface BpmOAEvectionMapper extends BaseMapperX<BpmOAEvectionDO> {
.eq(BpmOAEvectionDO::getUserId, userId)
.leIfPresent(BpmOAEvectionDO::getStartTime, createReqVO.getEndTime())
.geIfPresent(BpmOAEvectionDO::getEndTime, createReqVO.getStartTime())
.in(BpmOAEvectionDO::getResult, Arrays.asList(BpmProcessInstanceResultEnum.PROCESS, BpmProcessInstanceResultEnum.APPROVE)));
.in(BpmOAEvectionDO::getResult, Arrays.asList(BpmProcessInstanceResultEnum.PROCESS.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())));
}
}

View File

@ -0,0 +1,9 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.oa;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesItemDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BpmOAExpensesItemMapper extends BaseMapperX<BpmOAExpensesItemDO> {
}

View File

@ -0,0 +1,9 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.oa;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BpmOAExpensesMapper extends BaseMapperX<BpmOAExpensesDO> {
}

View File

@ -0,0 +1,9 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.oa;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALoanDO;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface BpmOALoanMapper extends BaseMapperX<BpmOALoanDO> {
}

View File

@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.product.api.storeproduct.StoreProductApi;
import cn.iocoder.yudao.module.product.api.storeproductattrvalue.StoreProductAttrValueApi;
import cn.iocoder.yudao.module.smartfactory.api.factoryInfo.FactoryInfoApi;
import cn.iocoder.yudao.module.smartfactory.api.staff.StaffApi;
import cn.iocoder.yudao.module.system.api.assetreceive.AssetReceiveApi;
import cn.iocoder.yudao.module.system.api.assets.AssetsApi;
import cn.iocoder.yudao.module.system.api.assets.AssetsTypeApi;
@ -19,6 +21,7 @@ import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.equipment.UsersExtApi;
import cn.iocoder.yudao.module.system.api.group.AttendanceGroupApi;
import cn.iocoder.yudao.module.system.api.holiday.HolidayApi;
import cn.iocoder.yudao.module.system.api.loan.LoanApi;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.system.api.permission.RoleApi;
import cn.iocoder.yudao.module.system.api.position.PositionApi;
@ -40,7 +43,7 @@ import org.springframework.context.annotation.Configuration;
SubscribeMessageSendApi.class, SocialClientApi.class, UsersExtApi.class, AttendanceApi.class, BankApi.class, ConfigApi.class, PositionApi.class, SupplierApi.class, AssetsApi.class,
AssetsTypeApi.class, AssetReceiveApi.class, AttendanceApi.class, AttendanceGroupApi.class, WorkOvertimeApi.class, HolidayApi.class,
RentalOrderApi.class, RentalDepositRecordApi.class, ProjectApi.class, RentalItemsRecordApi.class,AdminOauthUserOtherInfoApi.class, StoreProductAttrValueApi.class, StoreProductApi.class,
ContractApi.class, BusinessApi.class, CrmCustomerApi.class
ContractApi.class, BusinessApi.class, CrmCustomerApi.class, StaffApi.class, LoanApi.class, FactoryInfoApi.class
})
public class RpcConfiguration {
}

View File

@ -44,7 +44,7 @@ public class WorkOvertimeJob {
LocalDateTime now = LocalDateTime.now();
List<BpmOAOvertimeDO> bpmOAOvertimeDOS = overtimeMapper.selectList(new LambdaQueryWrapper<BpmOAOvertimeDO>()
.eq(BpmOAOvertimeDO::getSettlementFlag, 0)
.eq(BpmOAOvertimeDO::getResult, BpmProcessInstanceResultEnum.APPROVE)
.eq(BpmOAOvertimeDO::getResult, BpmProcessInstanceResultEnum.APPROVE.getResult())
.ge(BpmOAOvertimeDO::getEndTime, now));
if (CollectionUtil.isNotEmpty(bpmOAOvertimeDOS)) {
List<Long> ids = bpmOAOvertimeDOS.stream().map(BpmOAOvertimeDO::getId).collect(Collectors.toList());

View File

@ -257,7 +257,7 @@ public class BpmOACashServiceImpl extends BpmOABaseService implements BpmOACashS
Long count = cashMapper.selectCount(new LambdaQueryWrapperX<BpmOACashDO>()
.eq(BpmOACashDO::getImprestId, cash.getImprestId())
.eq(BpmOACashDO::getResult, BpmProcessInstanceResultEnum.APPROVE));
.eq(BpmOACashDO::getResult, BpmProcessInstanceResultEnum.APPROVE.getResult()));
if (count > 0L) {
//将相应备用金申请状态改为 未报销
bpmOAImprestMapper.updateById(new BpmOAImprestDO().setId(cash.getImprestId()).setStatus(BpmOAImprestDO.NOT_COMPLETED));

View File

@ -1,9 +1,5 @@
package cn.iocoder.yudao.module.bpm.service.oa;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.string.DTO.IdCardDO;
import cn.iocoder.yudao.framework.common.util.string.StrUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
@ -13,28 +9,19 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAEntryDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAEntryMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.infra.api.file.dto.UserFileUpdateReqDTO;
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.UserSaveRespDTO;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_ENTRY_NOT_EXISTS;
@ -58,16 +45,6 @@ public class BpmOAEntryServiceImpl implements BpmOAEntryService {
@Resource
private BpmProcessInstanceApi processInstanceApi;
@Resource
@Lazy
private BpmProcessInstanceService bpmProcessInstanceService;
@Resource
private AdminUserApi userApi;
@Resource
private FileApi fileApi;
@Resource
private BpmHistoryProcessInstanceService historyProcessInstanceService;
@ -111,57 +88,20 @@ public class BpmOAEntryServiceImpl implements BpmOAEntryService {
@Transactional(rollbackFor = Exception.class)
public void updateEntryResult(String processInstanceId, Long id, Integer result) {
BpmOAEntryDO entry = validateLeaveExists(id);
validateLeaveExists(id);
BpmOAEntryDO updateVO = new BpmOAEntryDO().setId(id).setResult(result);
//审核通过 最后节点
if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
ProcessInstance instance = bpmProcessInstanceService.getProcessInstance(processInstanceId);
if (instance.isEnded()) {
// 新增入职申请中的用户信息
UserSaveRespDTO saveRespDTO = BeanUtils.toBean(entry, UserSaveRespDTO.class);
saveRespDTO.setId(null);
saveRespDTO.setDeptId(entry.getEntryDeptId());
saveRespDTO.setPositionId(entry.getEntryPositionId());
saveRespDTO.setPostIds(Collections.singleton(entry.getEntryPostId()));
saveRespDTO.setPassword("123456");
saveRespDTO.setStatus(1); // 默认设置关闭
// 解析身份证号码
IdCardDO idCardDO = StrUtils.IdCardAnalysis(saveRespDTO.getIdcard());
// 设置性别年龄生日
saveRespDTO.setSex(idCardDO.getSex());
saveRespDTO.setAge(idCardDO.getAge());
saveRespDTO.setBirthdayDay(idCardDO.getDate());
// 插入用户 获得用户编号
Long userId = userApi.createUser(saveRespDTO).getCheckedData();
updateVO.setEntryUserId(userId);
// 同步修改用户文件数据
List<UploadUserFile> uploadUserFiles = BeanUtils.toBean(entry.getFileItems(), UploadUserFile.class);
UserFileUpdateReqDTO updateReqDTO = new UserFileUpdateReqDTO()
.setUrls(convertList(uploadUserFiles, UploadUserFile::getUrl))
.setUserId(userId);
fileApi.updateUserFileUserId(updateReqDTO);
}
}
// 更新入职申请状态
entryMapper.updateById(updateVO);
}
private BpmOAEntryDO validateLeaveExists(Long id) {
private void validateLeaveExists(Long id) {
BpmOAEntryDO entry = entryMapper.selectById(id);
if (entry == null) {
throw exception(OA_ENTRY_NOT_EXISTS);
}
return entry;
}
@Override

View File

@ -89,7 +89,7 @@ public class BpmOAEvectionServiceImpl extends BpmOABaseService implements BpmOAE
// 发起出差申请后判断是否是当天的出差
if (evection.getStartTime().toLocalDate().isEqual(LocalDate.now())) {
// 设置外勤打卡权限
Set<Long> userIds = evection.getTogetherUserIds();
Set<Long> userIds = evection.getTogetherUserIds() == null ? new HashSet<>() : evection.getTogetherUserIds();
userIds.add(userId);
userApi.updateFieldworkType(userIds, 1);
}

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.bpm.service.oa;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesItemDO;
import javax.validation.Valid;
import java.util.List;
public interface BpmOAExpensesService {
/**
* 创建生产开支申请
*
* @param userId 用户编号
* @param createReqVO 创建信息
* @return 编号
*/
Long createExpenses(Long userId, @Valid BpmOAExpensesCreateReqVO createReqVO);
/**
* 更新生产开支申请的状态
*
* @param id 编号
* @param result 结果
*/
void updateExpensesResult(String processInstanceId, Long id, Integer result);
/**
* 获得生产开支申请
*
* @param id 编号
* @return 现金支出申请
*/
BpmOAExpensesDO getExpenses(Long id);
/**
* 获得指定得生产开支明细
*
* @param expensesId 生产开支 编号
* @return 明细
*/
List<BpmOAExpensesItemDO> getExpensesItem(Long expensesId);
/**
* 通过流程实例id获取
*
* @param processInstanceId 流程实例编号
* @return 生产开支对象
*/
BpmOAExpensesDO getByProcessInstanceId(String processInstanceId);
/**
* 转换生产开支详情 用于前端返回值
* @param expenses 开支对象
* @return 开支对象
*/
BpmOAExpensesRespVO convertExpenses(BpmOAExpensesDO expenses);
}

View File

@ -0,0 +1,221 @@
package cn.iocoder.yudao.module.bpm.service.oa;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
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.vo.expenses.BpmOAExpensesCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.expenses.BpmOAExpensesRespVO;
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAExpensesConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAExpensesItemDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAExpensesItemMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAExpensesMapper;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAImprestMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.financialpayment.FinancialPaymentService;
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.system.api.bank.BankApi;
import cn.iocoder.yudao.module.system.api.bank.dto.BankRespDTO;
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 org.flowable.engine.runtime.ProcessInstance;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_EXPENSES_NOT_EXISTS;
/**
* OA 生产开支 Service 实现类
*
* @author 符溶馨
*/
@Service
@Validated
public class BpmOAExpensesServiceImpl extends BpmOABaseService implements BpmOAExpensesService {
/**
* OA 生产开支对应的流程定义 KEY
*/
public static final String PROCESS_KEY = "oa_expenses_2";
@Resource
private BpmOAExpensesMapper expensesMapper;
@Resource
private BpmOAExpensesItemMapper expensesItemMapper;
@Resource
private BpmProcessInstanceApi processInstanceApi;
@Resource
@Lazy // 解决循环依赖
private BpmProcessInstanceService bpmProcessInstanceService;
@Resource
private FinancialPaymentService financialPaymentService;
@Resource
private DeptApi deptApi;
@Resource
private BankApi bankApi;
@Resource
private AdminUserApi userApi;
@Resource
@Lazy // 解决循环依赖
private BpmHistoryProcessInstanceService historyProcessInstanceService;
@Override
public Long createExpenses(Long userId, BpmOAExpensesCreateReqVO createReqVO) {
//插入OA 生产开支申请
BpmOAExpensesDO expenses = BpmOAExpensesConvert.INSTANCE.convert(createReqVO)
.setUserId(userId)
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
expensesMapper.insert(expenses);
// 批量插入生产开支明细数据
List<BpmOAExpensesItemDO> bpmOAExpensesItemDOS = BeanUtils.toBean(createReqVO.getExpensesItem(), BpmOAExpensesItemDO.class);
bpmOAExpensesItemDOS.forEach(item -> item.setExpensesId(expenses.getId()));
expensesItemMapper.insertBatch(bpmOAExpensesItemDOS);
// 发起 BPM 流程
Map<String, Object> processInstanceVariables = new HashMap<>();
String processInstanceId = processInstanceApi.createProcessInstance(userId,
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(expenses.getId()))).getCheckedData();
// 将工作流的编号更新到 OA 生产开支单中
expensesMapper.updateById(new BpmOAExpensesDO().setId(expenses.getId()).setProcessInstanceId(processInstanceId));
// 判断是否为重新发起的流程
if (createReqVO.getProcessInstanceId() != null && createReqVO.getResult() == 3) {
historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId());
}
List<UploadUserFile> fileItems = createReqVO.getFileItems();
//这里的逻辑如果fileItems不为空且有数据那么说明是上传了附件的则需要更工作流文件表对应的实例Id
if (fileItems != null && !fileItems.isEmpty()) {
uploadBpmFileProcessInstanceId(processInstanceId, fileItems);
}
return expenses.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
public void updateExpensesResult(String processInstanceId, Long id, Integer result) {
// 获得现金支出业务数据
BpmOAExpensesDO expenses = validateLeaveExists(id);
expensesMapper.updateById(new BpmOAExpensesDO().setId(id).setResult(result));
// 获取现金支出明细
List<BpmOAExpensesItemDO> expensesItemDOs = getExpensesItem(id);
List<Long> procureIds = new ArrayList<>();
//审核通过 最后节点
if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
ProcessInstance instance = bpmProcessInstanceService.getProcessInstance(processInstanceId);
if (instance.isEnded()) {
String reason = expensesItemDOs.stream()
.map(BpmOAExpensesItemDO::getDetail)
.filter(StrUtil::isNotEmpty)
.collect(Collectors.joining(","));
BpmProcessInstanceExtDO processInstance = bpmProcessInstanceService.getProcessInstanceDO(processInstanceId);
CommonResult<AdminUserRespDTO> user = userApi.getUser(expenses.getUserId());
// -- 插入到财务支付表中
financialPaymentService.save(new FinancialPaymentDO()
.setUserId(expenses.getUserId())
.setDeptId(user.getData() == null ? null : user.getData().getDeptId())
.setProcessInstanceId(expenses.getProcessInstanceId())
.setProcessInstanceName(processInstance.getName())
.setReason(reason)
.setObjectId(id)
.setType(6)
.setStatus(0)
.setAmountPayable(expenses.getTotalMoney())
.setBeginTime(processInstance.getCreateTime())
.setEndTime(processInstance.getEndTime())
);
}
}
}
private BpmOAExpensesDO validateLeaveExists(Long id) {
BpmOAExpensesDO expenses = expensesMapper.selectById(id);
if (expenses == null) {
throw exception(OA_EXPENSES_NOT_EXISTS);
}
return expenses;
}
@Override
public BpmOAExpensesDO getExpenses(Long id) {
return expensesMapper.selectById(id);
}
@Override
public List<BpmOAExpensesItemDO> getExpensesItem(Long expensesId) {
return expensesItemMapper.selectList(BpmOAExpensesItemDO::getExpensesId, expensesId);
}
@Override
public BpmOAExpensesDO getByProcessInstanceId(String processInstanceId) {
List<BpmOAExpensesDO> list = expensesMapper.selectList(
new LambdaQueryWrapper<BpmOAExpensesDO>()
.eq(BpmOAExpensesDO::getProcessInstanceId, processInstanceId));
if (!list.isEmpty()) {
return list.get(0);
}
return null;
}
@Override
public BpmOAExpensesRespVO convertExpenses(BpmOAExpensesDO expenses) {
// 获取明细数据
List<BpmOAExpensesItemDO> expensesItemDOs = getExpensesItem(expenses.getId());
//获取部门信息map
Map<Long, DeptRespDTO> deptMap = deptApi.getDeptMap(convertSet(expensesItemDOs, BpmOAExpensesItemDO::getDeptId));
// 获取银行卡信息
BankRespDTO bankRespDTO = null;
if (expenses.getBankId() != null) {
bankRespDTO = bankApi.getBank(expenses.getBankId()).getCheckedData();
}
return BpmOAExpensesConvert.INSTANCE.convert1(expenses, expensesItemDOs, deptMap, bankRespDTO);
}
}

View File

@ -0,0 +1,56 @@
package cn.iocoder.yudao.module.bpm.service.oa;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.loan.BpmOALoanCreateReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALoanDO;
import javax.validation.Valid;
import java.util.List;
/**
* 生产借支 Service 接口
*
* @author 符溶馨
*/
public interface BpmOALoanService {
/**
* 创建借支申请
*
* @param userId 用户编号
* @param createReqVO 创建信息
* @return 编号
*/
Long createLoan(Long userId, @Valid BpmOALoanCreateReqVO createReqVO);
/**
* 更新借支申请的状态
*
* @param processInstanceId 流程实例编号
* @param id id
* @param result 结果
*/
void updateLoanResult(String processInstanceId, Long id, Integer result);
/**
* 获得借支申请
*
* @param id 编号
* @return 加班申请
*/
BpmOALoanDO getLoan(Long id);
/**
* 获得指定的借支申请
*
* @param processInstanceId 流程实例编号
* @return 借支申请
*/
BpmOALoanDO getByProcessInstanceId(String processInstanceId);
/**
* 获得指定用户的借支列表
* @param staffId 员工编号
* @return 借支列表
*/
List<BpmOALoanDO> getListByStaffId(Long staffId);
}

View File

@ -0,0 +1,140 @@
package cn.iocoder.yudao.module.bpm.service.oa;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
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.vo.loan.BpmOALoanCreateReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOALoanDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOALoanMapper;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.service.task.BpmHistoryProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.system.api.loan.LoanApi;
import cn.iocoder.yudao.module.system.api.loan.dto.LoanDTO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_LOAN_NOT_EXISTS;
/**
* OA 加班申请 Service 实现类
*
* @author 符溶馨
*/
@Service
@Validated
public class BpmOALoanServiceImpl extends BpmOABaseService implements BpmOALoanService {
/**
* OA 加班对应的流程定义 KEY
*/
public static final String PROCESS_KEY = "oa_loan_2";
@Resource
private BpmOALoanMapper loanMapper;
@Resource
private BpmProcessInstanceService processInstanceService;
@Resource
private BpmHistoryProcessInstanceService historyProcessInstanceService;
@Resource
private LoanApi loanApi;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createLoan(Long userId, BpmOALoanCreateReqVO vo) {
//插入OA 借支申请
BpmOALoanDO loan = BeanUtils.toBean(vo, BpmOALoanDO.class)
.setUserId(userId)
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
loanMapper.insert(loan);
// 发起 BPM 流程
Map<String, Object> processInstanceVariables = new HashMap<>();
String processInstanceId = processInstanceService.createProcessInstance(userId,
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(loan.getId())));
// 将工作流的编号更新到 OA 借支申请单中
loanMapper.updateById(new BpmOALoanDO().setId(loan.getId()).setProcessInstanceId(processInstanceId));
// 判断是否为重新发起的流程
if (vo.getProcessInstanceId() != null && vo.getResult() == 3) {
historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, vo.getProcessInstanceId());
}
List<UploadUserFile> fileItems = vo.getFileItems();
//这里的逻辑如果fileItems不为空且有数据那么说明是上传了附件的则需要更工作流文件表对应的实例Id
if (fileItems != null && !fileItems.isEmpty()) {
uploadBpmFileProcessInstanceId(processInstanceId, fileItems);
}
return loan.getId();
}
@Override
public void updateLoanResult(String processInstanceId, Long id, Integer result) {
BpmOALoanDO loanDO = validateLeaveExists(id);
loanMapper.updateById(new BpmOALoanDO().setId(id).setResult(result));
//审核通过 最后节点
if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
ProcessInstance instance = processInstanceService.getProcessInstance(processInstanceId);
if (instance.isEnded()) {
// 同步插入借支表中
LoanDTO createDO = new LoanDTO()
.setAmount(loanDO.getTotalMoney())
.setReturnAmount(BigDecimal.ZERO);
loanApi.createLoan(createDO);
}
}
}
private BpmOALoanDO validateLeaveExists(Long id) {
BpmOALoanDO loanDO = loanMapper.selectById(id);
if (loanDO == null) {
throw exception(OA_LOAN_NOT_EXISTS);
}
return loanDO;
}
@Override
public BpmOALoanDO getLoan(Long id) {
return loanMapper.selectById(id);
}
@Override
public BpmOALoanDO getByProcessInstanceId(String processInstanceId) {
List<BpmOALoanDO> bpmOALoanDOS = loanMapper.selectList(BpmOALoanDO::getProcessInstanceId, processInstanceId);
if (!CollectionUtil.isEmpty(bpmOALoanDOS)) {
return bpmOALoanDOS.get(0);
}
return null;
}
@Override
public List<BpmOALoanDO> getListByStaffId(Long staffId) {
return loanMapper.selectList(new LambdaQueryWrapperX<BpmOALoanDO>()
.eq(BpmOALoanDO::getSfUserId, staffId)
.eq(BpmOALoanDO::getResult, BpmProcessInstanceResultEnum.APPROVE.getResult()));
}
}

View File

@ -103,6 +103,15 @@ public class BpmOAReimbursementServiceImpl extends BpmOABaseService implements B
public Long createReimbursement(Long userId, BpmOAReimbursementCreateReqVO createReqVO) {
BpmOAReimbursementDO reimbursement = BpmOAReimbursementConvert.INSTANCE.convert(createReqVO).setUserId(userId)
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
// 如果是备用金报销则更新备用金流程status
if (createReqVO.getImprestId() != null) {
bpmOAImprestMapper.updateById(new BpmOAImprestDO().setId(createReqVO.getImprestId()).setStatus(BpmOAImprestDO.IN_PROGRESS));
}else {
// 清空差额字段
reimbursement.setDifference(BigDecimal.ZERO);
}
// 插入 OA 报销表单
reimbursementMapper.insert(reimbursement);
// 同步插入明细数据
@ -125,12 +134,6 @@ public class BpmOAReimbursementServiceImpl extends BpmOABaseService implements B
historyProcessInstanceService.createHistoryProcessInstance(processInstanceId, createReqVO.getProcessInstanceId());
}
//如果是备用金报销则更新备用金流程status,并存入当前报销流程ID
if (createReqVO.getImprestId() != null) {
bpmOAImprestMapper.updateById(new BpmOAImprestDO().setId(createReqVO.getImprestId()).setStatus(BpmOAImprestDO.IN_PROGRESS));
}
//判断是否有 采购报销
List<Long> procureIds = new ArrayList<>();
for (BpmOAReimbursementItemDO data : createDO) {
@ -262,7 +265,7 @@ public class BpmOAReimbursementServiceImpl extends BpmOABaseService implements B
Long count = reimbursementMapper.selectCount(new LambdaQueryWrapperX<BpmOAReimbursementDO>()
.eq(BpmOAReimbursementDO::getImprestId, bpmOAReimbursementDO.getImprestId())
.eq(BpmOAReimbursementDO::getResult, BpmProcessInstanceResultEnum.APPROVE));
.eq(BpmOAReimbursementDO::getResult, BpmProcessInstanceResultEnum.APPROVE.getResult()));
if (count > 0L) {
//将相应备用金申请状态改为 未报销
bpmOAImprestMapper.updateById(new BpmOAImprestDO().setId(bpmOAReimbursementDO.getImprestId()).setStatus(BpmOAImprestDO.NOT_COMPLETED));

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.bpm.service.oa.listener;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventListener;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAExpensesService;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAExpensesServiceImpl;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* OA 生产开支的结果的监听器实现类
*
* @author 符溶馨
*/
@Component
public class BpmOAExpensesResultListener extends BpmProcessInstanceResultEventListener {
@Resource
private BpmOAExpensesService expensesService;
@Override
protected String getProcessDefinitionKey() {
return BpmOAExpensesServiceImpl.PROCESS_KEY;
}
@Override
protected void onEvent(BpmProcessInstanceResultEvent event) {
expensesService.updateExpensesResult(event.getId(), Long.parseLong(event.getBusinessKey()), event.getResult());
}
}

View File

@ -0,0 +1,32 @@
package cn.iocoder.yudao.module.bpm.service.oa.listener;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent;
import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEventListener;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOALoanService;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOALoanServiceImpl;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* OA 借支申请单的结果的监听器实现类
*
* @author 符溶馨
*/
@Component
public class BpmOALoanResultListener extends BpmProcessInstanceResultEventListener {
@Resource
private BpmOALoanService loanService;
@Override
protected String getProcessDefinitionKey() {
return BpmOALoanServiceImpl.PROCESS_KEY;
}
@Override
protected void onEvent(BpmProcessInstanceResultEvent event) {
loanService.updateLoanResult(event.getId(), Long.parseLong(event.getBusinessKey()),
event.getResult());
}
}