Commit a03e661a56fa86c38048bdb5719a2073b536b990

Authored by 芋道源码
Committed by Gitee
2 parents c777237d 3b612b2e

!868 feat: 待回款提醒,即将到期的合同,待审核回款

Merge pull request !868 from dhb52/develop
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java
@@ -14,6 +14,9 @@ import lombok.ToString; @@ -14,6 +14,9 @@ import lombok.ToString;
14 @ToString(callSuper = true) 14 @ToString(callSuper = true)
15 public class CrmContractPageReqVO extends PageParam { 15 public class CrmContractPageReqVO extends PageParam {
16 16
  17 + public static final Integer EXPIRY_TYPE_ABOUT_TO_EXPIRE = 1;
  18 + public static final Integer EXPIRY_TYPE_EXPIRED = 2;
  19 +
17 @Schema(description = "合同编号", example = "XYZ008") 20 @Schema(description = "合同编号", example = "XYZ008")
18 private String no; 21 private String no;
19 22
@@ -30,4 +33,10 @@ public class CrmContractPageReqVO extends PageParam { @@ -30,4 +33,10 @@ public class CrmContractPageReqVO extends PageParam {
30 @InEnum(CrmSceneTypeEnum.class) 33 @InEnum(CrmSceneTypeEnum.class)
31 private Integer sceneType; // 场景类型,为 null 时则表示全部 34 private Integer sceneType; // 场景类型,为 null 时则表示全部
32 35
  36 + @Schema(description = "审批状态", example = "20")
  37 + private Integer auditStatus;
  38 +
  39 + @Schema(description = "过期类型", example = "1")
  40 + private Integer expiryType; // 过期类型,为 null 时则表示全部
  41 +
33 } 42 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java
@@ -14,6 +14,13 @@ import lombok.ToString; @@ -14,6 +14,13 @@ import lombok.ToString;
14 @ToString(callSuper = true) 14 @ToString(callSuper = true)
15 public class CrmReceivablePlanPageReqVO extends PageParam { 15 public class CrmReceivablePlanPageReqVO extends PageParam {
16 16
  17 + // 待回款
  18 + public final static Integer REMIND_NEEDED = 1;
  19 + // 已逾期
  20 + public final static Integer REMIND_EXPIRED = 2;
  21 + // 已回款
  22 + public final static Integer REMIND_RECEIVED = 3;
  23 +
17 @Schema(description = "客户编号", example = "18026") 24 @Schema(description = "客户编号", example = "18026")
18 private Long customerId; 25 private Long customerId;
19 26
@@ -25,4 +32,7 @@ public class CrmReceivablePlanPageReqVO extends PageParam { @@ -25,4 +32,7 @@ public class CrmReceivablePlanPageReqVO extends PageParam {
25 @InEnum(CrmSceneTypeEnum.class) 32 @InEnum(CrmSceneTypeEnum.class)
26 private Integer sceneType; // 场景类型,为 null 时则表示全部 33 private Integer sceneType; // 场景类型,为 null 时则表示全部
27 34
  35 + @Schema(description = "提醒类型", example = "1")
  36 + private Integer remindType; // 提醒类型,为 null 时则表示全部
  37 +
28 } 38 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java
@@ -27,4 +27,7 @@ public class CrmReceivablePageReqVO extends PageParam { @@ -27,4 +27,7 @@ public class CrmReceivablePageReqVO extends PageParam {
27 @InEnum(CrmSceneTypeEnum.class) 27 @InEnum(CrmSceneTypeEnum.class)
28 private Integer sceneType; // 场景类型,为 null 时则表示全部 28 private Integer sceneType; // 场景类型,为 null 时则表示全部
29 29
  30 + @Schema(description = "审批状态", example = "20")
  31 + private Integer auditStatus;
  32 +
30 } 33 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java
1 package cn.iocoder.yudao.module.crm.dal.mysql.contract; 1 package cn.iocoder.yudao.module.crm.dal.mysql.contract;
2 2
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
7 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; 8 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO;
8 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; 9 import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO;
  10 +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum;
9 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; 11 import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum;
10 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; 12 import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
11 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 13 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
12 import org.apache.ibatis.annotations.Mapper; 14 import org.apache.ibatis.annotations.Mapper;
13 15
  16 +import java.time.LocalDateTime;
14 import java.util.Collection; 17 import java.util.Collection;
15 import java.util.List; 18 import java.util.List;
16 19
@@ -39,18 +42,35 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> { @@ -39,18 +42,35 @@ public interface CrmContractMapper extends BaseMapperX<CrmContractDO> {
39 } 42 }
40 43
41 default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) { 44 default PageResult<CrmContractDO> selectPage(CrmContractPageReqVO pageReqVO, Long userId) {
42 - MPJLambdaWrapperX<CrmContractDO> mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); 45 + MPJLambdaWrapperX<CrmContractDO> query = new MPJLambdaWrapperX<>();
43 // 拼接数据权限的查询条件 46 // 拼接数据权限的查询条件
44 - CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTRACT.getType(), 47 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(),
45 CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); 48 CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE);
46 // 拼接自身的查询条件 49 // 拼接自身的查询条件
47 - mpjLambdaWrapperX.selectAll(CrmContractDO.class) 50 + query.selectAll(CrmContractDO.class)
48 .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) 51 .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo())
49 .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) 52 .likeIfPresent(CrmContractDO::getName, pageReqVO.getName())
50 .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) 53 .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId())
51 .eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId()) 54 .eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId())
  55 + .eqIfPresent(CrmContractDO::getAuditStatus, pageReqVO.getAuditStatus())
52 .orderByDesc(CrmContractDO::getId); 56 .orderByDesc(CrmContractDO::getId);
53 - return selectJoinPage(pageReqVO, CrmContractDO.class, mpjLambdaWrapperX); 57 +
  58 + // Backlog: 即将到期的合同
  59 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
  60 + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
  61 + if (CrmContractPageReqVO.EXPIRY_TYPE_ABOUT_TO_EXPIRE.equals(pageReqVO.getExpiryType())) {
  62 + // 即将到期
  63 + // TODO: @芋艿 需要配置 提前提醒天数
  64 + int REMIND_DAYS = 20;
  65 + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus())
  66 + .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS));
  67 + } else if (CrmContractPageReqVO.EXPIRY_TYPE_EXPIRED.equals(pageReqVO.getExpiryType())) {
  68 + // 已到期
  69 + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus())
  70 + .lt(CrmContractDO::getEndTime, endOfToday);
  71 + }
  72 +
  73 + return selectJoinPage(pageReqVO, CrmContractDO.class, query);
54 } 74 }
55 75
56 default List<CrmContractDO> selectBatchIds(Collection<Long> ids, Long userId) { 76 default List<CrmContractDO> selectBatchIds(Collection<Long> ids, Long userId) {
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java
@@ -45,6 +45,7 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; { @@ -45,6 +45,7 @@ public interface CrmReceivableMapper extends BaseMapperX&lt;CrmReceivableDO&gt; {
45 query.selectAll(CrmReceivableDO.class) 45 query.selectAll(CrmReceivableDO.class)
46 .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) 46 .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo())
47 .eqIfPresent(CrmReceivableDO::getPlanId, pageReqVO.getPlanId()) 47 .eqIfPresent(CrmReceivableDO::getPlanId, pageReqVO.getPlanId())
  48 + .eqIfPresent(CrmReceivableDO::getAuditStatus, pageReqVO.getAuditStatus())
48 .orderByDesc(CrmReceivableDO::getId); 49 .orderByDesc(CrmReceivableDO::getId);
49 return selectJoinPage(pageReqVO, CrmReceivableDO.class, query); 50 return selectJoinPage(pageReqVO, CrmReceivableDO.class, query);
50 } 51 }
yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java
1 package cn.iocoder.yudao.module.crm.dal.mysql.receivable; 1 package cn.iocoder.yudao.module.crm.dal.mysql.receivable;
2 2
  3 +import cn.hutool.core.date.LocalDateTimeUtil;
3 import cn.iocoder.yudao.framework.common.pojo.PageResult; 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
@@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; @@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils;
11 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 12 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
12 import org.apache.ibatis.annotations.Mapper; 13 import org.apache.ibatis.annotations.Mapper;
13 14
  15 +import java.time.LocalDateTime;
14 import java.util.Collection; 16 import java.util.Collection;
15 import java.util.List; 17 import java.util.List;
16 18
@@ -45,6 +47,27 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO @@ -45,6 +47,27 @@ public interface CrmReceivablePlanMapper extends BaseMapperX&lt;CrmReceivablePlanDO
45 .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId()) 47 .eqIfPresent(CrmReceivablePlanDO::getCustomerId, pageReqVO.getCustomerId())
46 .eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId()) 48 .eqIfPresent(CrmReceivablePlanDO::getContractId, pageReqVO.getContractId())
47 .orderByDesc(CrmReceivablePlanDO::getId); 49 .orderByDesc(CrmReceivablePlanDO::getId);
  50 +
  51 + // Backlog: 回款提醒类型
  52 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now());
  53 + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now());
  54 + if (CrmReceivablePlanPageReqVO.REMIND_NEEDED.equals(pageReqVO.getRemindType())) {
  55 + // 待回款
  56 + query.isNull(CrmReceivablePlanDO::getReceivableId)
  57 + .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday)
  58 + .apply("to_days(return_time) <= to_days(now())+ remind_days");
  59 + } else if (CrmReceivablePlanPageReqVO.REMIND_EXPIRED.equals(pageReqVO.getRemindType())) {
  60 + // 已逾期
  61 + query.isNull(CrmReceivablePlanDO::getReceivableId)
  62 + .lt(CrmReceivablePlanDO::getReturnTime, endOfToday);
  63 + } else if (CrmReceivablePlanPageReqVO.REMIND_RECEIVED.equals(pageReqVO.getRemindType())) {
  64 + // 已回款
  65 + query.isNotNull(CrmReceivablePlanDO::getReceivableId)
  66 + .gt(CrmReceivablePlanDO::getReturnTime, beginOfToday)
  67 + .apply("to_days(return_time) <= to_days(now()) + remind_days");
  68 + }
  69 +
  70 +
48 return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query); 71 return selectJoinPage(pageReqVO, CrmReceivablePlanDO.class, query);
49 } 72 }
50 73