Commit 2a40e3f8ea2c5f03838db503c5a92abe7a820010
1 parent
a50f539c
feature(*): 续保跟进调整
- 续保跟进调整
Showing
32 changed files
with
318 additions
and
323 deletions
fw-valhalla-rpc/src/main/java/cn/fw/valhalla/rpc/shirasawa/ShirasawaRpcService.java
... | ... | @@ -3,6 +3,7 @@ package cn.fw.valhalla.rpc.shirasawa; |
3 | 3 | import cn.fw.data.base.domain.common.Message; |
4 | 4 | import cn.fw.shirasawa.sdk.api.FollowApiService; |
5 | 5 | import cn.fw.shirasawa.sdk.enums.BusinessTypeEnum; |
6 | +import cn.fw.shirasawa.sdk.param.FollowChangeUserDTO; | |
6 | 7 | import cn.fw.shirasawa.sdk.param.FollowGenerateDTO; |
7 | 8 | import cn.fw.shirasawa.sdk.param.TaskCompleteDTO; |
8 | 9 | import cn.fw.shirasawa.sdk.param.TerminationDTO; |
... | ... | @@ -83,6 +84,22 @@ public class ShirasawaRpcService { |
83 | 84 | } |
84 | 85 | |
85 | 86 | /** |
87 | + * 变更跟进人数据 | |
88 | + * | |
89 | + * @param dto | |
90 | + */ | |
91 | + public void changeFollowData(final FollowInitDTO dto) { | |
92 | + FollowChangeUserDTO followChangeUserDTO = new FollowChangeUserDTO(); | |
93 | + followChangeUserDTO.setType(dto.getType()); | |
94 | + followChangeUserDTO.setBusinessType(dto.getBusinessType()); | |
95 | + followChangeUserDTO.setDetailId(dto.getDetailId()); | |
96 | + followChangeUserDTO.setShopId(dto.getShopId()); | |
97 | + followChangeUserDTO.setUserId(dto.getUserId()); | |
98 | + final Message<Void> msg = followApiService.taskChangeUser(followChangeUserDTO); | |
99 | + BV.isTrue(msg.isSuccess(), msg::getResult); | |
100 | + } | |
101 | + | |
102 | + /** | |
86 | 103 | * 查询是否有未完成的待办 |
87 | 104 | * |
88 | 105 | * @param userId | ... | ... |
fw-valhalla-sdk/pom.xml
fw-valhalla-sdk/src/main/java/cn/fw/valhalla/sdk/result/RenewalSwitchMQ.java
0 → 100644
1 | +package cn.fw.valhalla.sdk.result; | |
2 | + | |
3 | +import lombok.AllArgsConstructor; | |
4 | +import lombok.Data; | |
5 | +import lombok.NoArgsConstructor; | |
6 | + | |
7 | +import java.util.Date; | |
8 | + | |
9 | +/** | |
10 | + * 续保跟进切换MQ | |
11 | + * | |
12 | + * @author : kurisu | |
13 | + * @version : 2.0 | |
14 | + * @className : RenewalSwitchMQ | |
15 | + * @description : 续保跟进切换MQ | |
16 | + * @date : 2023-04-11 11:41 | |
17 | + */ | |
18 | +@Data | |
19 | +@AllArgsConstructor | |
20 | +@NoArgsConstructor | |
21 | +public class RenewalSwitchMQ { | |
22 | + public final static String TOPIC = "valhalla_renewal_switch"; | |
23 | + /** | |
24 | + * 对应跟进系统的跟进类型 | |
25 | + * 可以直接使用次值 | |
26 | + */ | |
27 | + private Integer followType; | |
28 | + /** | |
29 | + * 车架号 | |
30 | + */ | |
31 | + private String vin; | |
32 | + /** | |
33 | + * 续保跟进最后截止时间 | |
34 | + */ | |
35 | + private Date deadline; | |
36 | + | |
37 | +} | ... | ... |
fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/ClueChangeNoticeTask.java
1 | 1 | package cn.fw.valhalla.controller.task; |
2 | 2 | |
3 | -import cn.fw.valhalla.component.ClueChangeProducer; | |
3 | +import cn.fw.valhalla.component.producer.ClueChangeProducer; | |
4 | +import cn.fw.valhalla.component.producer.RenewalSwitchProducer; | |
4 | 5 | import cn.fw.valhalla.domain.db.follow.FollowClue; |
5 | 6 | import cn.fw.valhalla.domain.enums.FollowTypeEnum; |
6 | 7 | import cn.fw.valhalla.sdk.enums.CustomerFollowTypeEnum; |
... | ... | @@ -11,12 +12,15 @@ import lombok.extern.slf4j.Slf4j; |
11 | 12 | import org.springframework.beans.factory.annotation.Autowired; |
12 | 13 | import org.springframework.beans.factory.annotation.Value; |
13 | 14 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
15 | +import org.springframework.data.redis.core.BoundSetOperations; | |
14 | 16 | import org.springframework.data.redis.core.StringRedisTemplate; |
15 | 17 | import org.springframework.scheduling.annotation.Scheduled; |
16 | 18 | import org.springframework.stereotype.Component; |
19 | +import org.springframework.util.CollectionUtils; | |
17 | 20 | |
21 | +import java.util.ArrayList; | |
22 | +import java.util.List; | |
18 | 23 | import java.util.Objects; |
19 | -import java.util.concurrent.CompletableFuture; | |
20 | 24 | |
21 | 25 | /** |
22 | 26 | * 线索变更后的通知事件 |
... | ... | @@ -32,6 +36,7 @@ import java.util.concurrent.CompletableFuture; |
32 | 36 | @ConditionalOnProperty(prefix = "task", name = "switch", havingValue = "on") |
33 | 37 | public class ClueChangeNoticeTask { |
34 | 38 | private final ClueChangeProducer clueChangeProducer; |
39 | + private final RenewalSwitchProducer renewalSwitchProducer; | |
35 | 40 | private final FollowClueService followClueService; |
36 | 41 | private final StringRedisTemplate redisTemplate; |
37 | 42 | @Value("${spring.cache.custom.global-prefix}:follow:clue:change") |
... | ... | @@ -40,42 +45,45 @@ public class ClueChangeNoticeTask { |
40 | 45 | |
41 | 46 | @Autowired |
42 | 47 | public ClueChangeNoticeTask(final ClueChangeProducer clueChangeProducer, |
48 | + final RenewalSwitchProducer renewalSwitchProducer, | |
43 | 49 | final FollowClueService followClueService, |
44 | 50 | final StringRedisTemplate redisTemplate) { |
45 | 51 | this.clueChangeProducer = clueChangeProducer; |
52 | + this.renewalSwitchProducer = renewalSwitchProducer; | |
46 | 53 | this.followClueService = followClueService; |
47 | 54 | this.redisTemplate = redisTemplate; |
48 | 55 | } |
49 | 56 | |
50 | 57 | @Scheduled(initialDelay = 1000 * 30, fixedRate = 1000 * 60) |
51 | 58 | public void sendStopNotice() { |
52 | - String pop = null; | |
53 | - while ((pop = redisTemplate.opsForSet().pop(generateStopKey())) != null) { | |
59 | + List<String> failList = new ArrayList<>(); | |
60 | + final BoundSetOperations<String, String> operations = redisTemplate.boundSetOps(generateStopKey()); | |
61 | + String pop; | |
62 | + while ((pop = operations.pop()) != null) { | |
54 | 63 | try { |
55 | 64 | final Long clueId = Long.valueOf(pop); |
56 | - CompletableFuture.runAsync(() -> { | |
57 | - FollowClue clue = followClueService.getById(clueId); | |
58 | - if (Objects.nonNull(clue)) { | |
59 | - ClueChangeResult result = new ClueChangeResult(); | |
60 | - result.setFrameNo(clue.getVin()); | |
61 | - result.setGroupId(clue.getGroupId()); | |
62 | - result.setChangeType(ClueChangeResult.ChangeType.STOP); | |
63 | - if (FollowTypeEnum.RM.equals(clue.getClueType())) { | |
64 | - result.setClueType(CustomerFollowTypeEnum.RM.getValue()); | |
65 | - } else if (FollowTypeEnum.IR.equals(clue.getClueType())) { | |
66 | - result.setClueType(CustomerFollowTypeEnum.IR.getValue()); | |
67 | - } | |
68 | - clueChangeProducer.send(result); | |
65 | + FollowClue clue = followClueService.getById(clueId); | |
66 | + if (Objects.nonNull(clue)) { | |
67 | + ClueChangeResult result = new ClueChangeResult(); | |
68 | + result.setFrameNo(clue.getVin()); | |
69 | + result.setGroupId(clue.getGroupId()); | |
70 | + result.setChangeType(ClueChangeResult.ChangeType.STOP); | |
71 | + if (FollowTypeEnum.RM.equals(clue.getClueType())) { | |
72 | + result.setClueType(CustomerFollowTypeEnum.RM.getValue()); | |
73 | + } else if (FollowTypeEnum.IR.equals(clue.getClueType())) { | |
74 | + result.setClueType(CustomerFollowTypeEnum.IR.getValue()); | |
75 | + renewalSwitchProducer.send(clue.getVin(), clue.getEndTime().toLocalDate(), clue.getGroupId()); | |
69 | 76 | } |
70 | - }); | |
77 | + clueChangeProducer.send(result); | |
78 | + } | |
71 | 79 | } catch (Exception ex) { |
80 | + failList.add(pop); | |
72 | 81 | log.error(ex.getMessage(), ex); |
73 | 82 | } |
74 | 83 | } |
75 | - } | |
76 | - | |
77 | - private String generateAddKey() { | |
78 | - return String.format("%s:%s", getClueChangeKeyPrefix(), "ADD"); | |
84 | + if (!CollectionUtils.isEmpty(failList)) { | |
85 | + operations.add(failList.toArray(new String[0])); | |
86 | + } | |
79 | 87 | } |
80 | 88 | |
81 | 89 | private String generateStopKey() { | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/FollowFlowConsumer.java deleted
1 | -package cn.fw.valhalla.component; | |
2 | - | |
3 | -import cn.fw.shirasawa.sdk.mq.FollowApproveDTO; | |
4 | -import cn.fw.valhalla.domain.db.follow.ClueTask; | |
5 | -import cn.fw.valhalla.domain.db.follow.FollowClue; | |
6 | -import cn.fw.valhalla.domain.enums.ClueStatusEnum; | |
7 | -import cn.fw.valhalla.domain.enums.FollowTypeEnum; | |
8 | -import cn.fw.valhalla.domain.enums.TaskStateEnum; | |
9 | -import cn.fw.valhalla.service.bus.cust.CustomerBizService; | |
10 | -import cn.fw.valhalla.service.data.ClueTaskService; | |
11 | -import cn.fw.valhalla.service.data.FollowClueService; | |
12 | -import com.alibaba.fastjson.JSONObject; | |
13 | -import com.baomidou.mybatisplus.core.toolkit.Wrappers; | |
14 | -import lombok.extern.slf4j.Slf4j; | |
15 | -import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; | |
16 | -import org.apache.rocketmq.spring.core.RocketMQListener; | |
17 | -import org.springframework.beans.factory.annotation.Autowired; | |
18 | -import org.springframework.stereotype.Component; | |
19 | - | |
20 | -import java.util.Objects; | |
21 | - | |
22 | -/** | |
23 | - * @author : kurisu | |
24 | - * Date: 2020/9/16 | |
25 | - * Time: 10:57 | |
26 | - * Description: | |
27 | - */ | |
28 | -@Slf4j | |
29 | -@Component | |
30 | -@RocketMQMessageListener(topic = FollowApproveDTO.FOLLOW_APPROVE_TOPIC, consumerGroup = "${spring.application.name}_follow_flow_result") | |
31 | -public class FollowFlowConsumer implements RocketMQListener<FollowApproveDTO> { | |
32 | - | |
33 | - private final CustomerBizService customerBizService; | |
34 | - private final FollowClueService followClueService; | |
35 | - private final ClueTaskService clueTaskService; | |
36 | - | |
37 | - | |
38 | - @Autowired | |
39 | - public FollowFlowConsumer(final CustomerBizService customerBizService, | |
40 | - final FollowClueService followClueService, | |
41 | - final ClueTaskService clueTaskService) { | |
42 | - this.customerBizService = customerBizService; | |
43 | - this.followClueService = followClueService; | |
44 | - this.clueTaskService = clueTaskService; | |
45 | - } | |
46 | - | |
47 | - @Override | |
48 | - public void onMessage(FollowApproveDTO dto) { | |
49 | - log.info("跟进审批通过MQ消息回调:{}", JSONObject.toJSONString(dto)); | |
50 | - try { | |
51 | - FollowClue clue = null; | |
52 | - if (FollowTypeEnum.AC.getValue().equals(dto.getType())) { | |
53 | - clue = followClueService.getOne(Wrappers.<FollowClue>lambdaQuery() | |
54 | - .eq(FollowClue::getPlateNo, dto.getPlateNo()) | |
55 | - .eq(FollowClue::getClueState, ClueStatusEnum.ONGOING) | |
56 | - .eq(FollowClue::getClueType, dto.getType()) | |
57 | - ); | |
58 | - } else { | |
59 | - clue = followClueService.getOne(Wrappers.<FollowClue>lambdaQuery() | |
60 | - .eq(FollowClue::getVin, dto.getVin()) | |
61 | - .eq(FollowClue::getClueState, ClueStatusEnum.ONGOING) | |
62 | - .eq(FollowClue::getClueType, dto.getType()) | |
63 | - ); | |
64 | - } | |
65 | - | |
66 | - if (Objects.isNull(clue)) { | |
67 | - return; | |
68 | - } | |
69 | - | |
70 | - doSomething(clue); | |
71 | - } catch (Exception e) { | |
72 | - log.error("跟进审批通过处理异常", e); | |
73 | - throw e; | |
74 | - } | |
75 | - } | |
76 | - | |
77 | - public void doSomething(FollowClue clue) { | |
78 | - ClueTask task = clueTaskService.getOne(Wrappers.<ClueTask>lambdaQuery() | |
79 | - .eq(ClueTask::getType, clue.getClueType()) | |
80 | - .eq(ClueTask::getClueId, clue.getId()) | |
81 | - .eq(ClueTask::getState, TaskStateEnum.ONGOING) | |
82 | - , Boolean.FALSE | |
83 | - ); | |
84 | - if (Objects.isNull(task)) { | |
85 | - return; | |
86 | - } | |
87 | - customerBizService.abandon(task); | |
88 | - } | |
89 | -} |
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/AttentionConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/AttentionConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/AuthVehicleConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/AuthVehicleConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/CallReportConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/CallReportConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/CardNotifyConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/CardNotifyConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/CheckInConsumer.kt renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/CheckInConsumer.kt
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/FollowFlowConsumer.kt
0 → 100644
1 | +package cn.fw.valhalla.component.consumer; | |
2 | + | |
3 | +import cn.fw.shirasawa.sdk.mq.FollowApproveDTO | |
4 | +import cn.fw.valhalla.service.bus.cust.CustomerBizService | |
5 | +import cn.fw.valhalla.service.data.ClueTaskService | |
6 | +import cn.fw.valhalla.service.data.FollowClueService | |
7 | +import com.alibaba.fastjson.JSONObject | |
8 | +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener | |
9 | +import org.apache.rocketmq.spring.core.RocketMQListener | |
10 | +import org.slf4j.Logger | |
11 | +import org.slf4j.LoggerFactory | |
12 | +import org.springframework.stereotype.Component | |
13 | + | |
14 | +/** | |
15 | + * @author : kurisu | |
16 | + * Date: 2020/9/16 | |
17 | + * Time: 10:57 | |
18 | + * Description: | |
19 | + */ | |
20 | +@Component | |
21 | +@RocketMQMessageListener( | |
22 | + topic = FollowApproveDTO.FOLLOW_APPROVE_TOPIC, | |
23 | + consumerGroup = "\${spring.application.name}_follow_flow_result" | |
24 | +) | |
25 | +class FollowFlowConsumer( | |
26 | + private val customerBizService: CustomerBizService, | |
27 | + private val clueTaskService: ClueTaskService, | |
28 | + private val followClueService: FollowClueService | |
29 | +) : RocketMQListener<FollowApproveDTO> { | |
30 | + | |
31 | + private val log: Logger = LoggerFactory.getLogger(this.javaClass) | |
32 | + | |
33 | + override fun onMessage(dto: FollowApproveDTO?) { | |
34 | + log.info("跟进审批通过MQ消息回调:{}", JSONObject.toJSONString(dto)); | |
35 | + dto?.let { data -> | |
36 | + val clue = followClueService.getById(data.detailId.toLong()) | |
37 | + clue?.let { | |
38 | + clueTaskService.queryOngoingTaskByClueId(it.id)?.apply { | |
39 | + customerBizService.abandon(this) | |
40 | + } | |
41 | + } | |
42 | + } | |
43 | + } | |
44 | +} | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/FollowResultConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/FollowResultConsumer.java
1 | -package cn.fw.valhalla.component; | |
1 | +package cn.fw.valhalla.component.consumer; | |
2 | 2 | |
3 | 3 | import cn.fw.shirasawa.sdk.enums.DataTypeEnum; |
4 | 4 | import cn.fw.shirasawa.sdk.mq.FollowResultDTO; |
5 | -import cn.fw.valhalla.domain.db.follow.ClueTask; | |
5 | +import cn.fw.valhalla.domain.db.follow.FollowClue; | |
6 | 6 | import cn.fw.valhalla.service.bus.follow.FollowBizService; |
7 | -import cn.fw.valhalla.service.data.ClueTaskService; | |
7 | +import cn.fw.valhalla.service.data.FollowClueService; | |
8 | 8 | import cn.hutool.core.collection.ListUtil; |
9 | 9 | import com.alibaba.fastjson.JSONObject; |
10 | 10 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -30,14 +30,14 @@ import java.util.Set; |
30 | 30 | public class FollowResultConsumer implements RocketMQListener<FollowResultDTO> { |
31 | 31 | |
32 | 32 | private final FollowBizService followBizService; |
33 | - private final ClueTaskService clueTaskService; | |
33 | + private final FollowClueService followClueService; | |
34 | 34 | |
35 | 35 | |
36 | 36 | @Autowired |
37 | 37 | public FollowResultConsumer(final FollowBizService followBizService, |
38 | - final ClueTaskService clueTaskService) { | |
38 | + final FollowClueService followClueService) { | |
39 | 39 | this.followBizService = followBizService; |
40 | - this.clueTaskService = clueTaskService; | |
40 | + this.followClueService = followClueService; | |
41 | 41 | } |
42 | 42 | |
43 | 43 | @Override |
... | ... | @@ -56,11 +56,11 @@ public class FollowResultConsumer implements RocketMQListener<FollowResultDTO> { |
56 | 56 | return; |
57 | 57 | } |
58 | 58 | Long val = Long.valueOf(dto.getDetailId()); |
59 | - ClueTask task = clueTaskService.getById(val); | |
60 | - if (Objects.isNull(task)) { | |
59 | + FollowClue clue = followClueService.getById(val); | |
60 | + if (Objects.isNull(clue)) { | |
61 | 61 | return; |
62 | 62 | } |
63 | - followBizService.afterFollowComplete(task, dto.isOverdue()); | |
63 | + followBizService.afterFollowComplete(clue, dto.isOverdue()); | |
64 | 64 | } catch (Exception e) { |
65 | 65 | log.error("处理跟进结果MQ异常", e); |
66 | 66 | throw e; | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/InsuranceConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/InsuranceConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/MemberMergeConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/MemberMergeConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/MemberPhoneChangeConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/MemberPhoneChangeConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/MileageConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/MileageConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/RoleChangeConsumer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/consumer/RoleChangeConsumer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/ClueChangeProducer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/producer/ClueChangeProducer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/CustAfterDistProducer.kt renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/producer/CustAfterDistProducer.kt
1 | -package cn.fw.valhalla.component | |
1 | +package cn.fw.valhalla.component.producer | |
2 | 2 | |
3 | 3 | import cn.fw.valhalla.sdk.result.CustomerDistributedMQ |
4 | 4 | import org.apache.rocketmq.spring.core.RocketMQTemplate |
... | ... | @@ -19,7 +19,7 @@ import java.util.* |
19 | 19 | */ |
20 | 20 | @Component |
21 | 21 | class CustAfterDistProducer(private val rocketMQTemplate: RocketMQTemplate) { |
22 | - private val log: Logger = LoggerFactory.getLogger(CustAfterDistProducer::class.java) | |
22 | + private val log: Logger = LoggerFactory.getLogger(this.javaClass) | |
23 | 23 | |
24 | 24 | @RequestMapping(value = ["send"]) |
25 | 25 | fun send(resign: Boolean, staffIds: List<Long>?) { | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/CustomerChangeProducer.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/component/producer/CustomerChangeProducer.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/component/producer/RenewalSwitchProducer.kt
0 → 100644
1 | +package cn.fw.valhalla.component.producer | |
2 | + | |
3 | +import cn.fw.valhalla.common.utils.DateUtil | |
4 | +import cn.fw.valhalla.domain.enums.FollowTypeEnum | |
5 | +import cn.fw.valhalla.domain.enums.SettingTypeEnum | |
6 | +import cn.fw.valhalla.domain.vo.setting.SettingVO | |
7 | +import cn.fw.valhalla.sdk.result.CustomerDistributedMQ | |
8 | +import cn.fw.valhalla.sdk.result.RenewalSwitchMQ | |
9 | +import cn.fw.valhalla.service.bus.setting.SettingBizService | |
10 | +import cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy | |
11 | +import org.apache.rocketmq.spring.core.RocketMQTemplate | |
12 | +import org.slf4j.Logger | |
13 | +import org.slf4j.LoggerFactory | |
14 | +import org.springframework.stereotype.Component | |
15 | +import org.springframework.web.bind.annotation.RequestMapping | |
16 | +import java.time.LocalDate | |
17 | +import java.util.* | |
18 | + | |
19 | +/** | |
20 | + * 续保跟进切换mq生产者 | |
21 | + * | |
22 | + * @author : kurisu | |
23 | + * @version : 1.0 | |
24 | + * @className : RenewalSwitchProducer | |
25 | + * @description : 续保跟进切换mq生产者 | |
26 | + * @date : 2023-03-15 15:37 | |
27 | + */ | |
28 | +@Component | |
29 | +class RenewalSwitchProducer( | |
30 | + private val rocketMQTemplate: RocketMQTemplate, | |
31 | + private val settingBizService: SettingBizService | |
32 | +) { | |
33 | + private val log: Logger = LoggerFactory.getLogger(this.javaClass) | |
34 | + | |
35 | + @RequestMapping(value = ["send"]) | |
36 | + fun send(vin: String, deadline: LocalDate, groupId: Long) { | |
37 | + val settingVO: Optional<SettingVO?> = settingBizService.querySettingByType( | |
38 | + FollowTypeEnum.IR, | |
39 | + SettingTypeEnum.MODE, | |
40 | + groupId, | |
41 | + SettingStrategy.COMMON_BRAND_ID | |
42 | + ) | |
43 | + // 模式 1、续保角色 2、续保角色+服务接待/新车销售 | |
44 | + val mode = settingVO.map { obj: SettingVO? -> obj?.detailValue }.orElse(1) | |
45 | + if (mode == 1) { | |
46 | + return | |
47 | + } | |
48 | + if (!LocalDate.now().plusDays(1L).isBefore(deadline)) { | |
49 | + return | |
50 | + } | |
51 | + log.info("发送续保跟进切换mq消息。vin:{}", vin) | |
52 | + try { | |
53 | + val mq = RenewalSwitchMQ(FollowTypeEnum.IR.value, vin, DateUtil.localDate2Date(deadline)) | |
54 | + rocketMQTemplate.syncSend(CustomerDistributedMQ.TOPIC + ":*", mq) | |
55 | + } catch (e: Exception) { | |
56 | + log.info("发送保有客分配结束mq消息失败!", e) | |
57 | + } | |
58 | + } | |
59 | +} | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/LeaveNeedDoBizService.java
... | ... | @@ -9,7 +9,7 @@ import cn.fw.hermes.sdk.api.ImSendMessage; |
9 | 9 | import cn.fw.hermes.sdk.api.para.MsgParamCondition; |
10 | 10 | import cn.fw.valhalla.common.constant.RoleCode; |
11 | 11 | import cn.fw.valhalla.common.utils.DateUtil; |
12 | -import cn.fw.valhalla.component.CustAfterDistProducer; | |
12 | +import cn.fw.valhalla.component.producer.CustAfterDistProducer; | |
13 | 13 | import cn.fw.valhalla.domain.db.LeaveNeedDo; |
14 | 14 | import cn.fw.valhalla.domain.db.customer.Customer; |
15 | 15 | import cn.fw.valhalla.domain.db.follow.ClueTask; | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/cust/AbstractCustomerService.java
... | ... | @@ -3,7 +3,7 @@ package cn.fw.valhalla.service.bus.cust; |
3 | 3 | import cn.fw.hermes.sdk.api.ImSendMessage; |
4 | 4 | import cn.fw.oop.sdk.enums.BizTypeEnum; |
5 | 5 | import cn.fw.valhalla.common.utils.DateUtil; |
6 | -import cn.fw.valhalla.component.CustomerChangeProducer; | |
6 | +import cn.fw.valhalla.component.producer.CustomerChangeProducer; | |
7 | 7 | import cn.fw.valhalla.domain.db.customer.Customer; |
8 | 8 | import cn.fw.valhalla.domain.db.customer.CustomerBaseInfo; |
9 | 9 | import cn.fw.valhalla.domain.db.customer.CustomerLoanInfo; | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/FollowBizService.java
... | ... | @@ -209,13 +209,13 @@ public class FollowBizService { |
209 | 209 | /** |
210 | 210 | * 跟进完成 |
211 | 211 | * |
212 | - * @param task | |
212 | + * @param clue | |
213 | 213 | * @param overdue 逾期 |
214 | 214 | */ |
215 | - public void afterFollowComplete(ClueTask task, boolean overdue) { | |
216 | - FollowStrategy strategy = followMap.get(task.getType()); | |
215 | + public void afterFollowComplete(FollowClue clue, boolean overdue) { | |
216 | + FollowStrategy strategy = followMap.get(clue.getClueType()); | |
217 | 217 | Assert.notNull(strategy, "strategy cannot be null"); |
218 | - strategy.onFollowComplete(task, overdue); | |
218 | + strategy.onFollowComplete(clue, overdue); | |
219 | 219 | } |
220 | 220 | |
221 | 221 | /** | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/AbstractFollowStrategy.java
... | ... | @@ -12,7 +12,6 @@ import cn.fw.valhalla.domain.db.customer.CustomerBaseInfo; |
12 | 12 | import cn.fw.valhalla.domain.db.follow.ClueTask; |
13 | 13 | import cn.fw.valhalla.domain.db.follow.FollowClue; |
14 | 14 | import cn.fw.valhalla.domain.db.follow.FollowNoticeRecord; |
15 | -import cn.fw.valhalla.domain.db.pool.StammkundePool; | |
16 | 15 | import cn.fw.valhalla.domain.db.setting.FollowSettingDetail; |
17 | 16 | import cn.fw.valhalla.domain.dto.CustomerDetailDto; |
18 | 17 | import cn.fw.valhalla.domain.enums.*; |
... | ... | @@ -34,7 +33,6 @@ import cn.fw.valhalla.service.data.*; |
34 | 33 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
35 | 34 | import lombok.Getter; |
36 | 35 | import lombok.extern.slf4j.Slf4j; |
37 | -import org.springframework.beans.BeanUtils; | |
38 | 36 | import org.springframework.beans.factory.annotation.Autowired; |
39 | 37 | import org.springframework.beans.factory.annotation.Value; |
40 | 38 | import org.springframework.data.redis.core.StringRedisTemplate; |
... | ... | @@ -128,6 +126,7 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
128 | 126 | } |
129 | 127 | |
130 | 128 | @Override |
129 | + @Transactional(rollbackFor = Exception.class) | |
131 | 130 | public void settingChanged(List<SettingVO> setting, Long groupId) { |
132 | 131 | List<FollowClue> poolList = followClueService.list(Wrappers.<FollowClue>lambdaQuery() |
133 | 132 | .eq(FollowClue::getClueType, getFollowType()) |
... | ... | @@ -188,17 +187,12 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
188 | 187 | @Override |
189 | 188 | @Transactional(rollbackFor = Exception.class) |
190 | 189 | public void closeTask(ClueTask task) { |
191 | - boolean redistribution = Boolean.TRUE.equals(task.getRedistribution()); | |
192 | 190 | final Long clueId = task.getClueId(); |
193 | 191 | FollowClue clue = followClueService.getById(clueId); |
194 | 192 | BV.notNull(clue, () -> "跟进线索不存在: " + clueId); |
195 | - redistribution = redistribution || task.getDeadline().toLocalDate().isEqual(clue.getEndTime().toLocalDate()); | |
196 | - task.setState(TaskStateEnum.DEFEAT); | |
197 | 193 | task.setCloseTime(task.getDeadline().minusSeconds(1L)); |
194 | + task.setState(TaskStateEnum.DEFEAT); | |
198 | 195 | task.setReason(TaskDefeatTypeEnum.C); |
199 | - if (!redistribution) { | |
200 | - task.setReason(TaskDefeatTypeEnum.B); | |
201 | - } | |
202 | 196 | boolean rpcSucess = rpcStopTask(task); |
203 | 197 | if (!rpcSucess) { |
204 | 198 | log.info("跟进系统终止任务失败"); |
... | ... | @@ -206,15 +200,11 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
206 | 200 | task.setRpcSuccess(rpcSucess); |
207 | 201 | clueTaskService.updateById(task); |
208 | 202 | if (Objects.nonNull(clue)) { |
209 | - if (redistribution) { | |
210 | - clue.setCloseTime(task.getCloseTime()); | |
211 | - clue.setClueState(ClueStatusEnum.FAILURE); | |
212 | - followClueService.updateById(clue); | |
213 | - redisTemplate.opsForSet().add(generateStopKey(), String.valueOf(clueId)); | |
214 | - customerBizService.taskEndAbandon(task, clue); | |
215 | - } else { | |
216 | - createSecondaryTask(clue, task); | |
217 | - } | |
203 | + clue.setCloseTime(task.getCloseTime()); | |
204 | + clue.setClueState(ClueStatusEnum.FAILURE); | |
205 | + followClueService.updateById(clue); | |
206 | + redisTemplate.opsForSet().add(generateStopKey(), String.valueOf(clueId)); | |
207 | + customerBizService.taskEndAbandon(task, clue); | |
218 | 208 | } |
219 | 209 | } |
220 | 210 | |
... | ... | @@ -226,7 +216,6 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
226 | 216 | @Override |
227 | 217 | @Transactional(rollbackFor = Exception.class) |
228 | 218 | public void onRoleChangeCloseTask(ClueTask task) { |
229 | - boolean redistribution = Boolean.TRUE.equals(task.getRedistribution()); | |
230 | 219 | Long clueId = task.getClueId(); |
231 | 220 | FollowClue clue = followClueService.getById(clueId); |
232 | 221 | task.setState(TaskStateEnum.DEFEAT); |
... | ... | @@ -249,20 +238,21 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
249 | 238 | if (task.getFollowUser().equals(adviserId)) { |
250 | 239 | return; |
251 | 240 | } |
252 | - | |
253 | - boolean rpcSucess = rpcStopTask(task); | |
254 | - if (!rpcSucess) { | |
255 | - log.info("跟进系统终止任务失败"); | |
256 | - } | |
257 | - task.setRpcSuccess(rpcSucess); | |
258 | - clueTaskService.updateById(task); | |
259 | - | |
260 | - if (redistribution || Objects.isNull(adviserId)) { | |
241 | + if (Objects.isNull(adviserId)) { | |
242 | + boolean rpcSuccess = rpcStopTask(task); | |
243 | + if (!rpcSuccess) { | |
244 | + log.info("跟进系统终止任务失败"); | |
245 | + } | |
246 | + task.setRpcSuccess(rpcSuccess); | |
247 | + clueTaskService.updateById(task); | |
261 | 248 | clue.setCloseTime(task.getCloseTime()); |
262 | 249 | clue.setClueState(ClueStatusEnum.FAILURE); |
263 | 250 | followClueService.updateById(clue); |
251 | + | |
264 | 252 | redisTemplate.opsForSet().add(generateStopKey(), String.valueOf(clueId)); |
265 | 253 | } else { |
254 | + task.setRpcSuccess(true); | |
255 | + clueTaskService.updateById(task); | |
266 | 256 | createSecondaryTask(clue, adviserId); |
267 | 257 | } |
268 | 258 | } |
... | ... | @@ -312,13 +302,14 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
312 | 302 | /** |
313 | 303 | * 当跟进待办结束(包括完成和逾期) |
314 | 304 | * |
315 | - * @param task | |
305 | + * @param clue | |
316 | 306 | * @param overdue |
317 | 307 | */ |
318 | 308 | @Override |
319 | 309 | @Transactional(rollbackFor = Exception.class) |
320 | - public void onFollowComplete(ClueTask task, boolean overdue) { | |
321 | - if (!overdue) { | |
310 | + public void onFollowComplete(FollowClue clue, boolean overdue) { | |
311 | + ClueTask task = clueTaskService.queryOngoingTaskByClueId(clue.getId()); | |
312 | + if (!overdue && Objects.nonNull(task)) { | |
322 | 313 | Integer times = Optional.ofNullable(task.getTimes()).orElse(0); |
323 | 314 | task.setTimes(times + 1); |
324 | 315 | clueTaskService.updateById(task); |
... | ... | @@ -529,7 +520,7 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
529 | 520 | .plateNo(followClue.getPlateNo()) |
530 | 521 | .frameNo(followClue.getVin()) |
531 | 522 | .contacts(phone) |
532 | - .detailId(String.valueOf(clueTask.getId())) | |
523 | + .detailId(String.valueOf(followClue.getId())) | |
533 | 524 | .generateTime(DateUtil.localDateTime2Date(clueTask.getBeginTime())) |
534 | 525 | .deadline(DateUtil.localDateTime2Date(clueTask.getDeadline())) |
535 | 526 | .groupId(clueTask.getGroupId()) |
... | ... | @@ -560,7 +551,7 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
560 | 551 | } |
561 | 552 | |
562 | 553 | protected FollowInitDTO creteRedistributionFollowInitDTO(FollowClue followClue, ClueTask clueTask) { |
563 | - final LocalDateTime nextTime = Optional.ofNullable(followClue.getNextTime()).orElse(clueTask.getBeginTime()); | |
554 | + final LocalDateTime nextTime = clueTask.getBeginTime(); | |
564 | 555 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); |
565 | 556 | followInitDTO.setGenerateTime(DateUtil.localDateTime2Date(nextTime)); |
566 | 557 | Long brandId = COMMON_BRAND_ID; |
... | ... | @@ -610,49 +601,6 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
610 | 601 | followNoticeRecordService.save(record); |
611 | 602 | } |
612 | 603 | |
613 | - | |
614 | - protected void createSecondaryTask(FollowClue clue, ClueTask oldTask) { | |
615 | - LocalDate endTime = clue.getEndTime().toLocalDate(); | |
616 | - if (!LocalDate.now().isBefore(endTime)) { | |
617 | - clue.setCloseTime(clue.getEndTime()); | |
618 | - clue.setClueState(ClueStatusEnum.FAILURE); | |
619 | - followClueService.updateById(clue); | |
620 | - return; | |
621 | - } | |
622 | - ClueTask redistributionTask = new ClueTask(); | |
623 | - BeanUtils.copyProperties(oldTask, redistributionTask); | |
624 | - redistributionTask.setId(null); | |
625 | - redistributionTask.setRedistribution(Boolean.TRUE); | |
626 | - redistributionTask.setBeginTime(LocalDate.now().atStartOfDay()); | |
627 | - redistributionTask.setDeadline(clue.getEndTime()); | |
628 | - redistributionTask.setState(TaskStateEnum.ONGOING); | |
629 | - redistributionTask.setFinishShop(null); | |
630 | - redistributionTask.setFinishUser(null); | |
631 | - redistributionTask.setFinishUserName(null); | |
632 | - redistributionTask.setReason(null); | |
633 | - redistributionTask.setCloseTime(null); | |
634 | - redistributionTask.setRpcSuccess(Boolean.FALSE); | |
635 | - StammkundePool stammkundePool = customerChangeBizService.changeFollowUser(clue); | |
636 | - redistributionTask.setFollowUser(oldTask.getFollowUser()); | |
637 | - redistributionTask.setFollowUserName(oldTask.getFollowUserName()); | |
638 | - CustomerDetailDto customer = customerBizService.queryByFrameNo(clue.getVin(), clue.getGroupId()); | |
639 | - if (Objects.nonNull(customer) && Objects.nonNull(customer.getAdviserId()) && !oldTask.getFollowUser().equals(customer.getAdviserId())) { | |
640 | - redistributionTask.setFollowUser(customer.getAdviserId()); | |
641 | - redistributionTask.setFollowUserName(customer.getAdviserName()); | |
642 | - redistributionTask.setFollowShop(customer.getShopId()); | |
643 | - } | |
644 | - if (Objects.nonNull(stammkundePool)) { | |
645 | - redistributionTask.setFollowUser(stammkundePool.getAdviserId()); | |
646 | - redistributionTask.setFollowUserName(stammkundePool.getAdviserName()); | |
647 | - } | |
648 | - clueTaskService.save(redistributionTask); | |
649 | - FollowInitDTO followInitDTO = creteRedistributionFollowInitDTO(clue, redistributionTask); | |
650 | - shirasawaRpcService.createFollowData(followInitDTO); | |
651 | - clue.setNextTime(redistributionTask.getDeadline().plusDays(1L)); | |
652 | - followClueService.updateById(clue); | |
653 | - } | |
654 | - | |
655 | - | |
656 | 604 | protected boolean rpcStopTask(ClueTask clueTask) { |
657 | 605 | TaskDefeatTypeEnum reason = clueTask.getReason(); |
658 | 606 | if (TaskDefeatTypeEnum.B.equals(reason) || TaskDefeatTypeEnum.C.equals(reason)) { |
... | ... | @@ -673,7 +621,7 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
673 | 621 | clueStopDTO.setReason(TerminationReason.ROLE_CHANGE); |
674 | 622 | } |
675 | 623 | } |
676 | - clueStopDTO.setDetailId(String.valueOf(clueTask.getId())); | |
624 | + clueStopDTO.setDetailId(String.valueOf(clueTask.getClueId())); | |
677 | 625 | clueStopDTO.setShopId(clueTask.getFinishShop()); |
678 | 626 | ShopDTO shop = oopService.shop(clueTask.getFinishShop()); |
679 | 627 | if (Objects.nonNull(shop)) { |
... | ... | @@ -786,8 +734,7 @@ public abstract class AbstractFollowStrategy implements FollowStrategy { |
786 | 734 | redistributionTask.setRpcSuccess(Boolean.FALSE); |
787 | 735 | clueTaskService.save(redistributionTask); |
788 | 736 | FollowInitDTO followInitDTO = creteRedistributionFollowInitDTO(clue, redistributionTask); |
789 | - shirasawaRpcService.createFollowData(followInitDTO); | |
790 | - clue.setNextTime(redistributionTask.getDeadline().plusDays(1L)); | |
737 | + shirasawaRpcService.changeFollowData(followInitDTO); | |
791 | 738 | followClueService.updateById(clue); |
792 | 739 | } |
793 | 740 | ... | ... |
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 | - * | |
73 | + * // todo 续保跟进截止后战败mode2时档案 | |
74 | 74 | * @param task |
75 | 75 | */ |
76 | 76 | @Transactional(rollbackFor = Exception.class) |
... | ... | @@ -88,11 +88,11 @@ public interface FollowStrategy { |
88 | 88 | /** |
89 | 89 | * 当跟进待办结束(包括完成和逾期) |
90 | 90 | * |
91 | - * @param task | |
91 | + * @param clue | |
92 | 92 | * @param overdue |
93 | 93 | */ |
94 | 94 | @Transactional(rollbackFor = Exception.class) |
95 | - void onFollowComplete(ClueTask task, boolean overdue); | |
95 | + void onFollowComplete(FollowClue clue, boolean overdue); | |
96 | 96 | |
97 | 97 | /** |
98 | 98 | * 任务结束同步状态到跟进系统 | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/impl/ACFollowStrategy.java
... | ... | @@ -77,13 +77,13 @@ public class ACFollowStrategy extends AbstractFollowStrategy { |
77 | 77 | clueTaskService.save(clueTask); |
78 | 78 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); |
79 | 79 | followInitDTO.setCustomerName(accidentPool.getName()); |
80 | - followClue.setNextTime(clueTask.getDeadline().plusDays(1L)); | |
81 | 80 | shirasawaRpcService.createFollowData(followInitDTO); |
82 | 81 | followClueService.updateById(followClue); |
83 | 82 | } |
84 | 83 | |
85 | 84 | |
86 | 85 | @Override |
86 | + @Transactional(rollbackFor = Exception.class) | |
87 | 87 | public void settingChanged(List<SettingVO> setting, Long groupId) { |
88 | 88 | // 更改设置不影响事故车跟进 |
89 | 89 | } |
... | ... | @@ -106,15 +106,6 @@ public class ACFollowStrategy extends AbstractFollowStrategy { |
106 | 106 | clueTaskService.updateById(task); |
107 | 107 | } |
108 | 108 | |
109 | - /** | |
110 | - * [角色变动]结束任务 | |
111 | - * | |
112 | - * @param task | |
113 | - */ | |
114 | - @Transactional(rollbackFor = Exception.class) | |
115 | - public void onRoleChangeCloseTask(ClueTask task) { | |
116 | - } | |
117 | - | |
118 | 109 | @Override |
119 | 110 | protected FollowInitDTO creteFollowInitDTO(FollowClue followClue, ClueTask clueTask) { |
120 | 111 | final FollowInitDTO followInitDTO = FollowInitDTO.builder() |
... | ... | @@ -123,7 +114,7 @@ public class ACFollowStrategy extends AbstractFollowStrategy { |
123 | 114 | .type(DataTypeEnum.ofValue(clueTask.getType().getValue())) |
124 | 115 | .frameNo(followClue.getVin()) |
125 | 116 | .contacts(followClue.getSuggestMobile()) |
126 | - .detailId(String.valueOf(clueTask.getId())) | |
117 | + .detailId(String.valueOf(followClue.getId())) | |
127 | 118 | .generateTime(DateUtil.localDateTime2Date(clueTask.getBeginTime())) |
128 | 119 | .deadline(DateUtil.localDateTime2Date(clueTask.getDeadline())) |
129 | 120 | .groupId(clueTask.getGroupId()) | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/impl/FMFollowStrategy.java
... | ... | @@ -96,7 +96,6 @@ public class FMFollowStrategy extends AbstractFollowStrategy { |
96 | 96 | followClue.setClueState(ClueStatusEnum.ONGOING); |
97 | 97 | clueTaskService.save(clueTask); |
98 | 98 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); |
99 | - followClue.setNextTime(clueTask.getDeadline().plusDays(1L)); | |
100 | 99 | shirasawaRpcService.createFollowData(followInitDTO); |
101 | 100 | followClueService.updateById(followClue); |
102 | 101 | } | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/impl/IRFollowStrategy.java
... | ... | @@ -4,27 +4,28 @@ import cn.fw.valhalla.common.constant.RoleCode; |
4 | 4 | import cn.fw.valhalla.common.utils.StringUtils; |
5 | 5 | import cn.fw.valhalla.domain.db.OriginalData; |
6 | 6 | import cn.fw.valhalla.domain.db.customer.Customer; |
7 | +import cn.fw.valhalla.domain.db.customer.CustomerReachLog; | |
7 | 8 | import cn.fw.valhalla.domain.db.follow.ClueTask; |
8 | 9 | import cn.fw.valhalla.domain.db.follow.FollowClue; |
9 | 10 | import cn.fw.valhalla.domain.dto.CustomerDetailDto; |
10 | 11 | import cn.fw.valhalla.domain.enums.*; |
12 | +import cn.fw.valhalla.domain.vo.customer.CustomerDetailVO; | |
11 | 13 | import cn.fw.valhalla.domain.vo.setting.SettingVO; |
12 | 14 | import cn.fw.valhalla.rpc.erp.dto.PostUserDTO; |
13 | 15 | import cn.fw.valhalla.rpc.oop.dto.ShopDTO; |
14 | 16 | import cn.fw.valhalla.rpc.shirasawa.dto.FollowInitDTO; |
15 | 17 | import cn.fw.valhalla.service.bus.follow.strategy.AbstractFollowStrategy; |
18 | +import cn.fw.valhalla.service.data.CustomerReachLogService; | |
16 | 19 | import cn.hutool.core.collection.ListUtil; |
17 | 20 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
18 | 21 | import lombok.extern.slf4j.Slf4j; |
19 | -import org.springframework.beans.BeanUtils; | |
22 | +import org.springframework.beans.factory.annotation.Autowired; | |
20 | 23 | import org.springframework.stereotype.Component; |
21 | 24 | import org.springframework.transaction.annotation.Transactional; |
22 | -import org.springframework.util.CollectionUtils; | |
23 | 25 | |
24 | 26 | import java.time.LocalDate; |
25 | 27 | import java.time.LocalDateTime; |
26 | 28 | import java.util.*; |
27 | -import java.util.stream.Collectors; | |
28 | 29 | |
29 | 30 | import static cn.fw.common.businessvalidator.Validator.BV; |
30 | 31 | import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID; |
... | ... | @@ -39,6 +40,13 @@ import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON |
39 | 40 | @Component |
40 | 41 | @SuppressWarnings("Duplicates") |
41 | 42 | public class IRFollowStrategy extends AbstractFollowStrategy { |
43 | + private final CustomerReachLogService customerReachLogService; | |
44 | + | |
45 | + @Autowired | |
46 | + public IRFollowStrategy(final CustomerReachLogService customerReachLogService) { | |
47 | + this.customerReachLogService = customerReachLogService; | |
48 | + } | |
49 | + | |
42 | 50 | @Override |
43 | 51 | public FollowTypeEnum getFollowType() { |
44 | 52 | return FollowTypeEnum.IR; |
... | ... | @@ -93,7 +101,7 @@ public class IRFollowStrategy extends AbstractFollowStrategy { |
93 | 101 | final int mode = settingVO.map(SettingVO::getDetailValue).orElse(1); |
94 | 102 | followClue.setPlateNo(customer.getPlateNo()); |
95 | 103 | final ClueTask clueTask = createNewTask(followClue); |
96 | - List<PostUserDTO> userByRole = new ArrayList<>(); | |
104 | + List<PostUserDTO> userByRole; | |
97 | 105 | if (mode == 1) { |
98 | 106 | userByRole = userService.getShopRolesUser(clueTask.getFollowShop(), RoleCode.XBGJ); |
99 | 107 | } else { |
... | ... | @@ -104,7 +112,6 @@ public class IRFollowStrategy extends AbstractFollowStrategy { |
104 | 112 | clueTaskService.save(clueTask); |
105 | 113 | followClue.setClueState(ClueStatusEnum.ONGOING); |
106 | 114 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); |
107 | - followClue.setNextTime(clueTask.getDeadline().plusDays(1L)); | |
108 | 115 | shirasawaRpcService.createFollowData(followInitDTO); |
109 | 116 | followClueService.updateById(followClue); |
110 | 117 | } |
... | ... | @@ -112,23 +119,18 @@ public class IRFollowStrategy extends AbstractFollowStrategy { |
112 | 119 | @Override |
113 | 120 | @Transactional(rollbackFor = Exception.class) |
114 | 121 | public void closeTask(ClueTask task) { |
115 | - boolean redistribution = Boolean.TRUE.equals(task.getRedistribution()); | |
116 | 122 | final Long clueId = task.getClueId(); |
117 | 123 | FollowClue clue = followClueService.getById(clueId); |
118 | 124 | BV.notNull(clue, () -> "跟进线索不存在: " + clueId); |
119 | - redistribution = redistribution || task.getDeadline().toLocalDate().isEqual(clue.getEndTime().toLocalDate()); | |
120 | 125 | task.setState(TaskStateEnum.DEFEAT); |
121 | 126 | task.setCloseTime(task.getDeadline().minusSeconds(1L)); |
122 | 127 | task.setReason(TaskDefeatTypeEnum.C); |
123 | - if (!redistribution) { | |
124 | - task.setReason(TaskDefeatTypeEnum.B); | |
125 | - } | |
126 | 128 | boolean rpcSucess = rpcStopTask(task); |
127 | 129 | if (!rpcSucess) { |
128 | 130 | log.info("跟进系统终止任务失败"); |
129 | 131 | } |
130 | 132 | task.setRpcSuccess(rpcSucess); |
131 | - if (Objects.nonNull(clue) && redistribution) { | |
133 | + if (Objects.nonNull(clue)) { | |
132 | 134 | clue.setClueState(ClueStatusEnum.FAILURE); |
133 | 135 | clue.setCloseTime(task.getCloseTime()); |
134 | 136 | followClueService.updateById(clue); |
... | ... | @@ -136,9 +138,6 @@ public class IRFollowStrategy extends AbstractFollowStrategy { |
136 | 138 | afterStopClue(clue); |
137 | 139 | } |
138 | 140 | clueTaskService.updateById(task); |
139 | - if (Objects.nonNull(clue) && !redistribution) { | |
140 | - this.createSecondaryTask(clue, task); | |
141 | - } | |
142 | 141 | } |
143 | 142 | |
144 | 143 | /** |
... | ... | @@ -148,29 +147,36 @@ public class IRFollowStrategy extends AbstractFollowStrategy { |
148 | 147 | */ |
149 | 148 | @Transactional(rollbackFor = Exception.class) |
150 | 149 | public void onRoleChangeCloseTask(ClueTask task) { |
151 | - boolean redistribution = Boolean.TRUE.equals(task.getRedistribution()); | |
152 | 150 | Long clueId = task.getClueId(); |
153 | 151 | FollowClue clue = followClueService.getById(clueId); |
154 | 152 | BV.notNull(clue, () -> "跟进线索不存在: " + clueId); |
155 | - redistribution = redistribution || task.getDeadline().toLocalDate().isEqual(clue.getEndTime().toLocalDate()); | |
153 | + Optional<SettingVO> settingVO = settingBizService.querySettingByType(getFollowType(), SettingTypeEnum.MODE, clue.getGroupId(), COMMON_BRAND_ID); | |
154 | + // 模式 1、续保角色 2、续保角色+服务接待/新车销售 | |
155 | + final int mode = settingVO.map(SettingVO::getDetailValue).orElse(1); | |
156 | 156 | task.setState(TaskStateEnum.DEFEAT); |
157 | 157 | task.setCloseTime(LocalDateTime.now()); |
158 | 158 | task.setReason(TaskDefeatTypeEnum.D); |
159 | - boolean rpcSucess = rpcStopTask(task); | |
160 | - if (!rpcSucess) { | |
161 | - log.info("跟进系统终止任务失败"); | |
162 | - } | |
163 | - task.setRpcSuccess(rpcSucess); | |
164 | - if (Objects.nonNull(clue) && redistribution) { | |
165 | - clue.setClueState(ClueStatusEnum.FAILURE); | |
166 | - clue.setCloseTime(task.getCloseTime()); | |
167 | - followClueService.updateById(clue); | |
168 | - afterStopClue(clue); | |
169 | - redisTemplate.opsForSet().add(generateStopKey(), String.valueOf(clueId)); | |
170 | - } | |
171 | - clueTaskService.updateById(task); | |
172 | - if (Objects.nonNull(clue) && !redistribution) { | |
173 | - this.createSecondaryTask(clue, task); | |
159 | + if (mode == 1) { | |
160 | + task.setRpcSuccess(true); | |
161 | + clueTaskService.updateById(task); | |
162 | + List<PostUserDTO> userByRole = userService.getShopRolesUser(task.getFollowShop(), RoleCode.XBGJ); | |
163 | + BV.isNotEmpty(userByRole, () -> String.format("该门店[mode: %s]没有【跟进】人员", mode)); | |
164 | + int randomIndex = new Random().nextInt(userByRole.size()); | |
165 | + PostUserDTO userDTO = userByRole.get(randomIndex); | |
166 | + createSecondaryTask(clue, userDTO.getUserId()); | |
167 | + } else { | |
168 | + Customer customer = customerService.queryByFrameNo(clue.getVin(), clue.getGroupId()); | |
169 | + Long adviserId = Optional.ofNullable(customer).map(Customer::getAdviserId).orElse(null); | |
170 | + if (Objects.isNull(adviserId)) { | |
171 | + boolean rpcSucess = rpcStopTask(task); | |
172 | + if (!rpcSucess) { | |
173 | + log.info("跟进系统终止任务失败"); | |
174 | + } | |
175 | + task.setRpcSuccess(rpcSucess); | |
176 | + clueTaskService.updateById(task); | |
177 | + return; | |
178 | + } | |
179 | + this.createSecondaryTask(clue, adviserId); | |
174 | 180 | } |
175 | 181 | } |
176 | 182 | |
... | ... | @@ -192,6 +198,14 @@ public class IRFollowStrategy extends AbstractFollowStrategy { |
192 | 198 | afterStopClue(clue); |
193 | 199 | redisTemplate.opsForSet().add(generateStopKey(), String.valueOf(clueId)); |
194 | 200 | } |
201 | + Optional<SettingVO> settingVO = settingBizService.querySettingByType(getFollowType(), SettingTypeEnum.MODE, clue.getGroupId(), COMMON_BRAND_ID); | |
202 | + // 模式 1、续保角色 2、续保角色+服务接待/新车销售 | |
203 | + 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(), "主动放弃"); | |
208 | + } | |
195 | 209 | } |
196 | 210 | |
197 | 211 | @Override |
... | ... | @@ -207,20 +221,29 @@ public class IRFollowStrategy extends AbstractFollowStrategy { |
207 | 221 | clueTask.setGroupId(followClue.getGroupId()); |
208 | 222 | Long userId = null; |
209 | 223 | Long shopId = null; |
210 | - if (StringUtils.isValid(followClue.getVin())) { | |
211 | - Customer customer = customerService.queryByFrameNo(followClue.getVin(), followClue.getGroupId()); | |
212 | - if (Objects.nonNull(customer)) { | |
213 | - userId = customer.getAdviserId(); | |
214 | - shopId = customer.getShopId(); | |
215 | - ShopDTO shop = oopService.shop(shopId); | |
216 | - if (Objects.isNull(shop)) { | |
217 | - userId = null; | |
218 | - shopId = followClue.getSuggestShopId(); | |
219 | - } | |
224 | + Customer customer = customerService.queryByFrameNo(followClue.getVin(), followClue.getGroupId()); | |
225 | + if (Objects.nonNull(customer)) { | |
226 | + userId = customer.getAdviserId(); | |
227 | + shopId = customer.getShopId(); | |
228 | + ShopDTO shop = oopService.shop(shopId); | |
229 | + if (Objects.isNull(shop)) { | |
230 | + userId = null; | |
231 | + shopId = null; | |
220 | 232 | } |
221 | 233 | } |
222 | 234 | if (Objects.isNull(shopId)) { |
223 | - shopId = followClue.getSuggestShopId(); | |
235 | + CustomerReachLog lastReach = customerReachLogService.getOne(Wrappers.<CustomerReachLog>lambdaQuery() | |
236 | + .eq(CustomerReachLog::getFrameNo, followClue.getVin()) | |
237 | + .eq(CustomerReachLog::getGroupId, followClue.getGroupId()) | |
238 | + .orderByDesc(CustomerReachLog::getArrivalTime) | |
239 | + , Boolean.FALSE); | |
240 | + if (Objects.nonNull(lastReach)) { | |
241 | + shopId = lastReach.getShopId(); | |
242 | + } | |
243 | + | |
244 | + if (Objects.isNull(shopId)) { | |
245 | + shopId = followClue.getSuggestShopId(); | |
246 | + } | |
224 | 247 | } |
225 | 248 | if (shopId == 146L) { |
226 | 249 | ArrayList<Long> arrayList = ListUtil.toList(67L, 65L, 66L); |
... | ... | @@ -232,47 +255,6 @@ public class IRFollowStrategy extends AbstractFollowStrategy { |
232 | 255 | return clueTask; |
233 | 256 | } |
234 | 257 | |
235 | - protected void createSecondaryTask(FollowClue clue, ClueTask oldTask) { | |
236 | - LocalDate endTime = clue.getEndTime().toLocalDate(); | |
237 | - if (!LocalDate.now().isBefore(endTime)) { | |
238 | - clue.setCloseTime(clue.getEndTime()); | |
239 | - clue.setClueState(ClueStatusEnum.FAILURE); | |
240 | - followClueService.updateById(clue); | |
241 | - return; | |
242 | - } | |
243 | - ClueTask redistributionTask = new ClueTask(); | |
244 | - BeanUtils.copyProperties(oldTask, redistributionTask); | |
245 | - redistributionTask.setId(null); | |
246 | - redistributionTask.setRedistribution(Boolean.TRUE); | |
247 | - redistributionTask.setBeginTime(LocalDate.now().atStartOfDay()); | |
248 | - redistributionTask.setDeadline(clue.getEndTime()); | |
249 | - redistributionTask.setState(TaskStateEnum.ONGOING); | |
250 | - redistributionTask.setFinishShop(null); | |
251 | - redistributionTask.setFinishUser(null); | |
252 | - redistributionTask.setCloseTime(null); | |
253 | - redistributionTask.setFinishUserName(null); | |
254 | - redistributionTask.setReason(null); | |
255 | - redistributionTask.setRpcSuccess(Boolean.FALSE);// todo 销售顾问跟进的场景 | |
256 | - List<PostUserDTO> userByRole = userService.getUserByRole(oldTask.getFollowShop(), RoleCode.XBGJ); | |
257 | - BV.isNotEmpty(userByRole, () -> "该门店没有【续保跟进】人员"); | |
258 | - List<PostUserDTO> newUserRole = userByRole.stream().filter(userDTO -> !userDTO.getUserId().equals(oldTask.getFollowUser())).collect(Collectors.toList()); | |
259 | - | |
260 | - if (CollectionUtils.isEmpty(newUserRole)) { | |
261 | - redistributionTask.setFollowUser(oldTask.getFollowUser()); | |
262 | - redistributionTask.setFollowUserName(oldTask.getFollowUserName()); | |
263 | - } else { | |
264 | - int randomIndex = new Random().nextInt(newUserRole.size()); | |
265 | - PostUserDTO userDTO = newUserRole.get(randomIndex); | |
266 | - redistributionTask.setFollowUser(userDTO.getUserId()); | |
267 | - redistributionTask.setFollowUserName(userDTO.getUserName()); | |
268 | - } | |
269 | - clueTaskService.save(redistributionTask); | |
270 | - FollowInitDTO followInitDTO = creteRedistributionFollowInitDTO(clue, redistributionTask); | |
271 | - shirasawaRpcService.createFollowData(followInitDTO); | |
272 | - clue.setNextTime(redistributionTask.getDeadline().plusDays(1L)); | |
273 | - followClueService.updateById(clue); | |
274 | - } | |
275 | - | |
276 | 258 | private void afterStopClue(FollowClue clue) { |
277 | 259 | String vin = clue.getVin(); |
278 | 260 | Long groupId = clue.getGroupId(); | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/impl/PubFollowStrategy.java
... | ... | @@ -144,8 +144,9 @@ public class PubFollowStrategy implements FollowStrategy { |
144 | 144 | } |
145 | 145 | |
146 | 146 | @Override |
147 | - public void onFollowComplete(final ClueTask task, final boolean overdue) { | |
148 | - if (!overdue) { | |
147 | + public void onFollowComplete(final FollowClue clue, final boolean overdue) { | |
148 | + ClueTask task = clueTaskService.queryOngoingTaskByClueId(clue.getId()); | |
149 | + if (!overdue && Objects.nonNull(task)) { | |
149 | 150 | Integer times = Optional.ofNullable(task.getTimes()).orElse(0); |
150 | 151 | task.setTimes(times + 1); |
151 | 152 | clueTaskService.updateById(task); |
... | ... | @@ -191,7 +192,7 @@ public class PubFollowStrategy implements FollowStrategy { |
191 | 192 | if (TaskStateEnum.DEFEAT.equals(clueTask.getState())) { |
192 | 193 | clueStopDTO.setTermination(Boolean.TRUE); |
193 | 194 | } |
194 | - clueStopDTO.setDetailId(String.valueOf(clueTask.getId())); | |
195 | + clueStopDTO.setDetailId(String.valueOf(clueTask.getClueId())); | |
195 | 196 | clueStopDTO.setShopId(clueTask.getFinishShop()); |
196 | 197 | ShopDTO shop = oopService.shop(clueTask.getFinishShop()); |
197 | 198 | if (Objects.nonNull(shop)) { |
... | ... | @@ -217,7 +218,7 @@ public class PubFollowStrategy implements FollowStrategy { |
217 | 218 | .plateNo(customerDetailDto.getPlateNo()) |
218 | 219 | .frameNo(pubClue.getVin()) |
219 | 220 | .contacts(customerDetailDto.getMobile()) |
220 | - .detailId(String.valueOf(clueTask.getId())) | |
221 | + .detailId(String.valueOf(clueTask.getClueId())) | |
221 | 222 | .generateTime(DateUtil.localDateTime2Date(clueTask.getBeginTime())) |
222 | 223 | .deadline(DateUtil.localDateTime2Date(clueTask.getDeadline())) |
223 | 224 | .groupId(clueTask.getGroupId()) | ... | ... |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/impl/RMFollowStrategy.java
... | ... | @@ -78,7 +78,6 @@ public class RMFollowStrategy extends AbstractFollowStrategy { |
78 | 78 | clueTaskService.save(clueTask); |
79 | 79 | followClue.setClueState(ClueStatusEnum.ONGOING); |
80 | 80 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); |
81 | - followClue.setNextTime(clueTask.getDeadline().plusDays(1L)); | |
82 | 81 | shirasawaRpcService.createFollowData(followInitDTO); |
83 | 82 | followClueService.updateById(followClue); |
84 | 83 | } | ... | ... |
pom.xml