|
|
@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
|
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
|
|
import com.crm.base.domain.exception.BusinessErrorException; |
|
|
import com.crm.base.domain.exception.BusinessErrorException; |
|
|
|
|
|
import com.crm.base.domain.result.PageResult; |
|
|
|
|
|
import com.crm.opportunity.domain.entity.Opportunity; |
|
|
import com.crm.opportunity.domain.entity.OpportunityAttachment; |
|
|
import com.crm.opportunity.domain.entity.OpportunityAttachment; |
|
|
import com.crm.opportunity.domain.entity.OpportunityCustomer; |
|
|
import com.crm.opportunity.domain.entity.OpportunityCustomer; |
|
|
import com.crm.opportunity.domain.entity.OpportunityFollow; |
|
|
import com.crm.opportunity.domain.entity.OpportunityFollow; |
|
|
@ -13,6 +15,7 @@ import com.crm.opportunity.domain.entity.OpportunityTeam; |
|
|
import com.crm.opportunity.mapper.OpportunityAttachmentMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityAttachmentMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityCustomerMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityCustomerMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityFollowMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityFollowMapper; |
|
|
|
|
|
import com.crm.opportunity.mapper.OpportunityMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityOplogMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityOplogMapper; |
|
|
import com.crm.opportunity.mapper.OpportunitySiteSurveyMapper; |
|
|
import com.crm.opportunity.mapper.OpportunitySiteSurveyMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityTeamMapper; |
|
|
import com.crm.opportunity.mapper.OpportunityTeamMapper; |
|
|
@ -22,6 +25,7 @@ import org.springframework.stereotype.Service; |
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
import org.springframework.util.StringUtils; |
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
|
|
import java.time.LocalDateTime; |
|
|
import java.util.List; |
|
|
import java.util.List; |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
@ -31,12 +35,16 @@ import java.util.List; |
|
|
@RequiredArgsConstructor |
|
|
@RequiredArgsConstructor |
|
|
public class OpportunitySubServiceImpl implements IOpportunitySubService { |
|
|
public class OpportunitySubServiceImpl implements IOpportunitySubService { |
|
|
|
|
|
|
|
|
|
|
|
/** 跟进附件每条记录最多关联附件数(规格约定:10 个) */ |
|
|
|
|
|
private static final int FOLLOW_ATTACHMENT_MAX = 10; |
|
|
|
|
|
|
|
|
private final OpportunityCustomerMapper customerMapper; |
|
|
private final OpportunityCustomerMapper customerMapper; |
|
|
private final OpportunityFollowMapper followMapper; |
|
|
private final OpportunityFollowMapper followMapper; |
|
|
private final OpportunitySiteSurveyMapper siteSurveyMapper; |
|
|
private final OpportunitySiteSurveyMapper siteSurveyMapper; |
|
|
private final OpportunityAttachmentMapper attachmentMapper; |
|
|
private final OpportunityAttachmentMapper attachmentMapper; |
|
|
private final OpportunityTeamMapper teamMapper; |
|
|
private final OpportunityTeamMapper teamMapper; |
|
|
private final OpportunityOplogMapper oplogMapper; |
|
|
private final OpportunityOplogMapper oplogMapper; |
|
|
|
|
|
private final OpportunityMapper oppMapper; |
|
|
|
|
|
|
|
|
// ==================== 客户 ====================
|
|
|
// ==================== 客户 ====================
|
|
|
|
|
|
|
|
|
@ -51,12 +59,13 @@ public class OpportunitySubServiceImpl implements IOpportunitySubService { |
|
|
// ==================== 跟进 ====================
|
|
|
// ==================== 跟进 ====================
|
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public Page<OpportunityFollow> pageFollows(Long oppId, long pageNum, long pageSize) { |
|
|
public PageResult<OpportunityFollow> pageFollows(Long oppId, long pageNum, long pageSize) { |
|
|
return followMapper.selectPage(new Page<>(pageNum, pageSize), |
|
|
Page<OpportunityFollow> page = followMapper.selectPage(new Page<>(pageNum, pageSize), |
|
|
new LambdaQueryWrapper<OpportunityFollow>() |
|
|
new LambdaQueryWrapper<OpportunityFollow>() |
|
|
.eq(OpportunityFollow::getOppId, oppId) |
|
|
.eq(OpportunityFollow::getOppId, oppId) |
|
|
.eq(OpportunityFollow::getDeleteKey, 0L) |
|
|
.eq(OpportunityFollow::getDeleteKey, 0L) |
|
|
.orderByDesc(OpportunityFollow::getFollowTime)); |
|
|
.orderByDesc(OpportunityFollow::getFollowTime)); |
|
|
|
|
|
return new PageResult<>(page); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
@ -69,6 +78,17 @@ public class OpportunitySubServiceImpl implements IOpportunitySubService { |
|
|
if (follow.getCustomerId() == null) throw new BusinessErrorException("关联客户必填"); |
|
|
if (follow.getCustomerId() == null) throw new BusinessErrorException("关联客户必填"); |
|
|
follow.setDeleteKey(0L); |
|
|
follow.setDeleteKey(0L); |
|
|
followMapper.insert(follow); |
|
|
followMapper.insert(follow); |
|
|
|
|
|
|
|
|
|
|
|
// 刷新回收锚点:last_valid_follow_time = max(原值, 本次跟进时间)
|
|
|
|
|
|
Opportunity opp = oppMapper.selectById(follow.getOppId()); |
|
|
|
|
|
if (opp != null) { |
|
|
|
|
|
LocalDateTime followAt = follow.getFollowTime(); |
|
|
|
|
|
if (opp.getLastValidFollowTime() == null || followAt.isAfter(opp.getLastValidFollowTime())) { |
|
|
|
|
|
oppMapper.update(null, new LambdaUpdateWrapper<Opportunity>() |
|
|
|
|
|
.eq(Opportunity::getId, follow.getOppId()) |
|
|
|
|
|
.set(Opportunity::getLastValidFollowTime, followAt)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
return follow.getId(); |
|
|
return follow.getId(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -81,16 +101,32 @@ public class OpportunitySubServiceImpl implements IOpportunitySubService { |
|
|
.eq(OpportunityFollow::getId, followId) |
|
|
.eq(OpportunityFollow::getId, followId) |
|
|
.set(OpportunityFollow::getDeleteKey, followId) |
|
|
.set(OpportunityFollow::getDeleteKey, followId) |
|
|
.set(OpportunityFollow::getDeleted, 1)); |
|
|
.set(OpportunityFollow::getDeleted, 1)); |
|
|
|
|
|
|
|
|
|
|
|
// 写操作日志:ROW_DELETE
|
|
|
|
|
|
OpportunityOplog log = new OpportunityOplog(); |
|
|
|
|
|
log.setOppId(follow.getOppId()); |
|
|
|
|
|
log.setOpKind("ROW_DELETE"); |
|
|
|
|
|
log.setLogType("ROW_CHANGE"); |
|
|
|
|
|
log.setEntityName("opportunity_follow"); |
|
|
|
|
|
log.setBizRef(follow.getFollowContent() != null |
|
|
|
|
|
? follow.getFollowContent().substring(0, Math.min(50, follow.getFollowContent().length())) |
|
|
|
|
|
: String.valueOf(followId)); |
|
|
|
|
|
log.setOpDesc("删除跟进记录"); |
|
|
|
|
|
log.setOpSource("MANUAL"); |
|
|
|
|
|
log.setOpTime(LocalDateTime.now()); |
|
|
|
|
|
log.setOpUserId(operatorId); |
|
|
|
|
|
oplogMapper.insert(log); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// ==================== 勘察 ====================
|
|
|
// ==================== 勘察 ====================
|
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public Page<OpportunitySiteSurvey> pageSiteSurveys(Long oppId, long pageNum, long pageSize) { |
|
|
public PageResult<OpportunitySiteSurvey> pageSiteSurveys(Long oppId, long pageNum, long pageSize) { |
|
|
return siteSurveyMapper.selectPage(new Page<>(pageNum, pageSize), |
|
|
Page<OpportunitySiteSurvey> page = siteSurveyMapper.selectPage(new Page<>(pageNum, pageSize), |
|
|
new LambdaQueryWrapper<OpportunitySiteSurvey>() |
|
|
new LambdaQueryWrapper<OpportunitySiteSurvey>() |
|
|
.eq(OpportunitySiteSurvey::getOppId, oppId) |
|
|
.eq(OpportunitySiteSurvey::getOppId, oppId) |
|
|
.orderByDesc(OpportunitySiteSurvey::getSurveyDate)); |
|
|
.orderByDesc(OpportunitySiteSurvey::getSurveyDate)); |
|
|
|
|
|
return new PageResult<>(page); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
@ -131,6 +167,16 @@ public class OpportunitySubServiceImpl implements IOpportunitySubService { |
|
|
public Long addAttachment(OpportunityAttachment attachment) { |
|
|
public Long addAttachment(OpportunityAttachment attachment) { |
|
|
if (attachment.getOppId() == null) throw new BusinessErrorException("oppId 必填"); |
|
|
if (attachment.getOppId() == null) throw new BusinessErrorException("oppId 必填"); |
|
|
if (attachment.getFileId() == null) throw new BusinessErrorException("fileId 必填"); |
|
|
if (attachment.getFileId() == null) throw new BusinessErrorException("fileId 必填"); |
|
|
|
|
|
// 跟进附件上限校验
|
|
|
|
|
|
if ("FOLLOW_UP".equals(attachment.getBizType()) && attachment.getBizId() != null) { |
|
|
|
|
|
long count = attachmentMapper.selectCount(new LambdaQueryWrapper<OpportunityAttachment>() |
|
|
|
|
|
.eq(OpportunityAttachment::getBizType, "FOLLOW_UP") |
|
|
|
|
|
.eq(OpportunityAttachment::getBizId, attachment.getBizId()) |
|
|
|
|
|
.eq(OpportunityAttachment::getDeleteKey, 0L)); |
|
|
|
|
|
if (count >= FOLLOW_ATTACHMENT_MAX) { |
|
|
|
|
|
throw new BusinessErrorException("跟进附件最多 " + FOLLOW_ATTACHMENT_MAX + " 个"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
attachment.setDeleteKey(0L); |
|
|
attachment.setDeleteKey(0L); |
|
|
attachmentMapper.insert(attachment); |
|
|
attachmentMapper.insert(attachment); |
|
|
return attachment.getId(); |
|
|
return attachment.getId(); |
|
|
@ -160,10 +206,11 @@ public class OpportunitySubServiceImpl implements IOpportunitySubService { |
|
|
// ==================== 操作日志 ====================
|
|
|
// ==================== 操作日志 ====================
|
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
public Page<OpportunityOplog> pageOplogs(Long oppId, long pageNum, long pageSize) { |
|
|
public PageResult<OpportunityOplog> pageOplogs(Long oppId, long pageNum, long pageSize) { |
|
|
return oplogMapper.selectPage(new Page<>(pageNum, pageSize), |
|
|
Page<OpportunityOplog> page = oplogMapper.selectPage(new Page<>(pageNum, pageSize), |
|
|
new LambdaQueryWrapper<OpportunityOplog>() |
|
|
new LambdaQueryWrapper<OpportunityOplog>() |
|
|
.eq(OpportunityOplog::getOppId, oppId) |
|
|
.eq(OpportunityOplog::getOppId, oppId) |
|
|
.orderByDesc(OpportunityOplog::getOpTime)); |
|
|
.orderByDesc(OpportunityOplog::getOpTime)); |
|
|
|
|
|
return new PageResult<>(page); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|