Commit 03d7ac8440336ce09369f6d6c1bca02346368545
1 parent
35e78c48
feature(*): 添加续保、事故车转化成的专属线索
- 添加续保、事故车转化成的专属线索
Showing
11 changed files
with
301 additions
and
15 deletions
fw-valhalla-common/src/main/java/cn/fw/valhalla/common/utils/ThreadPoolUtil.java
0 → 100644
1 | +package cn.fw.valhalla.common.utils; | ||
2 | + | ||
3 | +import cn.hutool.core.thread.ExecutorBuilder; | ||
4 | + | ||
5 | +import java.util.concurrent.ExecutorService; | ||
6 | +import java.util.concurrent.LinkedBlockingQueue; | ||
7 | + | ||
8 | +/** | ||
9 | + * ThreadPoolUtl | ||
10 | + * | ||
11 | + * @author : kurisu | ||
12 | + * @version : 2.0 | ||
13 | + * @className : ThreadPoolUtl | ||
14 | + * @description : ThreadPoolUtl | ||
15 | + * @date : 2023-04-19 17:31 | ||
16 | + */ | ||
17 | +public class ThreadPoolUtil { | ||
18 | + private static volatile ThreadPoolUtil INSTANCE; | ||
19 | + private final ExecutorService executor; | ||
20 | + | ||
21 | + private ThreadPoolUtil() { | ||
22 | + this.executor = ExecutorBuilder.create() | ||
23 | + .setCorePoolSize(20) | ||
24 | + .setMaxPoolSize(60) | ||
25 | + .setWorkQueue(new LinkedBlockingQueue<>(4096)) | ||
26 | + .build(); | ||
27 | + } | ||
28 | + | ||
29 | + public static ThreadPoolUtil getInstance() { | ||
30 | + if (INSTANCE == null) { | ||
31 | + synchronized (ThreadPoolUtil.class) { | ||
32 | + if (INSTANCE == null) { | ||
33 | + INSTANCE = new ThreadPoolUtil(); | ||
34 | + } | ||
35 | + } | ||
36 | + } | ||
37 | + return INSTANCE; | ||
38 | + } | ||
39 | + | ||
40 | + public ExecutorService getExecutor() { | ||
41 | + return executor; | ||
42 | + } | ||
43 | +} |
fw-valhalla-domain/src/main/java/cn/fw/valhalla/domain/enums/PubStandType.java
@@ -22,6 +22,14 @@ public enum PubStandType implements IEnum<Integer> { | @@ -22,6 +22,14 @@ public enum PubStandType implements IEnum<Integer> { | ||
22 | * 市场活动 | 22 | * 市场活动 |
23 | */ | 23 | */ |
24 | ACTIVITY(2), | 24 | ACTIVITY(2), |
25 | + /** | ||
26 | + * 续保 | ||
27 | + */ | ||
28 | + IR(3), | ||
29 | + /** | ||
30 | + * 事故车 | ||
31 | + */ | ||
32 | + AC(4), | ||
25 | ; | 33 | ; |
26 | 34 | ||
27 | /** | 35 | /** |
fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/FollowTaskDealTask.java
1 | package cn.fw.valhalla.controller.task; | 1 | package cn.fw.valhalla.controller.task; |
2 | 2 | ||
3 | import cn.fw.valhalla.common.utils.DateUtil; | 3 | import cn.fw.valhalla.common.utils.DateUtil; |
4 | +import cn.fw.valhalla.common.utils.ThreadPoolUtil; | ||
4 | import cn.fw.valhalla.domain.db.follow.ClueTask; | 5 | import cn.fw.valhalla.domain.db.follow.ClueTask; |
5 | import cn.fw.valhalla.domain.db.follow.FollowClue; | 6 | import cn.fw.valhalla.domain.db.follow.FollowClue; |
6 | import cn.fw.valhalla.domain.enums.ClueStatusEnum; | 7 | import cn.fw.valhalla.domain.enums.ClueStatusEnum; |
@@ -18,6 +19,7 @@ import org.springframework.util.CollectionUtils; | @@ -18,6 +19,7 @@ import org.springframework.util.CollectionUtils; | ||
18 | import java.time.LocalDate; | 19 | import java.time.LocalDate; |
19 | import java.time.LocalDateTime; | 20 | import java.time.LocalDateTime; |
20 | import java.util.List; | 21 | import java.util.List; |
22 | +import java.util.concurrent.CompletableFuture; | ||
21 | 23 | ||
22 | /** | 24 | /** |
23 | * @author : kurisu | 25 | * @author : kurisu |
@@ -50,14 +52,15 @@ public class FollowTaskDealTask { | @@ -50,14 +52,15 @@ public class FollowTaskDealTask { | ||
50 | .eq(FollowClue::getClueState, ClueStatusEnum.WAITING) | 52 | .eq(FollowClue::getClueState, ClueStatusEnum.WAITING) |
51 | .gt(FollowClue::getStartTime, DateUtil.localDateTime2Date(LocalDate.now().minusDays(1L).atTime(23, 59, 59))) | 53 | .gt(FollowClue::getStartTime, DateUtil.localDateTime2Date(LocalDate.now().minusDays(1L).atTime(23, 59, 59))) |
52 | .le(FollowClue::getStartTime, DateUtil.localDateTime2Date(LocalDateTime.now())) | 54 | .le(FollowClue::getStartTime, DateUtil.localDateTime2Date(LocalDateTime.now())) |
53 | - .last("limit 0, 500") | 55 | + .last("limit 0, 300") |
54 | ); | 56 | ); |
55 | if (CollectionUtils.isEmpty(list)) { | 57 | if (CollectionUtils.isEmpty(list)) { |
56 | return; | 58 | return; |
57 | } | 59 | } |
58 | - for (FollowClue cluePool : list) { | ||
59 | - followBizService.startClue(cluePool); | ||
60 | - } | 60 | + CompletableFuture<Void>[] futures = list.stream() |
61 | + .map(clue -> CompletableFuture.runAsync(() -> followBizService.startClue(clue), ThreadPoolUtil.getInstance().getExecutor())) | ||
62 | + .<CompletableFuture<Void>>toArray(CompletableFuture[]::new); | ||
63 | + CompletableFuture.allOf(futures).join(); | ||
61 | } | 64 | } |
62 | 65 | ||
63 | /** | 66 | /** |
@@ -68,18 +71,18 @@ public class FollowTaskDealTask { | @@ -68,18 +71,18 @@ public class FollowTaskDealTask { | ||
68 | List<ClueTask> list = clueTaskService.list(Wrappers.<ClueTask>lambdaQuery() | 71 | List<ClueTask> list = clueTaskService.list(Wrappers.<ClueTask>lambdaQuery() |
69 | .eq(ClueTask::getState, TaskStateEnum.ONGOING) | 72 | .eq(ClueTask::getState, TaskStateEnum.ONGOING) |
70 | .le(ClueTask::getDeadline, LocalDateTime.now()) | 73 | .le(ClueTask::getDeadline, LocalDateTime.now()) |
71 | - .last("limit 0, 500") | 74 | + .last("limit 0, 300") |
72 | ); | 75 | ); |
73 | if (CollectionUtils.isEmpty(list)) { | 76 | if (CollectionUtils.isEmpty(list)) { |
74 | return; | 77 | return; |
75 | } | 78 | } |
76 | - for (ClueTask r : list) { | ||
77 | - followBizService.endTask(r); | ||
78 | - } | 79 | + CompletableFuture<Void>[] futures = list.stream() |
80 | + .map(task -> CompletableFuture.runAsync(() -> followBizService.endTask(task), ThreadPoolUtil.getInstance().getExecutor())) | ||
81 | + .<CompletableFuture<Void>>toArray(CompletableFuture[]::new); | ||
82 | + CompletableFuture.allOf(futures).join(); | ||
79 | } | 83 | } |
80 | 84 | ||
81 | 85 | ||
82 | - | ||
83 | /** | 86 | /** |
84 | * 任务结束同步状态到跟进系统 | 87 | * 任务结束同步状态到跟进系统 |
85 | */ | 88 | */ |
@@ -93,8 +96,9 @@ public class FollowTaskDealTask { | @@ -93,8 +96,9 @@ public class FollowTaskDealTask { | ||
93 | if (CollectionUtils.isEmpty(list)) { | 96 | if (CollectionUtils.isEmpty(list)) { |
94 | return; | 97 | return; |
95 | } | 98 | } |
96 | - for (ClueTask r : list) { | ||
97 | - followBizService.syncEndTask(r); | ||
98 | - } | 99 | + CompletableFuture<Void>[] futures = list.stream() |
100 | + .map(task -> CompletableFuture.runAsync(() -> followBizService.syncEndTask(task), ThreadPoolUtil.getInstance().getExecutor())) | ||
101 | + .<CompletableFuture<Void>>toArray(CompletableFuture[]::new); | ||
102 | + CompletableFuture.allOf(futures).join(); | ||
99 | } | 103 | } |
100 | } | 104 | } |
fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/PubFollowTask.java
@@ -45,6 +45,7 @@ public class PubFollowTask { | @@ -45,6 +45,7 @@ public class PubFollowTask { | ||
45 | @Getter(AccessLevel.PRIVATE) | 45 | @Getter(AccessLevel.PRIVATE) |
46 | private String pubClueCompleteKey; | 46 | private String pubClueCompleteKey; |
47 | 47 | ||
48 | + | ||
48 | public PubFollowTask(final StringRedisTemplate stringRedisTemplate, | 49 | public PubFollowTask(final StringRedisTemplate stringRedisTemplate, |
49 | final PubFollowBizService pubFollowBizService, | 50 | final PubFollowBizService pubFollowBizService, |
50 | final PubCluePoolService pubCluePoolService) { | 51 | final PubCluePoolService pubCluePoolService) { |
@@ -98,6 +99,7 @@ public class PubFollowTask { | @@ -98,6 +99,7 @@ public class PubFollowTask { | ||
98 | } | 99 | } |
99 | } | 100 | } |
100 | 101 | ||
102 | + | ||
101 | /** | 103 | /** |
102 | * 处理角色变动战败公共池跟进线索 | 104 | * 处理角色变动战败公共池跟进线索 |
103 | */ | 105 | */ |
fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/PubStandTask.java
@@ -2,10 +2,12 @@ package cn.fw.valhalla.controller.task; | @@ -2,10 +2,12 @@ package cn.fw.valhalla.controller.task; | ||
2 | 2 | ||
3 | import cn.fw.common.cache.locker.DistributedLocker; | 3 | import cn.fw.common.cache.locker.DistributedLocker; |
4 | import cn.fw.valhalla.common.utils.StringUtils; | 4 | import cn.fw.valhalla.common.utils.StringUtils; |
5 | +import cn.fw.valhalla.domain.db.pub.PubCluePool; | ||
5 | import cn.fw.valhalla.rpc.oop.OopService; | 6 | import cn.fw.valhalla.rpc.oop.OopService; |
6 | import cn.fw.valhalla.rpc.oop.dto.GroupDTO; | 7 | import cn.fw.valhalla.rpc.oop.dto.GroupDTO; |
7 | import cn.fw.valhalla.service.bus.pub.PubDistributeBizService; | 8 | import cn.fw.valhalla.service.bus.pub.PubDistributeBizService; |
8 | import cn.fw.valhalla.service.bus.pub.PubStandBizService; | 9 | import cn.fw.valhalla.service.bus.pub.PubStandBizService; |
10 | +import com.alibaba.fastjson.JSONObject; | ||
9 | import lombok.AccessLevel; | 11 | import lombok.AccessLevel; |
10 | import lombok.Getter; | 12 | import lombok.Getter; |
11 | import lombok.RequiredArgsConstructor; | 13 | import lombok.RequiredArgsConstructor; |
@@ -24,6 +26,7 @@ import org.springframework.util.CollectionUtils; | @@ -24,6 +26,7 @@ import org.springframework.util.CollectionUtils; | ||
24 | import java.time.MonthDay; | 26 | import java.time.MonthDay; |
25 | import java.util.ArrayList; | 27 | import java.util.ArrayList; |
26 | import java.util.List; | 28 | import java.util.List; |
29 | +import java.util.Objects; | ||
27 | import java.util.concurrent.CompletableFuture; | 30 | import java.util.concurrent.CompletableFuture; |
28 | import java.util.concurrent.TimeUnit; | 31 | import java.util.concurrent.TimeUnit; |
29 | 32 | ||
@@ -46,10 +49,16 @@ public class PubStandTask { | @@ -46,10 +49,16 @@ public class PubStandTask { | ||
46 | private final StringRedisTemplate redisTemplate; | 49 | private final StringRedisTemplate redisTemplate; |
47 | private final OopService oopService; | 50 | private final OopService oopService; |
48 | private final DistributedLocker distributedLocker; | 51 | private final DistributedLocker distributedLocker; |
52 | + private final StringRedisTemplate stringRedisTemplate; | ||
53 | + | ||
49 | @Value("${spring.cache.custom.global-prefix}:stand:pub") | 54 | @Value("${spring.cache.custom.global-prefix}:stand:pub") |
50 | @Getter(AccessLevel.PRIVATE) | 55 | @Getter(AccessLevel.PRIVATE) |
51 | private String keyPrefix; | 56 | private String keyPrefix; |
52 | 57 | ||
58 | + @Value("${spring.cache.custom.global-prefix}:pub:distribute:fromClue") | ||
59 | + @Getter(AccessLevel.PRIVATE) | ||
60 | + private String fromClueCacheKey; | ||
61 | + | ||
53 | /** | 62 | /** |
54 | * 重置状态 | 63 | * 重置状态 |
55 | */ | 64 | */ |
@@ -69,6 +78,37 @@ public class PubStandTask { | @@ -69,6 +78,37 @@ public class PubStandTask { | ||
69 | } | 78 | } |
70 | } | 79 | } |
71 | 80 | ||
81 | + /** | ||
82 | + * 线索开始跟进后建立专属线索关系(如果能的话) | ||
83 | + */ | ||
84 | + @Scheduled(initialDelay = 1000 * 10, fixedRate = 1000 * 10) | ||
85 | + public void dealFromClue() { | ||
86 | + BoundListOperations<String, String> listOps = stringRedisTemplate.boundListOps(getFromClueCacheKey()); | ||
87 | + List<String> failList = new ArrayList<>(); | ||
88 | + String objectStr; | ||
89 | + while ((objectStr = listOps.leftPop()) != null) { | ||
90 | + if (!StringUtils.isEmpty(objectStr)) { | ||
91 | + continue; | ||
92 | + } | ||
93 | + try { | ||
94 | + PubCluePool cluePool = JSONObject.parseObject(objectStr, PubCluePool.class); | ||
95 | + if (Objects.isNull(cluePool)) { | ||
96 | + continue; | ||
97 | + } | ||
98 | + pubDistributeBizService.distributeFromClue(cluePool); | ||
99 | + } catch (Exception e) { | ||
100 | + if (StringUtils.isValid(objectStr)) { | ||
101 | + failList.add(objectStr); | ||
102 | + } | ||
103 | + log.error("线索开始跟进后建立专属线索关系失败", e); | ||
104 | + } | ||
105 | + } | ||
106 | + if (!CollectionUtils.isEmpty(failList)) { | ||
107 | + String[] idArr = failList.toArray(new String[0]); | ||
108 | + listOps.rightPushAll(idArr); | ||
109 | + } | ||
110 | + } | ||
111 | + | ||
72 | private void doDistribute(GroupDTO group) { | 112 | private void doDistribute(GroupDTO group) { |
73 | final String key = generateKey(group.getId()); | 113 | final String key = generateKey(group.getId()); |
74 | final String lockKey = String.format("pub:distribute:%s", group.getId()); | 114 | final String lockKey = String.format("pub:distribute:%s", group.getId()); |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/impl/ACFollowStrategy.java
@@ -19,14 +19,17 @@ import cn.fw.valhalla.rpc.oop.dto.ShopDTO; | @@ -19,14 +19,17 @@ import cn.fw.valhalla.rpc.oop.dto.ShopDTO; | ||
19 | import cn.fw.valhalla.rpc.shirasawa.dto.FollowInitDTO; | 19 | import cn.fw.valhalla.rpc.shirasawa.dto.FollowInitDTO; |
20 | import cn.fw.valhalla.service.bus.follow.strategy.AbstractFollowStrategy; | 20 | import cn.fw.valhalla.service.bus.follow.strategy.AbstractFollowStrategy; |
21 | import cn.fw.valhalla.service.data.AccidentPoolService; | 21 | import cn.fw.valhalla.service.data.AccidentPoolService; |
22 | +import cn.fw.valhalla.service.event.ClueFromPublicEvent; | ||
22 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | 23 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
23 | import lombok.extern.slf4j.Slf4j; | 24 | import lombok.extern.slf4j.Slf4j; |
24 | import org.springframework.beans.factory.annotation.Autowired; | 25 | import org.springframework.beans.factory.annotation.Autowired; |
26 | +import org.springframework.context.ApplicationEventPublisher; | ||
25 | import org.springframework.stereotype.Component; | 27 | import org.springframework.stereotype.Component; |
26 | import org.springframework.transaction.annotation.Transactional; | 28 | import org.springframework.transaction.annotation.Transactional; |
27 | 29 | ||
28 | import java.time.Duration; | 30 | import java.time.Duration; |
29 | import java.util.*; | 31 | import java.util.*; |
32 | +import java.util.concurrent.CompletableFuture; | ||
30 | 33 | ||
31 | import static cn.fw.common.businessvalidator.Validator.BV; | 34 | import static cn.fw.common.businessvalidator.Validator.BV; |
32 | import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID; | 35 | import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID; |
@@ -42,10 +45,13 @@ import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON | @@ -42,10 +45,13 @@ import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON | ||
42 | public class ACFollowStrategy extends AbstractFollowStrategy { | 45 | public class ACFollowStrategy extends AbstractFollowStrategy { |
43 | 46 | ||
44 | private final AccidentPoolService accidentPoolService; | 47 | private final AccidentPoolService accidentPoolService; |
48 | + private final ApplicationEventPublisher eventPublisher; | ||
45 | 49 | ||
46 | @Autowired | 50 | @Autowired |
47 | - public ACFollowStrategy(final AccidentPoolService accidentPoolService) { | 51 | + public ACFollowStrategy(final AccidentPoolService accidentPoolService, |
52 | + final ApplicationEventPublisher eventPublisher) { | ||
48 | this.accidentPoolService = accidentPoolService; | 53 | this.accidentPoolService = accidentPoolService; |
54 | + this.eventPublisher = eventPublisher; | ||
49 | } | 55 | } |
50 | 56 | ||
51 | @Override | 57 | @Override |
@@ -74,6 +80,16 @@ public class ACFollowStrategy extends AbstractFollowStrategy { | @@ -74,6 +80,16 @@ public class ACFollowStrategy extends AbstractFollowStrategy { | ||
74 | BV.isNotEmpty(userByRole, () -> "该门店没有事故车跟进人员"); | 80 | BV.isNotEmpty(userByRole, () -> "该门店没有事故车跟进人员"); |
75 | fillTaskUser(clueTask, userByRole); | 81 | fillTaskUser(clueTask, userByRole); |
76 | 82 | ||
83 | + if (StringUtils.isValid(followClue.getVin())) { | ||
84 | + final ClueFromPublicEvent poolEvent = new ClueFromPublicEvent(); | ||
85 | + poolEvent.setVin(followClue.getVin()); | ||
86 | + poolEvent.setShopId(clueTask.getFollowShop()); | ||
87 | + poolEvent.setGroupId(clueTask.getGroupId()); | ||
88 | + poolEvent.setUserId(clueTask.getFollowUser()); | ||
89 | + poolEvent.setType(PubStandType.AC); | ||
90 | + CompletableFuture.runAsync(() -> eventPublisher.publishEvent(poolEvent)); | ||
91 | + } | ||
92 | + | ||
77 | followClue.setClueState(ClueStatusEnum.ONGOING); | 93 | followClue.setClueState(ClueStatusEnum.ONGOING); |
78 | clueTaskService.save(clueTask); | 94 | clueTaskService.save(clueTask); |
79 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); | 95 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/strategy/impl/IRFollowStrategy.java
@@ -16,16 +16,19 @@ import cn.fw.valhalla.rpc.oop.dto.ShopDTO; | @@ -16,16 +16,19 @@ import cn.fw.valhalla.rpc.oop.dto.ShopDTO; | ||
16 | import cn.fw.valhalla.rpc.shirasawa.dto.FollowInitDTO; | 16 | import cn.fw.valhalla.rpc.shirasawa.dto.FollowInitDTO; |
17 | import cn.fw.valhalla.service.bus.follow.strategy.AbstractFollowStrategy; | 17 | import cn.fw.valhalla.service.bus.follow.strategy.AbstractFollowStrategy; |
18 | import cn.fw.valhalla.service.data.CustomerReachLogService; | 18 | import cn.fw.valhalla.service.data.CustomerReachLogService; |
19 | +import cn.fw.valhalla.service.event.ClueFromPublicEvent; | ||
19 | import cn.hutool.core.collection.ListUtil; | 20 | import cn.hutool.core.collection.ListUtil; |
20 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; | 21 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
21 | import lombok.extern.slf4j.Slf4j; | 22 | import lombok.extern.slf4j.Slf4j; |
22 | import org.springframework.beans.factory.annotation.Autowired; | 23 | import org.springframework.beans.factory.annotation.Autowired; |
24 | +import org.springframework.context.ApplicationEventPublisher; | ||
23 | import org.springframework.stereotype.Component; | 25 | import org.springframework.stereotype.Component; |
24 | import org.springframework.transaction.annotation.Transactional; | 26 | import org.springframework.transaction.annotation.Transactional; |
25 | 27 | ||
26 | import java.time.LocalDate; | 28 | import java.time.LocalDate; |
27 | import java.time.LocalDateTime; | 29 | import java.time.LocalDateTime; |
28 | import java.util.*; | 30 | import java.util.*; |
31 | +import java.util.concurrent.CompletableFuture; | ||
29 | 32 | ||
30 | import static cn.fw.common.businessvalidator.Validator.BV; | 33 | import static cn.fw.common.businessvalidator.Validator.BV; |
31 | import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID; | 34 | import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON_BRAND_ID; |
@@ -41,10 +44,13 @@ import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON | @@ -41,10 +44,13 @@ import static cn.fw.valhalla.service.bus.setting.strategy.SettingStrategy.COMMON | ||
41 | @SuppressWarnings("Duplicates") | 44 | @SuppressWarnings("Duplicates") |
42 | public class IRFollowStrategy extends AbstractFollowStrategy { | 45 | public class IRFollowStrategy extends AbstractFollowStrategy { |
43 | private final CustomerReachLogService customerReachLogService; | 46 | private final CustomerReachLogService customerReachLogService; |
47 | + private final ApplicationEventPublisher eventPublisher; | ||
44 | 48 | ||
45 | @Autowired | 49 | @Autowired |
46 | - public IRFollowStrategy(final CustomerReachLogService customerReachLogService) { | 50 | + public IRFollowStrategy(final CustomerReachLogService customerReachLogService, |
51 | + final ApplicationEventPublisher eventPublisher) { | ||
47 | this.customerReachLogService = customerReachLogService; | 52 | this.customerReachLogService = customerReachLogService; |
53 | + this.eventPublisher = eventPublisher; | ||
48 | } | 54 | } |
49 | 55 | ||
50 | @Override | 56 | @Override |
@@ -109,6 +115,15 @@ public class IRFollowStrategy extends AbstractFollowStrategy { | @@ -109,6 +115,15 @@ public class IRFollowStrategy extends AbstractFollowStrategy { | ||
109 | } | 115 | } |
110 | BV.isNotEmpty(userByRole, () -> String.format("该门店[mode: %s]没有【跟进】人员", mode)); | 116 | BV.isNotEmpty(userByRole, () -> String.format("该门店[mode: %s]没有【跟进】人员", mode)); |
111 | fillTaskUser(clueTask, userByRole); | 117 | fillTaskUser(clueTask, userByRole); |
118 | + if (mode == 2 && Objects.isNull(customer.getAdviserId())) { | ||
119 | + final ClueFromPublicEvent poolEvent = new ClueFromPublicEvent(); | ||
120 | + poolEvent.setVin(customer.getFrameNo()); | ||
121 | + poolEvent.setShopId(clueTask.getFollowShop()); | ||
122 | + poolEvent.setUserId(clueTask.getFollowUser()); | ||
123 | + poolEvent.setType(PubStandType.IR); | ||
124 | + poolEvent.setGroupId(clueTask.getGroupId()); | ||
125 | + CompletableFuture.runAsync(() -> eventPublisher.publishEvent(poolEvent)); | ||
126 | + } | ||
112 | clueTaskService.save(clueTask); | 127 | clueTaskService.save(clueTask); |
113 | followClue.setClueState(ClueStatusEnum.ONGOING); | 128 | followClue.setClueState(ClueStatusEnum.ONGOING); |
114 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); | 129 | final FollowInitDTO followInitDTO = creteFollowInitDTO(followClue, clueTask); |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/listener/ClueFromPublicListener.java
0 → 100644
1 | +package cn.fw.valhalla.service.bus.listener; | ||
2 | + | ||
3 | +import cn.fw.valhalla.domain.db.pub.PubCluePool; | ||
4 | +import cn.fw.valhalla.domain.enums.PubStandType; | ||
5 | +import cn.fw.valhalla.domain.enums.PublicClueStateEnum; | ||
6 | +import cn.fw.valhalla.service.bus.pub.PubDistributeBizService; | ||
7 | +import cn.fw.valhalla.service.event.ClueFromPublicEvent; | ||
8 | +import com.alibaba.fastjson.JSONObject; | ||
9 | +import lombok.AccessLevel; | ||
10 | +import lombok.Getter; | ||
11 | +import lombok.extern.slf4j.Slf4j; | ||
12 | +import org.springframework.beans.factory.annotation.Autowired; | ||
13 | +import org.springframework.beans.factory.annotation.Value; | ||
14 | +import org.springframework.context.event.EventListener; | ||
15 | +import org.springframework.data.redis.core.StringRedisTemplate; | ||
16 | +import org.springframework.stereotype.Component; | ||
17 | + | ||
18 | +import java.time.LocalDate; | ||
19 | + | ||
20 | +/** | ||
21 | + * 产生线索建立专属线索监听 | ||
22 | + * | ||
23 | + * @author : kurisu | ||
24 | + * @version : 2.0 | ||
25 | + * @className : ClueFromPublicListener | ||
26 | + * @description : 产生线索建立专属线索监听 | ||
27 | + * @date : 2023-04-26 11:05 | ||
28 | + */ | ||
29 | + | ||
30 | +@Component | ||
31 | +@Slf4j | ||
32 | +public class ClueFromPublicListener { | ||
33 | + private final PubDistributeBizService pubDistributeBizService; | ||
34 | + private final StringRedisTemplate stringRedisTemplate; | ||
35 | + | ||
36 | + @Value("${spring.cache.custom.global-prefix}:pub:distribute:fromClue") | ||
37 | + @Getter(AccessLevel.PRIVATE) | ||
38 | + private String cacheKey; | ||
39 | + | ||
40 | + @Autowired | ||
41 | + public ClueFromPublicListener(final PubDistributeBizService pubDistributeBizService, | ||
42 | + final StringRedisTemplate stringRedisTemplate) { | ||
43 | + this.pubDistributeBizService = pubDistributeBizService; | ||
44 | + this.stringRedisTemplate = stringRedisTemplate; | ||
45 | + } | ||
46 | + | ||
47 | + | ||
48 | + /** | ||
49 | + * 跟进线索产生时档案建立专属线索关系 | ||
50 | + * | ||
51 | + * @param event | ||
52 | + */ | ||
53 | + @EventListener(ClueFromPublicEvent.class) | ||
54 | + public void stopTaskAndAddPublic(final ClueFromPublicEvent event) { | ||
55 | + final String vin = event.getVin(); | ||
56 | + final Long shopId = event.getShopId(); | ||
57 | + final Long groupId = event.getShopId(); | ||
58 | + final Long userId = event.getUserId(); | ||
59 | + final PubStandType type = event.getType(); | ||
60 | + | ||
61 | + final PubCluePool pool = new PubCluePool(); | ||
62 | + pool.setVin(vin); | ||
63 | + pool.setStartTime(LocalDate.now()); | ||
64 | + pool.setState(PublicClueStateEnum.ONGOING); | ||
65 | + pool.setBegun(Boolean.FALSE); | ||
66 | + pool.setSourceType(type); | ||
67 | + pool.setAdviserId(userId); | ||
68 | + pool.setShopId(shopId); | ||
69 | + pool.setGroupId(groupId); | ||
70 | + try { | ||
71 | + pubDistributeBizService.distributeFromClue(pool); | ||
72 | + } catch (Exception e) { | ||
73 | + stringRedisTemplate.opsForList().rightPush(getCacheKey(), JSONObject.toJSONString(pool)); | ||
74 | + log.error("跟进线索产生时档案建立专属线索关系失败", e); | ||
75 | + } | ||
76 | + } | ||
77 | +} |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/CustomEventListener.java renamed to fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/listener/CustomEventListener.java
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/pub/PubDistributeBizService.java
@@ -6,12 +6,15 @@ import cn.fw.valhalla.domain.db.customer.AffiliationRecord; | @@ -6,12 +6,15 @@ import cn.fw.valhalla.domain.db.customer.AffiliationRecord; | ||
6 | import cn.fw.valhalla.domain.db.customer.Customer; | 6 | import cn.fw.valhalla.domain.db.customer.Customer; |
7 | import cn.fw.valhalla.domain.db.follow.ClueTask; | 7 | import cn.fw.valhalla.domain.db.follow.ClueTask; |
8 | import cn.fw.valhalla.domain.db.follow.FollowClue; | 8 | import cn.fw.valhalla.domain.db.follow.FollowClue; |
9 | +import cn.fw.valhalla.domain.db.pool.PublicPool; | ||
9 | import cn.fw.valhalla.domain.db.pool.StammkundePool; | 10 | import cn.fw.valhalla.domain.db.pool.StammkundePool; |
10 | import cn.fw.valhalla.domain.db.pub.PubCluePool; | 11 | import cn.fw.valhalla.domain.db.pub.PubCluePool; |
11 | import cn.fw.valhalla.domain.db.pub.PubStandStaffInfo; | 12 | import cn.fw.valhalla.domain.db.pub.PubStandStaffInfo; |
12 | import cn.fw.valhalla.domain.enums.*; | 13 | import cn.fw.valhalla.domain.enums.*; |
13 | import cn.fw.valhalla.domain.vo.setting.SettingVO; | 14 | import cn.fw.valhalla.domain.vo.setting.SettingVO; |
15 | +import cn.fw.valhalla.rpc.ehr.EhrRpcService; | ||
14 | import cn.fw.valhalla.rpc.erp.UserService; | 16 | import cn.fw.valhalla.rpc.erp.UserService; |
17 | +import cn.fw.valhalla.rpc.erp.dto.UserInfoDTO; | ||
15 | import cn.fw.valhalla.rpc.erp.dto.UserRoleDataRangeDTO; | 18 | import cn.fw.valhalla.rpc.erp.dto.UserRoleDataRangeDTO; |
16 | import cn.fw.valhalla.rpc.mkt.MktRpcService; | 19 | import cn.fw.valhalla.rpc.mkt.MktRpcService; |
17 | import cn.fw.valhalla.rpc.mkt.dto.QualificationDTO; | 20 | import cn.fw.valhalla.rpc.mkt.dto.QualificationDTO; |
@@ -50,6 +53,7 @@ import java.util.stream.Collectors; | @@ -50,6 +53,7 @@ import java.util.stream.Collectors; | ||
50 | public class PubDistributeBizService { | 53 | public class PubDistributeBizService { |
51 | private final OopService oopService; | 54 | private final OopService oopService; |
52 | private final UserService userService; | 55 | private final UserService userService; |
56 | + private final EhrRpcService ehrRpcService; | ||
53 | private final FollowClueService followClueService; | 57 | private final FollowClueService followClueService; |
54 | private final ClueTaskService clueTaskService; | 58 | private final ClueTaskService clueTaskService; |
55 | private final ShirasawaRpcService shirasawaRpcService; | 59 | private final ShirasawaRpcService shirasawaRpcService; |
@@ -123,6 +127,39 @@ public class PubDistributeBizService { | @@ -123,6 +127,39 @@ public class PubDistributeBizService { | ||
123 | } | 127 | } |
124 | 128 | ||
125 | /** | 129 | /** |
130 | + * 线索开始跟进后建立专属线索关系(如果能的话) | ||
131 | + * | ||
132 | + * @param pubClue | ||
133 | + */ | ||
134 | + @Transactional(rollbackFor = Exception.class) | ||
135 | + public void distributeFromClue(final PubCluePool pubClue) { | ||
136 | + Customer customer = customerService.queryByEngineNo(pubClue.getVin(), pubClue.getGroupId()); | ||
137 | + if (Objects.isNull(customer)) { | ||
138 | + return; | ||
139 | + } | ||
140 | + PublicPool publicPool = publicPoolService.queryByVin(pubClue.getVin(), pubClue.getGroupId()); | ||
141 | + if (Objects.isNull(publicPool)) { | ||
142 | + return; | ||
143 | + } | ||
144 | + if (Objects.nonNull(customer.getAdviserId())) { | ||
145 | + return; | ||
146 | + } | ||
147 | + Optional<SettingVO> settingVO = settingBizService.querySettingByType(FollowTypeEnum.OT, SettingTypeEnum.PUBLIC_VALID_DAY, pubClue.getGroupId(), null); | ||
148 | + int publicValidDay = settingVO.map(SettingVO::getDetailValue).orElse(60); | ||
149 | + pubClue.setDeadline(LocalDate.now().plusDays(publicValidDay)); | ||
150 | + | ||
151 | + UserInfoDTO user = ehrRpcService.user(pubClue.getAdviserId()); | ||
152 | + if (Objects.nonNull(user)) { | ||
153 | + pubClue.setAdviserName(user.getUserName()); | ||
154 | + } | ||
155 | + ShopDTO shop = oopService.shop(pubClue.getShopId()); | ||
156 | + if (Objects.nonNull(shop)) { | ||
157 | + pubClue.setShopName(shop.getShortName()); | ||
158 | + } | ||
159 | + createPubRelation(pubClue, customer.getId()); | ||
160 | + } | ||
161 | + | ||
162 | + /** | ||
126 | * 查询门店 | 163 | * 查询门店 |
127 | * | 164 | * |
128 | * @param staffInfo | 165 | * @param staffInfo |
@@ -384,4 +421,26 @@ public class PubDistributeBizService { | @@ -384,4 +421,26 @@ public class PubDistributeBizService { | ||
384 | return true; | 421 | return true; |
385 | } | 422 | } |
386 | 423 | ||
424 | + private void createPubRelation(PubCluePool pool, Long customerId) { | ||
425 | + Long staffId = pool.getAdviserId(); | ||
426 | + Long shopId = pool.getShopId(); | ||
427 | + Long groupId = pool.getGroupId(); | ||
428 | + String vin = pool.getVin(); | ||
429 | + | ||
430 | + StammkundePool stammkundePool = new StammkundePool(); | ||
431 | + stammkundePool.setCustomerId(customerId); | ||
432 | + stammkundePool.setShopId(shopId); | ||
433 | + stammkundePool.setGroupId(groupId); | ||
434 | + stammkundePool.setAktiv(Boolean.FALSE); | ||
435 | + stammkundePool.setCreateTime(new Date()); | ||
436 | + stammkundePool.setAdviserId(staffId); | ||
437 | + stammkundePool.setAdviserName(pool.getAdviserName()); | ||
438 | + stammkundePool.setSources(StammkundeSourcesEnum.PUBLIC_POOL); | ||
439 | + stammkundePool.setPoolStatus(StammkundeStatusEnum.PUBLIC); | ||
440 | + | ||
441 | + customerService.afterDistributePubClue(Collections.singletonList(vin), staffId, shopId, groupId); | ||
442 | + pubCluePoolService.save(pool); | ||
443 | + stammkundePoolService.save(stammkundePool); | ||
444 | + publicPoolService.removeByVin(vin, groupId); | ||
445 | + } | ||
387 | } | 446 | } |
fw-valhalla-service/src/main/java/cn/fw/valhalla/service/event/ClueFromPublicEvent.java
0 → 100644
1 | +package cn.fw.valhalla.service.event; | ||
2 | + | ||
3 | +import cn.fw.valhalla.domain.enums.PubStandType; | ||
4 | +import lombok.Data; | ||
5 | + | ||
6 | +/** | ||
7 | + * 产生线索是档案在公共池 | ||
8 | + * | ||
9 | + * @author : kurisu | ||
10 | + * @version : 2.0 | ||
11 | + * @className : ClueFromPublicEvent | ||
12 | + * @description : 产生线索是档案在公共池 | ||
13 | + * @date : 2023-04-26 10:37 | ||
14 | + */ | ||
15 | +@Data | ||
16 | +public class ClueFromPublicEvent { | ||
17 | + private String vin; | ||
18 | + private Long userId; | ||
19 | + private Long shopId; | ||
20 | + private Long groupId; | ||
21 | + private PubStandType type; | ||
22 | +} |