Commit b245c23a44ca3544ea7b0eadc1a6fa45858c45b4

Authored by 张志伟
1 parent 8cd965a1

feature(*): 续保跟进调整

- 续保跟进调整
fw-valhalla-rpc/src/main/java/cn/fw/valhalla/rpc/shirasawa/ShirasawaRpcService.java
... ... @@ -7,6 +7,7 @@ import cn.fw.shirasawa.sdk.param.FollowChangeUserDTO;
7 7 import cn.fw.shirasawa.sdk.param.FollowGenerateDTO;
8 8 import cn.fw.shirasawa.sdk.param.TaskCompleteDTO;
9 9 import cn.fw.shirasawa.sdk.param.TerminationDTO;
  10 +import cn.fw.valhalla.common.utils.DateUtil;
10 11 import cn.fw.valhalla.rpc.shirasawa.dto.ClueStopDTO;
11 12 import cn.fw.valhalla.rpc.shirasawa.dto.FollowInitDTO;
12 13 import lombok.RequiredArgsConstructor;
... ... @@ -14,6 +15,7 @@ import lombok.extern.slf4j.Slf4j;
14 15 import org.springframework.beans.BeanUtils;
15 16 import org.springframework.stereotype.Service;
16 17  
  18 +import java.time.LocalDate;
17 19 import java.util.Objects;
18 20 import java.util.Optional;
19 21  
... ... @@ -87,19 +89,36 @@ public class ShirasawaRpcService {
87 89 * 变更跟进人数据
88 90 *
89 91 * @param dto
  92 + * @param nextTime
90 93 */
91   - public void changeFollowData(final FollowInitDTO dto) {
  94 + public void changeFollowData(final FollowInitDTO dto, LocalDate nextTime) {
92 95 FollowChangeUserDTO followChangeUserDTO = new FollowChangeUserDTO();
93 96 followChangeUserDTO.setType(dto.getType());
94 97 followChangeUserDTO.setBusinessType(dto.getBusinessType());
95 98 followChangeUserDTO.setDetailId(dto.getDetailId());
96 99 followChangeUserDTO.setShopId(dto.getShopId());
97 100 followChangeUserDTO.setUserId(dto.getUserId());
  101 + followChangeUserDTO.setRecommendNextTime(DateUtil.localDate2Date(nextTime));
98 102 final Message<Void> msg = followApiService.taskChangeUser(followChangeUserDTO);
99 103 BV.isTrue(msg.isSuccess(), msg::getResult);
100 104 }
101 105  
102 106 /**
  107 + * 变更下次跟进时间
  108 + *
  109 + * @param dataType dataType
  110 + * @param detailId detailId
  111 + * @param nextTime nextTime
  112 + */
  113 + public void updateNextTime(Integer dataType,
  114 + String detailId,
  115 + LocalDate nextTime) {
  116 + long time = DateUtil.localDate2Date(nextTime).getTime();
  117 + final Message<Void> msg = followApiService.updateFollowNextTime(dataType, detailId, time);
  118 + BV.isTrue(msg.isSuccess(), msg::getResult);
  119 + }
  120 +
  121 + /**
103 122 * 查询是否有未完成的待办
104 123 *
105 124 * @param userId
... ...
fw-valhalla-sdk/pom.xml
... ... @@ -37,8 +37,9 @@
37 37 <scope>provided</scope>
38 38 </dependency>
39 39 <dependency>
40   - <groupId>cn.fw</groupId>
41   - <artifactId>fw-common-data</artifactId>
  40 + <groupId>com.baomidou</groupId>
  41 + <artifactId>mybatis-plus-extension</artifactId>
  42 + <scope>provided</scope>
42 43 </dependency>
43 44 </dependencies>
44 45  
... ...
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/LeaveNeedDoBizService.java
... ... @@ -23,6 +23,7 @@ import cn.fw.valhalla.domain.enums.*;
23 23 import cn.fw.valhalla.domain.query.LeaveQueryVO;
24 24 import cn.fw.valhalla.domain.vo.DistributableVO;
25 25 import cn.fw.valhalla.domain.vo.LeaveNeedDoVO;
  26 +import cn.fw.valhalla.domain.vo.setting.SettingVO;
26 27 import cn.fw.valhalla.rpc.backlog.TodoRpcService;
27 28 import cn.fw.valhalla.rpc.backlog.dto.BackLogItemDTO;
28 29 import cn.fw.valhalla.rpc.ehr.EhrRpcService;
... ... @@ -33,7 +34,9 @@ import cn.fw.valhalla.rpc.erp.dto.UserInfoDTO;
33 34 import cn.fw.valhalla.rpc.erp.dto.UserRoleDataRangeDTO;
34 35 import cn.fw.valhalla.rpc.oop.OopService;
35 36 import cn.fw.valhalla.rpc.oop.dto.ShopDTO;
  37 +import cn.fw.valhalla.rpc.shirasawa.ShirasawaRpcService;
36 38 import cn.fw.valhalla.service.bus.follow.FollowBizService;
  39 +import cn.fw.valhalla.service.bus.setting.SettingBizService;
37 40 import cn.fw.valhalla.service.data.*;
38 41 import com.alibaba.fastjson.JSONObject;
39 42 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
... ... @@ -52,6 +55,7 @@ import java.util.*;
52 55 import java.util.stream.Collectors;
53 56  
54 57 import static cn.fw.common.businessvalidator.Validator.BV;
  58 +import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID;
55 59  
56 60 /**
57 61 * @author : kurisu
... ... @@ -75,7 +79,8 @@ public class LeaveNeedDoBizService {
75 79 private final FollowClueService followClueService;
76 80 private final ClueTaskService clueTaskService;
77 81 private final CustAfterDistProducer custAfterDistProducer;
78   -
  82 + private final ShirasawaRpcService shirasawaRpcService;
  83 + private final SettingBizService settingBizService;
79 84 /**
80 85 * Redis工具
81 86 */
... ... @@ -215,16 +220,35 @@ public class LeaveNeedDoBizService {
215 220 if (Objects.isNull(leaveNeedDo)) {
216 221 return;
217 222 }
  223 +
218 224 List<ClueTask> list = clueTaskService.list(Wrappers.<ClueTask>lambdaQuery()
219 225 .in(ClueTask::getType, FollowTypeEnum.FM, FollowTypeEnum.RM)
220 226 .eq(ClueTask::getState, TaskStateEnum.ONGOING)
221 227 .eq(ClueTask::getFollowUser, leaveNeedDo.getUserId())
222 228 );
223   - if (CollectionUtils.isEmpty(list)) {
224   - return;
  229 + if (!CollectionUtils.isEmpty(list)) {
  230 + for (ClueTask task : list) {
  231 + followBizService.roleChangeEndTask(task);
  232 + }
225 233 }
226   - for (ClueTask task : list) {
227   - followBizService.roleChangeEndTask(task);
  234 +
  235 + List<ClueTask> irlist = clueTaskService.list(Wrappers.<ClueTask>lambdaQuery()
  236 + .eq(ClueTask::getType, FollowTypeEnum.IR)
  237 + .eq(ClueTask::getState, TaskStateEnum.ONGOING)
  238 + .eq(ClueTask::getFollowUser, leaveNeedDo.getUserId())
  239 + );
  240 +
  241 + if (!CollectionUtils.isEmpty(irlist)) {
  242 + Long groupId = irlist.get(0).getGroupId();
  243 + Optional<SettingVO> settingVO = settingBizService.querySettingByType(FollowTypeEnum.IR, SettingTypeEnum.MODE, groupId, COMMON_BRAND_ID);
  244 + // 模式 1、续保角色 2、续保角色+服务接待/新车销售
  245 + final int mode = settingVO.map(SettingVO::getDetailValue).orElse(1);
  246 + if (mode == 1) {
  247 + return;
  248 + }
  249 + for (ClueTask task : irlist) {
  250 + followBizService.roleChangeEndTask(task);
  251 + }
228 252 }
229 253 }
230 254  
... ... @@ -245,8 +269,15 @@ public class LeaveNeedDoBizService {
245 269 if (CollectionUtils.isEmpty(list)) {
246 270 return;
247 271 }
  272 + Long groupId = list.get(0).getGroupId();
  273 + Optional<SettingVO> settingVO = settingBizService.querySettingByType(FollowTypeEnum.IR, SettingTypeEnum.MODE, groupId, COMMON_BRAND_ID);
  274 + // 模式 1、续保角色 2、续保角色+服务接待/新车销售
  275 + final int mode = settingVO.map(SettingVO::getDetailValue).orElse(1);
248 276  
249 277 for (ClueTask task : list) {
  278 + if (mode != 1) {
  279 + shirasawaRpcService.updateNextTime(FollowTypeEnum.IR.getValue(), String.valueOf(task.getClueId()), task.getDeadline().plusDays(1L).toLocalDate());
  280 + }
250 281 followBizService.roleChangeEndTask(task);
251 282 }
252 283 }
... ...
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/AbstractFollowStrategy.java
... ... @@ -734,14 +734,10 @@ public abstract class AbstractFollowStrategy implements FollowStrategy {
734 734 redistributionTask.setRpcSuccess(Boolean.FALSE);
735 735 clueTaskService.save(redistributionTask);
736 736 FollowInitDTO followInitDTO = creteRedistributionFollowInitDTO(clue, redistributionTask);
737   - shirasawaRpcService.changeFollowData(followInitDTO);
  737 + shirasawaRpcService.changeFollowData(followInitDTO, redistributionTask.getBeginTime().toLocalDate());
738 738 followClueService.updateById(clue);
739 739 }
740 740  
741   - protected String generateAddKey() {
742   - return String.format("%s:%s", getClueChangeKeyPrefix(), "ADD");
743   - }
744   -
745 741 protected String generateStopKey() {
746 742 return String.format("%s:%s", getClueChangeKeyPrefix(), "STOP");
747 743 }
... ...
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/FollowStrategy.java
... ... @@ -70,7 +70,7 @@ public interface FollowStrategy {
70 70  
71 71 /**
72 72 * [角色变动]结束任务
73   - * // todo 续保跟进截止后战败mode2时档案
  73 + *
74 74 * @param task
75 75 */
76 76 @Transactional(rollbackFor = Exception.class)
... ...
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/impl/IRFollowStrategy.java
... ... @@ -150,6 +150,9 @@ public class IRFollowStrategy extends AbstractFollowStrategy {
150 150 Long clueId = task.getClueId();
151 151 FollowClue clue = followClueService.getById(clueId);
152 152 BV.notNull(clue, () -> "跟进线索不存在: " + clueId);
  153 + Customer customer = customerService.queryByFrameNo(clue.getVin(), clue.getGroupId());
  154 + Long adviserId = Optional.ofNullable(customer).map(Customer::getAdviserId).orElse(null);
  155 +
153 156 Optional<SettingVO> settingVO = settingBizService.querySettingByType(getFollowType(), SettingTypeEnum.MODE, clue.getGroupId(), COMMON_BRAND_ID);
154 157 // 模式 1、续保角色 2、续保角色+服务接待/新车销售
155 158 final int mode = settingVO.map(SettingVO::getDetailValue).orElse(1);
... ... @@ -165,17 +168,24 @@ public class IRFollowStrategy extends AbstractFollowStrategy {
165 168 PostUserDTO userDTO = userByRole.get(randomIndex);
166 169 createSecondaryTask(clue, userDTO.getUserId());
167 170 } else {
168   - Customer customer = customerService.queryByFrameNo(clue.getVin(), clue.getGroupId());
169   - Long adviserId = Optional.ofNullable(customer).map(Customer::getAdviserId).orElse(null);
170 171 if (Objects.isNull(adviserId)) {
171   - boolean rpcSucess = rpcStopTask(task);
172   - if (!rpcSucess) {
173   - log.info("跟进系统终止任务失败");
  172 + List<PostUserDTO> userByRole = userService.getShopRolesUser(task.getFollowShop(), RoleCode.XBGJ, RoleCode.FWGW);
  173 + BV.isNotEmpty(userByRole, () -> String.format("该门店[mode: %s]没有【跟进】人员", mode));
  174 + int randomIndex = new Random().nextInt(userByRole.size());
  175 + PostUserDTO userDTO = userByRole.get(randomIndex);
  176 + adviserId = userDTO.getUserId();
  177 + } else {
  178 + if (task.getFollowUser().equals(adviserId)) {
  179 + return;
174 180 }
175   - task.setRpcSuccess(rpcSucess);
176   - clueTaskService.updateById(task);
177   - return;
178 181 }
  182 +
  183 + boolean rpcSucess = rpcStopTask(task);
  184 + if (!rpcSucess) {
  185 + log.info("跟进系统终止任务失败");
  186 + }
  187 + task.setRpcSuccess(rpcSucess);
  188 + clueTaskService.updateById(task);
179 189 this.createSecondaryTask(clue, adviserId);
180 190 }
181 191 }
... ... @@ -201,10 +211,12 @@ public class IRFollowStrategy extends AbstractFollowStrategy {
201 211 Optional<SettingVO> settingVO = settingBizService.querySettingByType(getFollowType(), SettingTypeEnum.MODE, clue.getGroupId(), COMMON_BRAND_ID);
202 212 // 模式 1、续保角色 2、续保角色+服务接待/新车销售
203 213 final int mode = settingVO.map(SettingVO::getDetailValue).orElse(1);
204   - CustomerDetailVO detailByVin = customerBizService.getDetailByVin(clue.getVin(), clue.getGroupId());
205   - Long aLong = Optional.ofNullable(detailByVin).map(CustomerDetailVO::getAdviserId).orElse(null);
206   - if (task.getFollowUser().equals(aLong)) {
207   - customerBizService.abandon(detailByVin.getId(), "主动放弃");
  214 + if (mode != 1) {
  215 + CustomerDetailVO detailByVin = customerBizService.getDetailByVin(clue.getVin(), clue.getGroupId());
  216 + Long aLong = Optional.ofNullable(detailByVin).map(CustomerDetailVO::getAdviserId).orElse(null);
  217 + if (task.getFollowUser().equals(aLong)) {
  218 + customerBizService.abandon(detailByVin.getId(), "主动放弃");
  219 + }
208 220 }
209 221 }
210 222  
... ...
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/pub/PubDistributeBizService.java
1 1 package cn.fw.valhalla.service.bus.pub;
2 2  
  3 +import cn.fw.valhalla.common.constant.RoleCode;
3 4 import cn.fw.valhalla.common.utils.DateUtil;
4 5 import cn.fw.valhalla.domain.db.customer.AffiliationRecord;
5 6 import cn.fw.valhalla.domain.db.customer.Customer;
  7 +import cn.fw.valhalla.domain.db.follow.ClueTask;
6 8 import cn.fw.valhalla.domain.db.follow.FollowClue;
7 9 import cn.fw.valhalla.domain.db.pool.StammkundePool;
8 10 import cn.fw.valhalla.domain.db.pub.PubCluePool;
9 11 import cn.fw.valhalla.domain.db.pub.PubStandStaffInfo;
10 12 import cn.fw.valhalla.domain.enums.*;
11 13 import cn.fw.valhalla.domain.vo.setting.SettingVO;
  14 +import cn.fw.valhalla.rpc.erp.UserService;
  15 +import cn.fw.valhalla.rpc.erp.dto.UserRoleDataRangeDTO;
12 16 import cn.fw.valhalla.rpc.mkt.MktRpcService;
13 17 import cn.fw.valhalla.rpc.mkt.dto.QualificationDTO;
14 18 import cn.fw.valhalla.rpc.oop.OopService;
... ... @@ -45,7 +49,9 @@ import java.util.stream.Collectors;
45 49 @Slf4j
46 50 public class PubDistributeBizService {
47 51 private final OopService oopService;
  52 + private final UserService userService;
48 53 private final FollowClueService followClueService;
  54 + private final ClueTaskService clueTaskService;
49 55 private final ShirasawaRpcService shirasawaRpcService;
50 56 private final PublicPoolService publicPoolService;
51 57 private final CustomerService customerService;
... ... @@ -211,7 +217,7 @@ public class PubDistributeBizService {
211 217 PubStandType standType = Optional.ofNullable(staffInfo.getStandType()).orElse(PubStandType.PUB);
212 218 switch (standType) {
213 219 case PUB:
214   - vinArr = vinList.subList(0, count);
  220 + vinArr = determinePub(vinList, staffInfo, count);
215 221 break;
216 222 case ACTIVITY:
217 223 vinArr = determineMkt(vinList, staffInfo, count);
... ... @@ -223,6 +229,51 @@ public class PubDistributeBizService {
223 229 }
224 230  
225 231 /**
  232 + * 分配档案
  233 + *
  234 + * @param vinList
  235 + * @param staffInfo
  236 + * @param count
  237 + * @return
  238 + */
  239 + private List<String> determinePub(List<String> vinList, PubStandStaffInfo staffInfo, int count) {
  240 + List<String> list = new ArrayList<>();
  241 + for (String vin : vinList) {
  242 + if (list.size() >= count) {
  243 + break;
  244 + }
  245 + Customer customer = customerService.queryByFrameNo(vin, staffInfo.getGroupId());
  246 + if (Objects.isNull(customer)) {
  247 + continue;
  248 + }
  249 + boolean hasDefeat = affiliationRecordService.count(Wrappers.<AffiliationRecord>lambdaQuery()
  250 + .eq(AffiliationRecord::getCustomerId, customer.getId())
  251 + .eq(AffiliationRecord::getOriginUserId, staffInfo.getStaffId())
  252 + .ge(AffiliationRecord::getDefeatTime, DateUtil.localDate2Date(LocalDate.now().minusMonths(12L)))
  253 + ) > 1;
  254 + if (hasDefeat) {
  255 + continue;
  256 + }
  257 + FollowClue clue = followClueService.getOne(Wrappers.<FollowClue>lambdaQuery()
  258 + .eq(FollowClue::getVin, vin)
  259 + .eq(FollowClue::getClueType, FollowTypeEnum.IR)
  260 + .eq(FollowClue::getClueState, ClueStatusEnum.ONGOING)
  261 + , Boolean.FALSE
  262 + );
  263 + if (Objects.nonNull(clue)) {
  264 + ClueTask clueTask = clueTaskService.queryOngoingTaskByClueId(clue.getId());
  265 + Long followUser = clueTask.getFollowUser();
  266 + List<UserRoleDataRangeDTO> roleDataRange = userService.getUserRoleDataRange(followUser, RoleCode.FWGW);
  267 + if (!staffInfo.getStaffId().equals(followUser) && !CollectionUtils.isEmpty(roleDataRange)) {
  268 + continue;
  269 + }
  270 + }
  271 + list.add(vin);
  272 + }
  273 + return list;
  274 + }
  275 +
  276 + /**
226 277 * 查询档案用户能否参与活动
227 278 *
228 279 * @param vinList
... ... @@ -233,7 +284,7 @@ public class PubDistributeBizService {
233 284 private List<String> determineMkt(List<String> vinList, PubStandStaffInfo staffInfo, int count) {
234 285 List<String> list = new ArrayList<>();
235 286 for (String vin : vinList) {
236   - if (list.size() == count) {
  287 + if (list.size() >= count) {
237 288 break;
238 289 }
239 290 Customer customer = customerService.queryByFrameNo(vin, staffInfo.getGroupId());
... ... @@ -243,7 +294,7 @@ public class PubDistributeBizService {
243 294 boolean hasDefeat = affiliationRecordService.count(Wrappers.<AffiliationRecord>lambdaQuery()
244 295 .eq(AffiliationRecord::getCustomerId, customer.getId())
245 296 .eq(AffiliationRecord::getOriginUserId, staffInfo.getStaffId())
246   - .ge(AffiliationRecord::getDefeatTime, DateUtil.localDate2Date(LocalDate.now().minusMonths(6L)))
  297 + .ge(AffiliationRecord::getDefeatTime, DateUtil.localDate2Date(LocalDate.now().minusMonths(12L)))
247 298 ) > 1;
248 299 if (hasDefeat) {
249 300 continue;
... ...