feat(bpm): 后补票功能支持

- 新增后补票相关的字段和接口
- 实现后补票的分页查询、附件上传、状态更新和附件删除功能
- 优化后补票列表的展示,增加申请人信息和部门信息
This commit is contained in:
furongxin 2025-01-05 10:56:13 +08:00
parent 44a86b1bac
commit 23d3c78eda
9 changed files with 249 additions and 15 deletions

View File

@ -1,15 +1,12 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.enums.DeptTypeEnum;
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.module.bpm.controller.admin.oa.vo.contract.BpmOAContractPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.contract.BpmOAContractRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentPageReqVO;
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.controller.admin.oa.vo.payment.*;
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;
@ -18,20 +15,23 @@ 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.project.ProjectApi;
import cn.iocoder.yudao.module.system.api.project.dto.ProjectDTO;
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.apache.commons.lang3.StringUtils;
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.*;
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.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
/**
@ -52,6 +52,9 @@ public class BpmOAPaymentController {
@Resource
private ProjectApi projectApi;
@Resource
private AdminUserApi userApi;
@Resource
private DeptApi deptApi;
@ -172,6 +175,80 @@ public class BpmOAPaymentController {
@Operation(summary = "获得 后补票的付款申请分页列表")
public CommonResult<PageResult<BpmOAPaymentRespVO>> getPage(@Valid BpmOAPaymentPageReqVO pageReqVO) {
return success(paymentService.getPaymentPage(pageReqVO));
// 获取所有 财务部门信息
List<DeptRespDTO> deptRespDTOS = deptApi.getDeptListByType(DeptTypeEnum.FINANCE_DEPT.getValue()).getCheckedData();
// 筛选 所属总公司的财务部门
List<DeptRespDTO> dto = deptApi.getDeptListByType(DeptTypeEnum.HEAD_COMPANY.getValue()).getCheckedData();
Long headCompanyId = dto.get(0).getId();
deptRespDTOS = deptRespDTOS.stream()
.filter(item -> item.getFlag().contains(headCompanyId.toString()))
.collect(Collectors.toList());
// 获取财务部门下 所有用户信息
List<AdminUserRespDTO> userRespDTOS = userApi.getUserListByDeptIds(convertSet(deptRespDTOS, DeptRespDTO::getId)).getCheckedData();
List<Long> userIds = convertList(userRespDTOS, AdminUserRespDTO::getId);
// 判断当前登录用户是否属于财务部
pageReqVO.setIsMy(!userIds.contains(getLoginUserId()));
PageResult<BpmOAPaymentRespVO> pageResult = BeanUtils.toBean(paymentService.getPaymentPage(pageReqVO, getLoginUserId()), BpmOAPaymentRespVO.class);
if (CollUtil.isNotEmpty(pageResult.getList())) {
// 获取发起人用户信息
Set<Long> startUserIds = convertSet(pageResult.getList(), BpmOAPaymentRespVO::getUserId);
Map<Long, AdminUserRespDTO> userMap = userApi.getUserMap(startUserIds);
// 获取部门信息Map
List<Long> deptIds = new ArrayList<>();
// 获取工厂详情
List<List<FactoryDetailVO>> factoryDetailList = convertList(pageResult.getList(), BpmOAPaymentRespVO::getFactoryDetail);
List<FactoryDetailVO> factoryDetailVOS = factoryDetailList.stream().flatMap(List::stream).collect(Collectors.toList());
if (CollectionUtil.isNotEmpty(factoryDetailVOS)) {
deptIds.addAll(convertList(factoryDetailVOS, FactoryDetailVO::getDeptId));
}else {
deptIds.addAll(convertList(pageResult.getList(), BpmOAPaymentRespVO::getDeptId));
}
// 添加公司集合
deptIds.addAll(convertList(pageResult.getList(), BpmOAPaymentRespVO::getPaymentCompany));
Map<Long, DeptRespDTO> dtoMap = deptApi.getDeptMap(new HashSet<>(deptIds));
pageResult.getList().forEach(item -> {
item.setUserName(userMap.get(item.getUserId()).getNickname());
// 设置部门名称
item.setDeptName(dtoMap.get(item.getDeptId()) != null ? dtoMap.get(item.getDeptId()).getName() : null);
// 设置付款公司名称
item.setPaymentCompanyName(dtoMap.get(item.getPaymentCompany()).getName());
// 设置工厂名称
item.getFactoryDetail().forEach(detail -> {
detail.setFactoryName(dtoMap.get(detail.getDeptId()).getName());
});
});
}
return success(pageResult);
}
@PutMapping("update-files")
@Operation(summary = "继续上传附件")
public CommonResult<Boolean> updateFiles(@Valid @RequestBody BpmOAPaymentUpdateReqVO updateReqVO) {
paymentService.updateFiles(updateReqVO);
return success(true);
}
@PutMapping("update-status")
@Operation(summary = "修改付款申请的补票状态")
public CommonResult<Boolean> updateStatus(@Valid @RequestBody BpmOAPaymentUpdateReqVO updateReqVO) {
paymentService.updateStatus(updateReqVO);
return success(true);
}
@PutMapping("/delete-files")
@Operation(summary = "删除后补附件")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
@Parameter(name = "url", description = "url", required = true, example = "1024")
public CommonResult<Boolean> deleteUser(@RequestParam("id") Long id,
@RequestParam("url") String url) {
paymentService.deleteFiles(id, url);
return success(true);
}
}

View File

@ -63,6 +63,9 @@ public class BpmOAPaymentCreateReqVO {
@Schema(description = "后补票批注", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private String annotations;
@Schema(description = "补票状态 | 0待补票 1已补票 2已确认", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private Integer status;
@Schema(description = "父级审批编号", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private Long parentId;

View File

@ -6,6 +6,9 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 付款申请分页 Request VO")
@Data
@ -16,4 +19,11 @@ public class BpmOAPaymentPageReqVO extends PageParam {
@Schema(description = "补票状态 | 0待补票 1已补票 2已确认")
private Integer status;
@Schema(description = "是否我的申请")
private Boolean isMy;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private String[] createTime;
}

View File

@ -19,6 +19,12 @@ import java.util.List;
@ToString(callSuper = true)
public class BpmOAPaymentRespVO extends BpmOABaseRespVO {
@Schema(description = "申请人编号")
private Long userId;
@Schema(description = "申请人名称")
private String userName;
@Schema(description = "申请事由")
private String reason;
@ -79,6 +85,9 @@ public class BpmOAPaymentRespVO extends BpmOABaseRespVO {
@Schema(description = "后补票批注", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private String annotations;
@Schema(description = "补票状态 | 0待补票 1已补票 2已确认", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private Integer status;
@Schema(description = "父级审批编号")
private Long parentId;
@ -87,4 +96,7 @@ public class BpmOAPaymentRespVO extends BpmOABaseRespVO {
@Schema(description = "上传文件")
private List<UploadUserFile> fileItems;
@Schema(description = "后补文件")
private List<UploadUserFile> laterFileItems;
}

View File

@ -0,0 +1,29 @@
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 付款申请 创建 Request VO
*
* @author 符溶馨
*/
@Schema(description = "管理后台 - 付款申请创建 Request VO")
@Data
public class BpmOAPaymentUpdateReqVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Long id;
@Schema(description = "后补票批注", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private String annotations;
@Schema(description = "补票状态 | 0待补票 1已补票 2重新补票 3已确认", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
private Integer status;
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
private List<UploadUserFile> fileItems;
}

View File

@ -112,6 +112,11 @@ public class BpmOAPaymentDO extends BaseDO {
*/
private String annotations;
/**
* 补票状态 | 0待补票 1已补票 2重新补票 3已确认
*/
private Integer status;
/**
* 父级审批
*/
@ -135,4 +140,10 @@ public class BpmOAPaymentDO extends BaseDO {
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<UploadUserFile> fileItems ;
/**
* 后补附件基本信息
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private List<UploadUserFile> laterFileItems;
}

View File

@ -1,8 +1,12 @@
package cn.iocoder.yudao.module.bpm.dal.mysql.oa;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentRespVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAPaymentDO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -12,4 +16,16 @@ import java.util.List;
public interface BpmOAPaymentMapper extends BaseMapperX<BpmOAPaymentDO> {
List<BpmOAPaymentRespVO> selectPaymentList(@Param("type") Integer type);
default PageResult<BpmOAPaymentDO> selectTicketsPage(BpmOAPaymentPageReqVO pageReqVO, Long userId) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<BpmOAPaymentDO>()
.eq(BpmOAPaymentDO::getResult, BpmProcessInstanceResultEnum.APPROVE.getResult())
.eq(BpmOAPaymentDO::getIsTickets, 1)
.eqIfPresent(BpmOAPaymentDO::getStatus, pageReqVO.getStatus())
.betweenIfPresent(BpmOAPaymentDO::getCreateTime, pageReqVO.getCreateTime())
.eq(pageReqVO.getIsMy(), BpmOAPaymentDO::getUserId, userId)
.orderByAsc(BpmOAPaymentDO::getStatus)
.orderByDesc(BpmOAPaymentDO::getId));
}
}

View File

@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentCreateReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentUpdateReqVO;
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAPaymentDO;
import javax.validation.Valid;
@ -51,8 +52,29 @@ public interface BpmOAPaymentService {
/**
* 获得 后补票的付款申请分页列表
*
* @param pageReqVO 分页条件
* @param userId 用户编号
* @return 付款申请分页列表
*/
PageResult<BpmOAPaymentRespVO> getPaymentPage(BpmOAPaymentPageReqVO pageReqVO);
PageResult<BpmOAPaymentDO> getPaymentPage(BpmOAPaymentPageReqVO pageReqVO, Long userId);
/**
* 更新付款申请附件
* @param updateReqVO 更新信息
*/
void updateFiles(BpmOAPaymentUpdateReqVO updateReqVO);
/**
* 更新付款申请补票状态
* @param updateReqVO 更新信息
*/
void updateStatus(BpmOAPaymentUpdateReqVO updateReqVO);
/**
* 删除后补附件信息
* @param id 编号
* @param url utl
*/
void deleteFiles(Long id, String url);
}

View File

@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.bpm.service.oa;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.UploadUserFile;
@ -9,9 +9,9 @@ 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.BpmOAPaymentPageReqVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentRespVO;
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.payment.BpmOAPaymentUpdateReqVO;
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;
@ -25,12 +25,13 @@ import org.springframework.stereotype.Service;
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.module.bpm.enums.ErrorCodeConstants.OA_PAYMENT_FILES_NOT_NULL;
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_PAYMENT_NOT_EXISTS;
/**
@ -68,6 +69,9 @@ public class BpmOAPaymentServiceImpl extends BpmOABaseService implements BpmOAPa
//插入OA 付款申请
BpmOAPaymentDO paymentDO = BeanUtils.toBean(createReqVO, BpmOAPaymentDO.class).setUserId(userId)
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
if (createReqVO.getIsTickets() == 1) {
paymentDO.setStatus(0); // 设置补票状态 为待补票
}
paymentMapper.insert(paymentDO);
// 发起 BPM 流程
@ -145,9 +149,59 @@ public class BpmOAPaymentServiceImpl extends BpmOABaseService implements BpmOAPa
}
@Override
public PageResult<BpmOAPaymentRespVO> getPaymentPage(BpmOAPaymentPageReqVO pageReqVO) {
public PageResult<BpmOAPaymentDO> getPaymentPage(BpmOAPaymentPageReqVO pageReqVO, Long userId) {
return null;
return paymentMapper.selectTicketsPage(pageReqVO, userId);
}
@Override
public void updateFiles(BpmOAPaymentUpdateReqVO updateReqVO) {
// 校验付款申请是否存在
BpmOAPaymentDO paymentDO = validateLeaveExists(updateReqVO.getId());
//这里的逻辑如果fileItems不为空且有数据那么说明是上传了附件的则需要更工作流文件表对应的实例Id
if (CollUtil.isNotEmpty(updateReqVO.getFileItems())) {
uploadBpmFileProcessInstanceId(paymentDO.getProcessInstanceId(), updateReqVO.getFileItems()) ;
}else {
throw exception(OA_PAYMENT_FILES_NOT_NULL);
}
// 更新附件
paymentMapper.updateById(new BpmOAPaymentDO()
.setId(paymentDO.getId())
.setLaterFileItems(updateReqVO.getFileItems())
.setStatus(updateReqVO.getStatus()));
}
@Override
public void updateStatus(BpmOAPaymentUpdateReqVO updateReqVO) {
// 校验付款申请是否存在
BpmOAPaymentDO paymentDO = validateLeaveExists(updateReqVO.getId());
BpmOAPaymentDO update = BeanUtils.toBean(updateReqVO, BpmOAPaymentDO.class);
if (update.getStatus() == 3) {
List<UploadUserFile> fileItems = paymentDO.getFileItems() == null ? new ArrayList<>() : paymentDO.getFileItems();
fileItems.addAll(paymentDO.getLaterFileItems());
update.setFileItems(fileItems);
}
paymentMapper.updateById(update);
}
@Override
public void deleteFiles(Long id, String url) {
// 校验付款申请是否存在
BpmOAPaymentDO paymentDO = validateLeaveExists(id);
List<UploadUserFile> fileItems = paymentDO.getLaterFileItems();
if (CollUtil.isNotEmpty(fileItems)) {
fileItems.removeIf(item -> item.getUrl().equals(url));
paymentMapper.updateById(new BpmOAPaymentDO()
.setId(id)
.setLaterFileItems(fileItems));
}
}
private BpmOAPaymentDO validateLeaveExists(Long id) {