feat(bpm): 添加 OA 回款申请功能
- 实现了 OA 回款申请的创建、查询、统计等功能 - 添加了回款申请相关的数据结构和接口定义 - 实现了回款申请的流程控制和状态更新- 添加了回款申请的附件上传和处理逻辑
This commit is contained in:
parent
1c07abebb0
commit
f9b0c8cf7d
@ -0,0 +1,50 @@
|
||||
package cn.iocoder.yudao.module.bpm.api.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptDTO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.contract.ContractStatisticsRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.ReceiptStatisticsVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReceiptDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAReceiptService;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
/**
|
||||
* Flowable 流程实例 Api 实现类
|
||||
*/
|
||||
@RestController
|
||||
@Validated
|
||||
public class BpmOAReceiptApiImpl implements BpmOAReceiptApi{
|
||||
|
||||
@Resource
|
||||
private BpmOAReceiptService receiptService;
|
||||
|
||||
@Override
|
||||
public CommonResult<ReceiptStatisticsDTO> getReceiptCount(String relation) {
|
||||
ReceiptStatisticsVO respVO = receiptService.getStatistics(getLoginUserId(), relation);
|
||||
return success(BeanUtils.toBean(respVO, ReceiptStatisticsDTO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<BpmOAReceiptDTO>> getReceiptList(BpmOAReceiptVO respVO) {
|
||||
List<BpmOAReceiptDO> receiptDO = receiptService.getReceiptList(respVO);
|
||||
return success(BeanUtils.toBean(receiptDO, BpmOAReceiptDTO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<List<ReceiptStatisticsDTO>> getContractStatistics(List<Long> userIds, LocalDateTime[] createTime) {
|
||||
List<ReceiptStatisticsDTO> respVOS = receiptService.getReceiptStatisticsListByUserIds(userIds, createTime);
|
||||
return success(BeanUtils.toBean(respVOS, ReceiptStatisticsDTO.class));
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa;
|
||||
|
||||
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.receipt.BpmOAReceiptCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAContractDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReceiptDO;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAContractService;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAReceiptService;
|
||||
import cn.iocoder.yudao.module.hrm.api.crmcustomer.CrmCustomerApi;
|
||||
import cn.iocoder.yudao.module.hrm.api.crmcustomer.dto.CrmCustomerDTO;
|
||||
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 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/receipt")
|
||||
@Validated
|
||||
public class BpmOAReceiptController {
|
||||
|
||||
@Resource
|
||||
private BpmOAReceiptService receiptService;
|
||||
|
||||
@Resource
|
||||
private CrmCustomerApi customerApi;
|
||||
|
||||
@Resource
|
||||
private BpmOAContractService contractService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建请求申请")
|
||||
public CommonResult<Long> createReceipt(@Valid @RequestBody BpmOAReceiptCreateReqVO createReqVO) {
|
||||
|
||||
return success(receiptService.createReceipt(getLoginUserId(), createReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得回款申请")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
public CommonResult<BpmOAReceiptRespVO> getReceipt(@RequestParam("id") Long id) {
|
||||
|
||||
BpmOAReceiptDO receipt = receiptService.getReceipt(id);
|
||||
BpmOAReceiptRespVO respVO = BeanUtils.toBean(receipt, BpmOAReceiptRespVO.class);
|
||||
if (respVO != null) {
|
||||
|
||||
// 获取客户信息
|
||||
CrmCustomerDTO crmCustomerDTO = customerApi.getCustomer(receipt.getCustomerId()).getCheckedData();
|
||||
// 获取合同信息
|
||||
BpmOAContractDO contractDO = contractService.getContract(receipt.getContractId());
|
||||
|
||||
// 设置客户名称
|
||||
respVO.setCustomerName(crmCustomerDTO != null ? crmCustomerDTO.getName() : null);
|
||||
// 设置合同名称
|
||||
respVO.setContractName(contractDO != null ? contractDO.getContractName() : null);
|
||||
}
|
||||
|
||||
return success(respVO);
|
||||
}
|
||||
|
||||
@GetMapping("/getByProcessInstanceId")
|
||||
@Operation(summary = "获得回款申请")
|
||||
@Parameter(name = "processInstanceId", description = "流程实例编号", required = true, example = "1024")
|
||||
public CommonResult<BpmOAReceiptRespVO> getByProcessInstanceId(@RequestParam("processInstanceId") String processInstanceId) {
|
||||
|
||||
BpmOAReceiptDO receipt = receiptService.getByProcessInstanceId(processInstanceId);
|
||||
BpmOAReceiptRespVO respVO = BeanUtils.toBean(receipt, BpmOAReceiptRespVO.class);
|
||||
if (respVO != null) {
|
||||
|
||||
// 获取客户信息
|
||||
CrmCustomerDTO crmCustomerDTO = customerApi.getCustomer(receipt.getCustomerId()).getCheckedData();
|
||||
// 获取合同信息
|
||||
BpmOAContractDO contractDO = contractService.getContract(receipt.getContractId());
|
||||
|
||||
// 设置客户名称
|
||||
respVO.setCustomerName(crmCustomerDTO != null ? crmCustomerDTO.getName() : null);
|
||||
// 设置合同名称
|
||||
respVO.setContractName(contractDO != null ? contractDO.getContractName() : null);
|
||||
}
|
||||
|
||||
return success(respVO);
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得回款分页列表")
|
||||
public CommonResult<PageResult<BpmOAReceiptRespVO>> getPage(@Valid BpmOAReceiptPageReqVO pageReqVO) {
|
||||
|
||||
return success(receiptService.getReceiptPage(pageReqVO));
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt;
|
||||
|
||||
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 org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
/**
|
||||
* 回款申请 创建 Request VO
|
||||
*
|
||||
* @author 符溶馨
|
||||
*/
|
||||
@Schema(description = "管理后台 - 回款申请创建 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode()
|
||||
@ToString(callSuper = true)
|
||||
public class BpmOAReceiptCreateReqVO {
|
||||
|
||||
@Schema(description = "客户ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "客户ID不能为空")
|
||||
private Long customerId;
|
||||
|
||||
@Schema(description = "合同ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "合同ID不能为空")
|
||||
private Long contractId;
|
||||
|
||||
@Schema(description = "回款日期", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate returnTime;
|
||||
|
||||
@Schema(description = "回款金额", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "回款金额不能为空")
|
||||
private BigDecimal money;
|
||||
|
||||
@Schema(description = "备注", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
|
||||
private String remark;
|
||||
|
||||
@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;
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Schema(description = "管理后台 - 回款申请分页 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class BpmOAReceiptPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "客户名称,模糊匹配")
|
||||
private String customerName;
|
||||
|
||||
@Schema(description = "合同名称,模糊匹配")
|
||||
private String contractName;
|
||||
|
||||
@Schema(description = "审批结果")
|
||||
private Integer result;
|
||||
|
||||
@Schema(description = "创建人名称")
|
||||
private String createName;
|
||||
|
||||
@Schema(description = "查询模式")
|
||||
private String relation;
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt;
|
||||
|
||||
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 org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
/**
|
||||
* @author 符溶馨
|
||||
*/
|
||||
@Schema(description = "管理后台 - 退款申请 请求Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BpmOAReceiptRespVO extends BpmOABaseRespVO {
|
||||
|
||||
@Schema(description = "客户ID")
|
||||
private Long customerId;
|
||||
|
||||
@Schema(description = "客户名称")
|
||||
private String customerName;
|
||||
|
||||
@Schema(description = "合同ID")
|
||||
private Long contractId;
|
||||
|
||||
@Schema(description = "合同编号")
|
||||
private String contractNo;
|
||||
|
||||
@Schema(description = "合同名称")
|
||||
private String contractName;
|
||||
|
||||
@Schema(description = "回款日期")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate returnTime;
|
||||
|
||||
@Schema(description = "回款金额")
|
||||
private BigDecimal money;
|
||||
|
||||
@Schema(description = "备注")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String createName;
|
||||
|
||||
@Schema(description = "上传文件", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private List<UploadUserFile> fileItems;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 合同审批 请求Request VO")
|
||||
@Data
|
||||
public class ReceiptStatisticsVO {
|
||||
|
||||
@Schema(description = "用户编号")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "今日新增回款金额")
|
||||
private BigDecimal todayAddMoney;
|
||||
|
||||
@Schema(description = "昨日新增回款金额")
|
||||
private BigDecimal yesterdayAddMoney;
|
||||
|
||||
@Schema(description = "较昨日百分比 | 金额")
|
||||
private BigDecimal moneyPercentage;
|
||||
|
||||
@Schema(description = "回款总金额")
|
||||
private BigDecimal money;
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
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.refund.BpmOARefundItems;
|
||||
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.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OA 回款申请 DO
|
||||
*
|
||||
* @author 符溶馨
|
||||
*/
|
||||
@TableName(value ="bpm_oa_receipt", autoResultMap = true)
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BpmOAReceiptDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* 出差表单主键
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 申请人的用户编号
|
||||
* 关联 AdminUserDO 的 id 属性
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 客户ID
|
||||
*/
|
||||
private Long customerId;
|
||||
|
||||
/**
|
||||
* 合同ID
|
||||
*/
|
||||
private Long contractId;
|
||||
|
||||
/**
|
||||
* 回款日期
|
||||
*/
|
||||
private LocalDate returnTime;
|
||||
|
||||
/**
|
||||
* 回款金额
|
||||
*/
|
||||
private BigDecimal money;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 结果
|
||||
* 枚举 {@link BpmProcessInstanceResultEnum}
|
||||
* 考虑到简单,所以直接复用了 BpmProcessInstanceResultEnum 枚举,也可以自己定义一个枚举哈
|
||||
*/
|
||||
private Integer result;
|
||||
|
||||
/**
|
||||
* 对应的流程编号
|
||||
* 关联 ProcessInstance 的 id 属性
|
||||
*/
|
||||
private String processInstanceId;
|
||||
|
||||
/**
|
||||
* 附件基本信息
|
||||
*/
|
||||
@TableField(typeHandler = JacksonTypeHandler.class)
|
||||
private List<UploadUserFile> fileItems ;
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
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.MPJLambdaWrapperX;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
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.receipt.BpmOAReceiptPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.ReceiptStatisticsVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAContractDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReceiptDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Mapper
|
||||
public interface BpmOAReceiptMapper extends BaseMapperX<BpmOAReceiptDO> {
|
||||
default PageResult<BpmOAReceiptRespVO> selectReceiptPage(BpmOAReceiptPageReqVO pageReqVO, Long userId) {
|
||||
|
||||
MPJLambdaWrapperX<BpmOAReceiptDO> query = new MPJLambdaWrapperX<>();
|
||||
query.selectAll(BpmOAReceiptDO.class);
|
||||
query.selectAs(BpmOAContractDO::getContractName, BpmOAReceiptRespVO::getContractName);
|
||||
query.selectAs(BpmOAContractDO::getCustomerName, BpmOAReceiptRespVO::getCustomerName);
|
||||
query.selectAs(BpmOAContractDO::getContractNo, BpmOAReceiptRespVO::getContractNo);
|
||||
query.selectAs("u.nickname", BpmOAReceiptRespVO::getCreateName);
|
||||
query.leftJoin(BpmOAContractDO.class, "c", BpmOAContractDO::getId, BpmOAReceiptDO::getContractId);
|
||||
query.leftJoin("system_users u on u.id = t.creator");
|
||||
query.eqIfPresent(BpmOAReceiptDO::getResult, pageReqVO.getResult());
|
||||
query.apply(Objects.nonNull(pageReqVO.getCustomerName()), "c.customer_name LIKE CONCAT('%', {0}, '%')", pageReqVO.getCustomerName());
|
||||
query.apply(Objects.nonNull(pageReqVO.getContractName()), "c.contract_name LIKE CONCAT('%', {0}, '%')", pageReqVO.getContractName());
|
||||
query.apply(Objects.nonNull(pageReqVO.getCreateName()),"u.nickname Like CONCAT('%', {0}, '%')", pageReqVO.getCreateName());
|
||||
if ("my".equals(pageReqVO.getRelation())) {
|
||||
query.eq(BpmOAContractDO::getUserId, userId);
|
||||
}else if ("sub".equals(pageReqVO.getRelation())){
|
||||
query.innerJoin("(" +
|
||||
"\tSELECT DISTINCT\n" +
|
||||
"\t\tu.id \n" +
|
||||
"\tFROM\n" +
|
||||
"\t\tsystem_users u\n" +
|
||||
"\t\tINNER JOIN system_dept d ON d.leader_user_id = "+ userId +"\n" +
|
||||
"\t\tINNER JOIN system_dept d1 ON d1.flag LIKE CONCAT( '%', d.id, '-' ) \n" +
|
||||
"\t\tOR d1.flag LIKE CONCAT( '%-', d.id, '-%' ) \n" +
|
||||
"\t\tOR d1.flag LIKE CONCAT( '-', d.id, '%' ) \n" +
|
||||
"\tWHERE\n" +
|
||||
"\t\tu.dept_id = d1.id \n" +
|
||||
"\t\tAND u.STATUS = 0 \n" +
|
||||
"\t) subordinate ON subordinate.id = t.user_id");
|
||||
}
|
||||
query.orderByDesc(BpmOAReceiptDO::getCreateTime);
|
||||
|
||||
return selectJoinPage(pageReqVO, BpmOAReceiptRespVO.class, query);
|
||||
}
|
||||
|
||||
ReceiptStatisticsVO selectStatistics(@Param("userId") Long userId,
|
||||
@Param("relation") String relation);
|
||||
|
||||
List<ReceiptStatisticsDTO> selectReceiptStatisticsListByUserIds(@Param("userIds") List<Long> userIds,
|
||||
@Param("createTime") LocalDateTime[] createTime);
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.BpmOAReceiptVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.contract.BpmOAContractPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.ReceiptStatisticsVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReceiptDO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
public interface BpmOAReceiptService {
|
||||
|
||||
/**
|
||||
* 创建回款申请
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createReceipt(Long userId, @Valid BpmOAReceiptCreateReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新回款申请的状态
|
||||
*
|
||||
* @param id 编号
|
||||
* @param result 结果
|
||||
*/
|
||||
void updateReceiptResult(String processInstanceId, Long id, Integer result);
|
||||
|
||||
/**
|
||||
* 获得回款申请
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 退款申请
|
||||
*/
|
||||
BpmOAReceiptDO getReceipt(Long id);
|
||||
|
||||
/**
|
||||
* 获得指定的回款申请
|
||||
* @param processInstanceId 流程实例编号
|
||||
* @return 退款申请
|
||||
*/
|
||||
BpmOAReceiptDO getByProcessInstanceId(String processInstanceId);
|
||||
|
||||
/**
|
||||
* 获得回款申请分页列表
|
||||
* @param pageReqVO 分页信息
|
||||
* @return 分页列表
|
||||
*/
|
||||
PageResult<BpmOAReceiptRespVO> getReceiptPage(BpmOAReceiptPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得回款统计信息
|
||||
* @param userId 用户编号
|
||||
* @param relation 查询类型
|
||||
* @return 回款统计信息
|
||||
*/
|
||||
ReceiptStatisticsVO getStatistics(Long userId, String relation);
|
||||
|
||||
/**
|
||||
* 获得回款列表
|
||||
* @param respVO 参数信息
|
||||
* @return 回款信息列表
|
||||
*/
|
||||
List<BpmOAReceiptDO> getReceiptList(BpmOAReceiptVO respVO);
|
||||
|
||||
/**
|
||||
* 获得指定用户回款统计信息
|
||||
* @param userIds 用户编号
|
||||
* @param createTime 创建时间
|
||||
* @return 回款统计信息
|
||||
*/
|
||||
List<ReceiptStatisticsDTO> getReceiptStatisticsListByUserIds(List<Long> userIds, LocalDateTime[] createTime);
|
||||
}
|
@ -0,0 +1,180 @@
|
||||
package cn.iocoder.yudao.module.bpm.service.oa;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
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.oa.vo.receipt.BpmOAReceiptVO;
|
||||
import cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO;
|
||||
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.receipt.BpmOAReceiptCreateReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptPageReqVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.BpmOAReceiptRespVO;
|
||||
import cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.ReceiptStatisticsVO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.dataobject.oa.BpmOAReceiptDO;
|
||||
import cn.iocoder.yudao.module.bpm.dal.mysql.oa.BpmOAReceiptMapper;
|
||||
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 org.flowable.engine.runtime.ProcessInstance;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDateTime;
|
||||
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.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.OA_RECEIPT_NOT_EXISTS;
|
||||
|
||||
/**
|
||||
* OA 回款申请 Service 实现类
|
||||
*
|
||||
* @author 符溶馨
|
||||
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class BpmOAReceiptServiceImpl extends BpmOABaseService implements BpmOAReceiptService{
|
||||
|
||||
/**
|
||||
* OA 退款对应的流程定义 KEY
|
||||
*/
|
||||
public static final String PROCESS_KEY = "oa_receipt_2";
|
||||
|
||||
@Resource
|
||||
private BpmOAReceiptMapper receiptMapper;
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceApi processInstanceApi;
|
||||
|
||||
@Resource
|
||||
private BpmHistoryProcessInstanceService historyProcessInstanceService;
|
||||
|
||||
@Resource
|
||||
private BpmProcessInstanceService bpmProcessInstanceService;
|
||||
|
||||
@Override
|
||||
public Long createReceipt(Long userId, BpmOAReceiptCreateReqVO createReqVO) {
|
||||
|
||||
//插入OA 回款申请
|
||||
BpmOAReceiptDO receipt = BeanUtils.toBean(createReqVO, BpmOAReceiptDO.class)
|
||||
.setUserId(userId)
|
||||
.setResult(BpmProcessInstanceResultEnum.PROCESS.getResult());
|
||||
receiptMapper.insert(receipt) ;
|
||||
|
||||
// 发起 BPM 流程
|
||||
Map<String, Object> processInstanceVariables = new HashMap<>();
|
||||
String processInstanceId = processInstanceApi.createProcessInstance(userId,
|
||||
new BpmProcessInstanceCreateReqDTO().setProcessDefinitionKey(PROCESS_KEY)
|
||||
.setVariables(processInstanceVariables).setBusinessKey(String.valueOf(receipt.getId()))).getCheckedData();
|
||||
|
||||
// 将工作流的编号,更新到 OA 回款申请单中
|
||||
receiptMapper.updateById(new BpmOAReceiptDO().setId(receipt.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 receipt.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateReceiptResult(String processInstanceId, Long id, Integer result) {
|
||||
|
||||
BpmOAReceiptDO receiptDO = validateLeaveExists(id);
|
||||
//审核通过 (最后节点)
|
||||
if (BpmProcessInstanceResultEnum.APPROVE.getResult().equals(result)) {
|
||||
|
||||
ProcessInstance instance = bpmProcessInstanceService.getProcessInstance(processInstanceId);
|
||||
|
||||
if (instance.isEnded()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
receiptMapper.updateById(new BpmOAReceiptDO().setId(id).setResult(result));
|
||||
}
|
||||
|
||||
private BpmOAReceiptDO validateLeaveExists(Long id) {
|
||||
BpmOAReceiptDO receiptDO = receiptMapper.selectById(id);
|
||||
if (receiptDO == null) {
|
||||
throw exception(OA_RECEIPT_NOT_EXISTS);
|
||||
}
|
||||
return receiptDO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmOAReceiptDO getReceipt(Long id) {
|
||||
|
||||
return receiptMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BpmOAReceiptDO getByProcessInstanceId(String processInstanceId) {
|
||||
|
||||
return receiptMapper.selectOne(BpmOAReceiptDO::getProcessInstanceId, processInstanceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<BpmOAReceiptRespVO> getReceiptPage(BpmOAReceiptPageReqVO pageReqVO) {
|
||||
|
||||
return receiptMapper.selectReceiptPage(pageReqVO, getLoginUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReceiptStatisticsVO getStatistics(Long userId, String relation) {
|
||||
ReceiptStatisticsVO respVO = receiptMapper.selectStatistics(userId, relation);
|
||||
|
||||
// 设置数量、金额百分比
|
||||
respVO.setMoneyPercentage(calculatePercentageChange(respVO.getTodayAddMoney(), respVO.getYesterdayAddMoney()));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BpmOAReceiptDO> getReceiptList(BpmOAReceiptVO respVO) {
|
||||
|
||||
return receiptMapper.selectList(new LambdaQueryWrapperX<BpmOAReceiptDO>()
|
||||
.inIfPresent(BpmOAReceiptDO::getUserId, respVO.getUserId())
|
||||
.eq(BpmOAReceiptDO::getResult, BpmProcessInstanceResultEnum.APPROVE.getResult())
|
||||
.betweenIfPresent(BpmOAReceiptDO::getReturnTime, respVO.getStarTime(), respVO.getEndTime()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ReceiptStatisticsDTO> getReceiptStatisticsListByUserIds(List<Long> userIds, LocalDateTime[] createTime) {
|
||||
|
||||
return receiptMapper.selectReceiptStatisticsListByUserIds(userIds, createTime);
|
||||
}
|
||||
|
||||
public static BigDecimal calculatePercentageChange(Object today, Object yesterday) {
|
||||
|
||||
// 转换为 BigDecimal 进行高精度计算
|
||||
BigDecimal bigToday = new BigDecimal(today.toString());
|
||||
BigDecimal bigYesterday = new BigDecimal(yesterday.toString());
|
||||
|
||||
if (bigYesterday.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
// 计算百分比变化
|
||||
BigDecimal difference = bigToday.subtract(bigYesterday); // a - b
|
||||
BigDecimal percentageChange = difference.divide(bigYesterday, 2, RoundingMode.HALF_UP); // (a - b) / b
|
||||
|
||||
// 转为百分比并返回
|
||||
return percentageChange.multiply(new BigDecimal(100)); // (result) * 100
|
||||
}
|
||||
}
|
@ -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.BpmOAReceiptService;
|
||||
import cn.iocoder.yudao.module.bpm.service.oa.BpmOAReceiptServiceImpl;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* OA 回款单的结果的监听器实现类
|
||||
*
|
||||
* @author 符溶馨
|
||||
*/
|
||||
@Component
|
||||
public class BpmOAReceiptResultListener extends BpmProcessInstanceResultEventListener {
|
||||
|
||||
@Resource
|
||||
private BpmOAReceiptService receiptService;
|
||||
|
||||
@Override
|
||||
protected String getProcessDefinitionKey() {
|
||||
|
||||
return BpmOAReceiptServiceImpl.PROCESS_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onEvent(BpmProcessInstanceResultEvent event) {
|
||||
receiptService.updateReceiptResult(event.getId(), Long.parseLong(event.getBusinessKey()), event.getResult());
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?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.BpmOAReceiptMapper">
|
||||
|
||||
<!--
|
||||
一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。
|
||||
无法满足的场景,例如说多表关联查询,才使用 XML 编写 SQL。
|
||||
代码生成器暂时只生成 Mapper XML 文件本身,更多推荐 MybatisX 快速开发插件来生成查询。
|
||||
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||
-->
|
||||
<select id="selectStatistics" resultType="cn.iocoder.yudao.module.bpm.controller.admin.oa.vo.receipt.ReceiptStatisticsVO">
|
||||
SELECT
|
||||
COALESCE ( SUM( CASE WHEN DATE( a.create_time ) = CURDATE() THEN a.money END ), 0 ) AS todayAddMoney,
|
||||
COALESCE ( SUM( CASE WHEN DATE( a.create_time ) = CURDATE() - INTERVAL 1 DAY THEN a.money END ), 0 ) AS yesterdayAddMoney
|
||||
FROM
|
||||
bpm_oa_receipt a
|
||||
<if test="relation == 'sub'">
|
||||
INNER JOIN (
|
||||
SELECT DISTINCT
|
||||
u.id
|
||||
FROM
|
||||
system_users u
|
||||
INNER JOIN system_dept d ON d.leader_user_id = #{userId}
|
||||
INNER JOIN system_dept d1 ON d1.flag LIKE CONCAT( '%', d.id, '-' )
|
||||
OR d1.flag LIKE CONCAT( '%-', d.id, '-%' )
|
||||
OR d1.flag LIKE CONCAT( '-', d.id, '%' )
|
||||
WHERE
|
||||
u.dept_id = d1.id
|
||||
AND u.STATUS = 0
|
||||
) subordinate ON subordinate.id = a.user_id
|
||||
</if>
|
||||
WHERE
|
||||
a.result = 2
|
||||
<if test="relation == 'my'">
|
||||
AND a.user_id = #{userId}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="selectReceiptStatisticsListByUserIds" resultType="cn.iocoder.yudao.module.bpm.api.oa.vo.receipt.ReceiptStatisticsDTO">
|
||||
SELECT
|
||||
user_id AS userId,
|
||||
SUM(money) AS money
|
||||
FROM
|
||||
bpm_oa_receipt
|
||||
WHERE
|
||||
deleted = 0
|
||||
AND result = 2
|
||||
AND user_id IN
|
||||
<foreach item="userId" collection="userIds" separator="," open="(" close=")" index="">
|
||||
#{userId}
|
||||
</foreach>
|
||||
<if test="createTime != null and createTime.length > 0">
|
||||
<if test="createTime[0] != null">
|
||||
and create_time >= #{createTime[0]}
|
||||
</if>
|
||||
<if test="createTime[1] != null">
|
||||
and create_time <= #{createTime[1]}
|
||||
</if>
|
||||
</if>
|
||||
GROUP BY user_id
|
||||
</select>
|
||||
</mapper>
|
Loading…
Reference in New Issue
Block a user