feat(bpm): 添加薪资付款功能并优化流程实例页面

- 新增薪资付款相关的实体类、控制器和服务
- 在流程实例页面添加支付状态字段
- 优化付款申请和报销流程,支持工厂明细数据
- 集成财务支付模块,实现支付信息的创建和查询
This commit is contained in:
furongxin 2024-12-24 22:57:27 +08:00
parent 15a5044334
commit 493e735a0c
17 changed files with 232 additions and 21 deletions

View File

@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.imprest.BpmOAImprestRe
import cn.iocoder.yudao.module.bpm.convert.oa.BpmOAImprestConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAImprestDO;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAImprestService;
import cn.iocoder.yudao.module.system.api.bank.BankApi;
import cn.iocoder.yudao.module.system.api.bank.dto.BankRespDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -33,6 +35,9 @@ public class BpmOAImprestController {
@Resource
private BpmOAImprestService imprestService;
@Resource
private BankApi bankApi;
@PostMapping("/create")
@Operation(summary = "创建请求申请")
public CommonResult<Long> createImprest(@Valid @RequestBody BpmOAImprestCreateReqVO createReqVO) {
@ -46,8 +51,18 @@ public class BpmOAImprestController {
public CommonResult<BpmOAImprestRespVO> getImprest(@RequestParam("id") Long id) {
BpmOAImprestDO imprest = imprestService.getImprest(id);
BpmOAImprestRespVO respVO = BpmOAImprestConvert.INSTANCE.convert(imprest);
if (respVO != null) {
// 获取收款账号信息
BankRespDTO bankRespDTO = bankApi.getBank(imprest.getBankId()).getCheckedData();
if (bankRespDTO != null) {
respVO.setBankName(bankRespDTO.getBankName());
respVO.setNickname(bankRespDTO.getNickname());
respVO.setBankNo(bankRespDTO.getBankNo());
}
}
return success(BpmOAImprestConvert.INSTANCE.convert(imprest));
return success(respVO);
}
@GetMapping("/getOne")
@ -75,7 +90,17 @@ public class BpmOAImprestController {
public CommonResult<BpmOAImprestRespVO> getByProcessInstanceId(@RequestParam("processInstanceId") String processInstanceId) {
BpmOAImprestDO imprest = imprestService.getByProcessInstanceId(processInstanceId);
BpmOAImprestRespVO respVO = BpmOAImprestConvert.INSTANCE.convert(imprest);
if (respVO != null) {
// 获取收款账号信息
BankRespDTO bankRespDTO = bankApi.getBank(imprest.getBankId()).getCheckedData();
if (bankRespDTO != null) {
respVO.setBankName(bankRespDTO.getBankName());
respVO.setNickname(bankRespDTO.getNickname());
respVO.setBankNo(bankRespDTO.getBankNo());
}
}
return success(BpmOAImprestConvert.INSTANCE.convert(imprest));
return success(respVO);
}
}

View File

@ -1,9 +1,11 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa;
import cn.hutool.core.collection.CollectionUtil;
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.payment.BpmOAPaymentCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.FactoryDetailVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAPaymentDO;
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAPaymentService;
import cn.iocoder.yudao.module.system.api.bank.BankApi;
@ -15,17 +17,16 @@ 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 org.apache.logging.log4j.util.Strings;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
@ -67,16 +68,27 @@ public class BpmOAPaymentController {
BpmOAPaymentDO payment = paymentService.getPayment(id);
BpmOAPaymentRespVO respVO = BeanUtils.toBean(payment, BpmOAPaymentRespVO.class);
if (respVO != null) {
// 获取部门信息Map
List<Long> deptIds = Arrays.asList(payment.getDeptId(), payment.getPaymentCompany());
List<Long> deptIds = new ArrayList<>();
if (CollectionUtil.isNotEmpty(respVO.getFactoryDetail())) {
deptIds.addAll(convertList(respVO.getFactoryDetail(), FactoryDetailVO::getDeptId));
}else {
deptIds.add(payment.getDeptId());
}
deptIds.add(payment.getPaymentCompany());
Map<Long, DeptRespDTO> dtoMap = deptApi.getDeptMap(new HashSet<>(deptIds));
// 设置部门名称
respVO.setDeptName(dtoMap.get(payment.getDeptId()).getName());
respVO.setDeptName(dtoMap.get(payment.getDeptId()) != null ? dtoMap.get(payment.getDeptId()).getName() : null);
// 设置付款公司名称
respVO.setPaymentCompanyName(dtoMap.get(payment.getPaymentCompany()).getName());
// 设置工厂名称
respVO.getFactoryDetail().forEach(item -> {
item.setFactoryName(dtoMap.get(item.getDeptId()).getName());
});
if (payment.getProjectNo() != null) {
if (Strings.isNotEmpty(payment.getProjectNo())) {
// 获取项目信息
ProjectDTO project = projectApi.getProject(payment.getProjectNo()).getCheckedData();
// 设置项目名称
@ -105,13 +117,23 @@ public class BpmOAPaymentController {
BpmOAPaymentRespVO respVO = BeanUtils.toBean(payment, BpmOAPaymentRespVO.class);
if (respVO != null) {
// 获取部门信息Map
List<Long> deptIds = Arrays.asList(payment.getDeptId(), payment.getPaymentCompany());
List<Long> deptIds = new ArrayList<>();
if (CollectionUtil.isNotEmpty(respVO.getFactoryDetail())) {
deptIds.addAll(convertList(respVO.getFactoryDetail(), FactoryDetailVO::getDeptId));
}else {
deptIds.add(payment.getDeptId());
}
deptIds.add(payment.getPaymentCompany());
Map<Long, DeptRespDTO> dtoMap = deptApi.getDeptMap(new HashSet<>(deptIds));
// 设置部门名称
respVO.setDeptName(dtoMap.get(payment.getDeptId()).getName());
respVO.setDeptName(dtoMap.get(payment.getDeptId()) != null ? dtoMap.get(payment.getDeptId()).getName() : null);
// 设置付款公司名称
respVO.setPaymentCompanyName(dtoMap.get(payment.getPaymentCompany()).getName());
// 设置工厂名称
respVO.getFactoryDetail().forEach(item -> {
item.setFactoryName(dtoMap.get(item.getDeptId()).getName());
});
if (payment.getProjectNo() != null) {
// 获取项目信息

View File

@ -29,6 +29,9 @@ public class BpmOAImprestCreateReqVO {
@NotNull(message = "费用类型不能为空")
private String type;
@Schema(description = "收款账号", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private Long bankId;
@Schema(description = "费用事由", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "费用事由不能为空")
private String reason;

View File

@ -28,6 +28,18 @@ public class BpmOAImprestRespVO extends BpmOABaseRespVO {
@NotNull(message = "费用类型不能为空")
private String type;
@Schema(description = "收款账号")
private Long bankId;
@Schema(description = "收款人")
private String nickname;
@Schema(description = "收款银行")
private String bankName;
@Schema(description = "银行卡号")
private String bankNo;
@Schema(description = "费用事由", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "费用事由不能为空")
private String reason;

View File

@ -28,6 +28,9 @@ public class BpmOAPaymentCreateReqVO {
@Schema(description = "费用产生部门编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private Long deptId;
@Schema(description = "工厂明细", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private List<FactoryDetailVO> factoryDetail;
@Schema(description = "项目编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private String projectNo;

View File

@ -31,6 +31,9 @@ public class BpmOAPaymentRespVO extends BpmOABaseRespVO {
@Schema(description = "费用产生部门名称")
private String deptName;
@Schema(description = "工厂明细", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private List<FactoryDetailVO> factoryDetail;
@Schema(description = "项目编号")
private String projectNo;

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Schema(description = "管理后台 - 工厂明细数据")
@Data
public class FactoryDetailVO {
@Schema(description = "工厂编号")
private Long deptId;
@Schema(description = "工厂名称")
private String factoryName;
@Schema(description = "金额")
private BigDecimal money;
}

View File

@ -5,6 +5,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
@ -25,6 +26,10 @@ public class BpmOASalaryCreateReqVO {
@NotNull(message = "申请原因不能为空")
private String reason;
@Schema(description = "薪资月份", requiredMode = Schema.RequiredMode.REQUIRED)
@DateTimeFormat(pattern = "yyyy-MM")
private String salaryDate;
@Schema(description = "付款公司")
private Long companyDeptId;
@ -35,6 +40,10 @@ public class BpmOASalaryCreateReqVO {
@NotNull(message = "付款总额不能为空")
private BigDecimal paymentTotal;
@Schema(description = "支付人数", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "支付人数不能为空")
private Integer paymentNumber;
@Schema(description = "支付对象")
private String paymentRecipient;

View File

@ -6,7 +6,9 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.List;
@ -22,6 +24,10 @@ public class BpmOASalaryRespVO extends BpmOABaseRespVO {
@Schema(description = "申请原因")
private String reason;
@Schema(description = "薪资月份")
@DateTimeFormat(pattern = "yyyy-MM")
private String salaryDate;
@Schema(description = "付款公司")
private Long companyDeptId;
@ -34,6 +40,9 @@ public class BpmOASalaryRespVO extends BpmOABaseRespVO {
@Schema(description = "付款总额")
private BigDecimal paymentTotal;
@Schema(description = "支付人数")
private Integer paymentNumber;
@Schema(description = "支付对象")
private String paymentRecipient;

View File

@ -8,6 +8,10 @@ import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.print.BpmProcessInstan
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*;
import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmTaskRespVO;
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert;
import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.service.financialpayment.FinancialPaymentService;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService;
@ -26,8 +30,10 @@ import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
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.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 流程实例") // 流程实例通过流程定义创建的一次申请
@ -48,13 +54,30 @@ public class BpmProcessInstanceController {
@Resource
private BpmMessageService messageService;
@Resource
private FinancialPaymentService financialPaymentService;
@GetMapping("/my-page")
@Operation(summary = "获得我的实例分页列表", description = "在【我的流程】菜单中,进行调用")
@PreAuthorize("@ss.hasPermission('bpm:process-instance:query')")
@DataPermission(enable = false)
public CommonResult<PageResult<BpmProcessInstancePageItemRespVO>> getMyProcessInstancePage(
@Valid BpmProcessInstanceMyPageReqVO pageReqVO) {
return success(processInstanceService.getMyProcessInstancePage(getLoginUserId(), pageReqVO));
public CommonResult<PageResult<BpmProcessInstancePageItemRespVO>> getMyProcessInstancePage(@Valid BpmProcessInstanceMyPageReqVO pageReqVO) {
PageResult<BpmProcessInstancePageItemRespVO> pageResult = processInstanceService.getMyProcessInstancePage(getLoginUserId(), pageReqVO);
// 获取流程实例编号
List<String> processInstanceIds = pageResult.getList().stream()
.filter(item -> item.getStatus().equals(BpmProcessInstanceResultEnum.APPROVE.getResult()))
.map(BpmProcessInstancePageItemRespVO::getId).collect(Collectors.toList());
// 查询支付信息
List<FinancialPaymentDO> financialPayments = financialPaymentService.getFinancialPaymentList(processInstanceIds);
Map<String, FinancialPaymentDO> financialPaymentMap = convertMap(financialPayments, FinancialPaymentDO::getProcessInstanceId);
pageResult.getList().forEach(item -> {
if (financialPaymentMap.containsKey(item.getId())) {
item.setPaymentStatus(financialPaymentMap.get(item.getId()).getStatus());
}
});
return success(pageResult);
}
@PostMapping("/create")

View File

@ -40,6 +40,9 @@ public class BpmProcessInstancePageItemRespVO {
@Schema(description = "发起人姓名", requiredMode = Schema.RequiredMode.REQUIRED)
private String startUserName ;
@Schema(description = "支付状态")
private Integer paymentStatus;
/**
* 当前任务
*/

View File

@ -50,6 +50,11 @@ public class BpmOAImprestDO extends BaseDO {
*/
private Long userId;
/**
* 收款账号
*/
private Long bankId;
/**
* 费用类型
*/

View File

@ -2,6 +2,7 @@ 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.controller.admin.oa.vo.payment.FactoryDetailVO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
@ -18,7 +19,7 @@ import java.util.List;
*
* @author 艾楷
*/
@TableName("bpm_oa_payment")
@TableName(value = "bpm_oa_payment", autoResultMap = true)
@KeySequence("bpm_oa_payment") // 用于 OraclePostgreSQLKingbaseDB2H2 数据库的主键自增如果是 MySQL 等数据库可不写
@Data
@EqualsAndHashCode(callSuper = true)
@ -55,6 +56,12 @@ public class BpmOAPaymentDO extends BaseDO {
*/
private Long deptId;
/**
* 工厂采购明细数据
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<FactoryDetailVO> factoryDetail;
/**
* 项目编号
*/

View File

@ -13,7 +13,7 @@ import java.math.BigDecimal;
import java.util.List;
/**
* OA 用章申请 DO
* OA 薪资付款 DO
*
* @author 符溶馨
*/
@ -27,7 +27,7 @@ import java.util.List;
public class BpmOASalaryDO extends BaseDO {
/**
* 出差表单主键
* 薪资付款表单主键
*/
@TableId
private Long id;
@ -44,6 +44,11 @@ public class BpmOASalaryDO extends BaseDO {
*/
private String reason;
/**
* 薪资月份
*/
private String salaryDate;
/**
* 付款公司
*/
@ -54,6 +59,11 @@ public class BpmOASalaryDO extends BaseDO {
*/
private BigDecimal paymentTotal;
/**
* 支付人数
*/
private Integer paymentNumber;
/**
* 支付对象
*/

View File

@ -19,7 +19,7 @@ public interface FinancialPaymentService {
/**
* 创建财务支付管理
*
* @param createReqVO 创建信息
* @param vo 创建信息
* @return 编号
*/
Long createFinancialPayment(@Valid FinancialPaymentSaveVO vo);
@ -81,4 +81,11 @@ public interface FinancialPaymentService {
* @param ids
*/
void cancel(List<Long> ids);
/**
* 获取指定流程实例编号的支付信息
* @param processInstanceIds 流程实例编号
* @return 支付信息列表
*/
List<FinancialPaymentDO> getFinancialPaymentList(List<String> processInstanceIds);
}

View File

@ -204,4 +204,10 @@ public class FinancialPaymentServiceImpl implements FinancialPaymentService {
financialPaymentMapper.cancel(ids);
}
@Override
public List<FinancialPaymentDO> getFinancialPaymentList(List<String> processInstanceIds) {
return financialPaymentMapper.selectList(FinancialPaymentDO::getProcessInstanceId, processInstanceIds);
}
}

View File

@ -1,15 +1,24 @@
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.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.financialpayment.FinancialPaymentDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAPaymentDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReimbursementItemDO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmProcessInstanceExtDO;
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAPaymentMapper;
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.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -17,6 +26,7 @@ import javax.annotation.Resource;
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.module.bpm.enums.ErrorCodeConstants.OA_PAYMENT_NOT_EXISTS;
@ -44,6 +54,12 @@ public class BpmOAPaymentServiceImpl extends BpmOABaseService implements BpmOAPa
@Resource
private BpmHistoryProcessInstanceService historyProcessInstanceService;
@Resource
private FinancialPaymentService financialPaymentService;
@Resource
private AdminUserApi userApi;
@Override
public Long createPayment(Long userId, BpmOAPaymentCreateReqVO createReqVO) {
@ -78,7 +94,33 @@ public class BpmOAPaymentServiceImpl extends BpmOABaseService implements BpmOAPa
@Override
public void updatePaymentResult(String processInstanceId, Long id, Integer result) {
validateLeaveExists(id);
BpmOAPaymentDO paymentDO = validateLeaveExists(id);
//审核通过 最后节点
if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
ProcessInstance instance = processInstanceService.getProcessInstance(processInstanceId);
if (instance.isEnded()) {
BpmProcessInstanceExtDO processInstance = processInstanceService.getProcessInstanceDO(processInstanceId);
// -- 插入到财务支付表中
CommonResult<AdminUserRespDTO> user = userApi.getUser(paymentDO.getUserId());
financialPaymentService.save(new FinancialPaymentDO()
.setUserId(paymentDO.getUserId())
.setDeptId(user.getData() == null ? null : user.getData().getDeptId())
.setProcessInstanceId(paymentDO.getProcessInstanceId())
.setReason(paymentDO.getReason())
.setObjectId(id)
.setType(4)
.setStatus(0)
.setAmountPayable(paymentDO.getAmount())
.setProcessInstanceName(processInstance.getName())
.setBeginTime(processInstance.getCreateTime())
.setEndTime(processInstance.getEndTime())
);
}
}
paymentMapper.updateById(new BpmOAPaymentDO().setId(id).setResult(result));
}
@ -100,9 +142,11 @@ public class BpmOAPaymentServiceImpl extends BpmOABaseService implements BpmOAPa
return paymentMapper.selectPaymentList(type);
}
private void validateLeaveExists(Long id) {
if (paymentMapper.selectById(id) == null) {
private BpmOAPaymentDO validateLeaveExists(Long id) {
BpmOAPaymentDO paymentDO = paymentMapper.selectById(id);
if (paymentDO == null) {
throw exception(OA_PAYMENT_NOT_EXISTS);
}
return paymentDO;
}
}