package cn.iocoder.yudao.module.crm.dal.mysql.customer; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.util.ObjUtil; 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.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmPermissionUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import java.time.LocalDateTime; import java.util.List; /** * 客户 Mapper * * @author Wanwan */ @Mapper public interface CrmCustomerMapper extends BaseMapperX { default Long selectCountByLockStatusAndOwnerUserId(Boolean lockStatus, Long ownerUserId) { return selectCount(new LambdaUpdateWrapper() .eq(CrmCustomerDO::getLockStatus, lockStatus) .eq(CrmCustomerDO::getOwnerUserId, ownerUserId)); } default Long selectCountByDealStatusAndOwnerUserId(@Nullable Boolean dealStatus, Long ownerUserId) { return selectCount(new LambdaQueryWrapperX() .eqIfPresent(CrmCustomerDO::getDealStatus, dealStatus) .eq(CrmCustomerDO::getOwnerUserId, ownerUserId)); } default int updateOwnerUserIdById(Long id, Long ownerUserId) { return update(new LambdaUpdateWrapper() .eq(CrmCustomerDO::getId, id) .set(CrmCustomerDO::getOwnerUserId, ownerUserId)); } default PageResult selectPage(CrmCustomerPageReqVO pageReqVO, Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 if (Boolean.TRUE.equals(pageReqVO.getPool())) { query.isNull(CrmCustomerDO::getOwnerUserId); } else { CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType()); } // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class) .likeIfPresent(CrmCustomerDO::getName, pageReqVO.getName()) .eqIfPresent(CrmCustomerDO::getMobile, pageReqVO.getMobile()) .eqIfPresent(CrmCustomerDO::getIndustryId, pageReqVO.getIndustryId()) .eqIfPresent(CrmCustomerDO::getLevel, pageReqVO.getLevel()) .eqIfPresent(CrmCustomerDO::getSource, pageReqVO.getSource()) .eqIfPresent(CrmCustomerDO::getFollowUpStatus, pageReqVO.getFollowUpStatus()); // backlog 查询 if (ObjUtil.isNotNull(pageReqVO.getContactStatus())) { Assert.isNull(pageReqVO.getPool(), "pool 必须是 null"); LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); } else if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_EXPIRED)) { // 已逾期 query.lt(CrmCustomerDO::getContactNextTime, beginOfToday); } else if (pageReqVO.getContactStatus().equals(CrmCustomerPageReqVO.CONTACT_ALREADY)) { // 已联系 query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday); } else { throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus()); } } return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } default CrmCustomerDO selectByCustomerName(String name) { return selectOne(CrmCustomerDO::getName, name); } default PageResult selectPutPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfig, Long ownerUserId) { final MPJLambdaWrapperX query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfig, ownerUserId); return selectJoinPage(pageReqVO, CrmCustomerDO.class, query.selectAll(CrmCustomerDO.class)); } default Long selectPutPoolRemindCustomerCount(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfig, Long userId) { final MPJLambdaWrapperX query = buildPutPoolRemindCustomerQuery(pageReqVO, poolConfig, userId); return selectCount(query); } private static MPJLambdaWrapperX buildPutPoolRemindCustomerQuery(CrmCustomerPageReqVO pageReqVO, CrmCustomerPoolConfigDO poolConfig, Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType()); // 未锁定 + 未成交 query.eq(CrmCustomerDO::getLockStatus, false).eq(CrmCustomerDO::getDealStatus, false); // 情况一:未成交提醒日期区间 Integer dealExpireDays = poolConfig.getDealExpireDays(); LocalDateTime startDealRemindTime = LocalDateTime.now().minusDays(dealExpireDays); LocalDateTime endDealRemindTime = LocalDateTime.now() .minusDays(Math.max(dealExpireDays - poolConfig.getNotifyDays(), 0)); // 情况二:未跟进提醒日期区间 Integer contactExpireDays = poolConfig.getContactExpireDays(); LocalDateTime startContactRemindTime = LocalDateTime.now().minusDays(contactExpireDays); LocalDateTime endContactRemindTime = LocalDateTime.now() .minusDays(Math.max(contactExpireDays - poolConfig.getNotifyDays(), 0)); query.and(q -> { // 情况一:成交超时提醒 q.between(CrmCustomerDO::getOwnerTime, startDealRemindTime, endDealRemindTime) // 情况二:跟进超时提醒 .or(w -> w.between(CrmCustomerDO::getOwnerTime, startContactRemindTime, endContactRemindTime) .and(p -> p.between(CrmCustomerDO::getContactLastTime, startContactRemindTime, endContactRemindTime) .or().isNull(CrmCustomerDO::getContactLastTime))); }); return query; } /** * 获得需要过期到公海的客户列表 * * @return 客户列表 */ default List selectListByAutoPool(CrmCustomerPoolConfigDO poolConfig) { LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.gt(CrmCustomerDO::getOwnerUserId, 0); // 未锁定 + 未成交 query.eq(CrmCustomerDO::getLockStatus, false).eq(CrmCustomerDO::getDealStatus, false); // 已经超时 LocalDateTime dealExpireTime = LocalDateTime.now().minusDays(poolConfig.getDealExpireDays()); LocalDateTime contactExpireTime = LocalDateTime.now().minusDays(poolConfig.getContactExpireDays()); query.and(q -> { // 情况一:成交超时 q.lt(CrmCustomerDO::getOwnerTime, dealExpireTime) // 情况二:跟进超时 .or(w -> w.lt(CrmCustomerDO::getOwnerTime, contactExpireTime) .and(p -> p.lt(CrmCustomerDO::getContactLastTime, contactExpireTime) .or().isNull(CrmCustomerDO::getContactLastTime))); }); return selectList(query); } default Long selectCountByTodayContact(Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, ownerUserId, CrmSceneTypeEnum.OWNER.getType()); // 今天需联系 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); return selectCount(query); } default Long selectCountByFollow(Long ownerUserId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 我负责的 + 非公海 CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, ownerUserId, CrmSceneTypeEnum.OWNER.getType()); // 未跟进 query.eq(CrmClueDO::getFollowUpStatus, false); return selectCount(query); } }