Blame view

fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/follow/FollowBizService.java 23.9 KB
045bdcc2   张志伟   :art:
1
2
  package cn.fw.valhalla.service.bus.follow;
  
fa966283   张志伟   📝 v1.0.1调整
3
  import cn.fw.common.cache.locker.DistributedLocker;
65610b54   张志伟   :art:
4
5
  import cn.fw.common.page.AppPage;
  import cn.fw.common.web.auth.LoginAuthBean;
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
6
7
  import cn.fw.valhalla.common.utils.DateUtil;
  import cn.fw.valhalla.domain.db.ApproveRecord;
ad395b9c   张志伟   :art:
8
  import cn.fw.valhalla.domain.db.OriginalData;
8c7566e0   张志伟   :sparkles:
9
  import cn.fw.valhalla.domain.db.SecretReportHistory;
612d25d9   张志伟   :art:
10
  import cn.fw.valhalla.domain.db.follow.FollowRecord;
8c7566e0   张志伟   :sparkles:
11
  import cn.fw.valhalla.domain.db.follow.FollowRecordLog;
23b952c1   张志伟   :art:
12
  import cn.fw.valhalla.domain.db.follow.FollowTask;
8587e21d   张志伟   :art:
13
  import cn.fw.valhalla.domain.db.pool.CustomerCluePool;
bff962f1   张志伟   :sparkles:
14
  import cn.fw.valhalla.domain.dto.CallReportDTO;
b2f969bd   张志伟   :art:
15
  import cn.fw.valhalla.domain.dto.FollowAttachmentDTO;
bff962f1   张志伟   :sparkles:
16
  import cn.fw.valhalla.domain.enums.*;
65610b54   张志伟   :art:
17
  import cn.fw.valhalla.domain.query.FollowQueryVO;
b2f969bd   张志伟   :art:
18
19
  import cn.fw.valhalla.domain.vo.follow.FollowDetailVO;
  import cn.fw.valhalla.domain.vo.follow.FollowRecordVO;
65610b54   张志伟   :art:
20
  import cn.fw.valhalla.domain.vo.follow.FollowTodoListVO;
08704989   张志伟   :art:
21
  import cn.fw.valhalla.domain.vo.setting.SettingVO;
5c35d8ab   张志伟   :bug:
22
23
  import cn.fw.valhalla.rpc.erp.UserService;
  import cn.fw.valhalla.rpc.erp.dto.UserInfoDTO;
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
24
  import cn.fw.valhalla.rpc.flow.FlowApproveRpc;
5f212858   张志伟   ✨ 公共池接口 100%
25
  import cn.fw.valhalla.rpc.flow.dto.FlowDto;
08704989   张志伟   :art:
26
  import cn.fw.valhalla.sdk.enums.DataTypeEnum;
65610b54   张志伟   :art:
27
  import cn.fw.valhalla.service.bus.follow.strategy.FollowStrategy;
8c7566e0   张志伟   :sparkles:
28
  import cn.fw.valhalla.service.data.*;
08704989   张志伟   :art:
29
  import cn.fw.valhalla.service.event.TaskCancelEvent;
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
30
  import com.baomidou.mybatisplus.core.toolkit.Wrappers;
c4fb2fa5   张志伟   ✨ 公共池接口 100%
31
  import lombok.Getter;
045bdcc2   张志伟   :art:
32
  import lombok.extern.slf4j.Slf4j;
fa966283   张志伟   📝 v1.0.1调整
33
34
  import org.apache.commons.lang3.tuple.Pair;
  import org.redisson.api.RLock;
65610b54   张志伟   :art:
35
  import org.springframework.beans.factory.annotation.Autowired;
c4fb2fa5   张志伟   ✨ 公共池接口 100%
36
  import org.springframework.beans.factory.annotation.Value;
045bdcc2   张志伟   :art:
37
  import org.springframework.stereotype.Service;
08704989   张志伟   :art:
38
  import org.springframework.transaction.annotation.Transactional;
65610b54   张志伟   :art:
39
  import org.springframework.util.Assert;
03b7b995   张志伟   ✨ 公共池后端逻辑 100%
40
  import org.springframework.util.CollectionUtils;
65610b54   张志伟   :art:
41
  
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
42
  import java.time.LocalDateTime;
c4fb2fa5   张志伟   ✨ 公共池接口 100%
43
  import java.util.*;
fa966283   张志伟   📝 v1.0.1调整
44
  import java.util.concurrent.TimeUnit;
65610b54   张志伟   :art:
45
  import java.util.stream.Collectors;
045bdcc2   张志伟   :art:
46
  
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
47
48
  import static cn.fw.common.businessvalidator.Validator.BV;
  
045bdcc2   张志伟   :art:
49
50
51
52
53
54
55
56
57
  /**
   * @author : kurisu
   * @className : FollowBizService
   * @description : 跟进业务服务
   * @date: 2020-08-14 17:27
   */
  @Slf4j
  @Service
  public class FollowBizService {
65610b54   张志伟   :art:
58
59
60
61
      /**
       * 跟进处理器map
       */
      private final Map<FollowTypeEnum, FollowStrategy> followMap;
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
62
63
64
65
      private final FlowApproveRpc flowApproveRpc;
      private final ApproveRecordService approveRecordService;
      private final FollowTaskService followTaskService;
      private final FollowRecordService followRecordService;
5c35d8ab   张志伟   :bug:
66
      private final UserService userService;
fa966283   张志伟   📝 v1.0.1调整
67
      private final DistributedLocker distributedLocker;
dac2e8b1   张志伟   :art:
68
      private final CustomerCluePoolService customerCluePoolService;
8c7566e0   张志伟   :sparkles:
69
70
      private final SecretReportHistoryService secretReportHistoryService;
      private final FollowRecordLogService followRecordLogService;
65610b54   张志伟   :art:
71
  
dc0c7fbf   张志伟   :bug:
72
      @Value("${follow.flowNo}")
c4fb2fa5   张志伟   ✨ 公共池接口 100%
73
74
75
      @Getter
      private String flowNo;
  
fa966283   张志伟   📝 v1.0.1调整
76
77
78
79
      @Value("${spring.cache.custom.global-prefix}:defeat")
      @Getter
      private String keyPrefix;
  
65610b54   张志伟   :art:
80
      @Autowired
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
81
82
83
84
      public FollowBizService(final List<FollowStrategy> followStrategyList,
                              final FlowApproveRpc flowApproveRpc,
                              final ApproveRecordService approveRecordService,
                              final FollowTaskService followTaskService,
5c35d8ab   张志伟   :bug:
85
                              final FollowRecordService followRecordService,
fa966283   张志伟   📝 v1.0.1调整
86
                              final UserService userService,
dac2e8b1   张志伟   :art:
87
                              final DistributedLocker distributedLocker,
8c7566e0   张志伟   :sparkles:
88
89
90
                              final CustomerCluePoolService customerCluePoolService,
                              final SecretReportHistoryService secretReportHistoryService,
                              final FollowRecordLogService followRecordLogService) {
65610b54   张志伟   :art:
91
          this.followMap = followStrategyList.stream().collect(Collectors.toMap(FollowStrategy::getFollowType, v -> v));
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
92
93
94
95
          this.flowApproveRpc = flowApproveRpc;
          this.approveRecordService = approveRecordService;
          this.followTaskService = followTaskService;
          this.followRecordService = followRecordService;
5c35d8ab   张志伟   :bug:
96
          this.userService = userService;
fa966283   张志伟   📝 v1.0.1调整
97
          this.distributedLocker = distributedLocker;
dac2e8b1   张志伟   :art:
98
          this.customerCluePoolService = customerCluePoolService;
8c7566e0   张志伟   :sparkles:
99
100
          this.secretReportHistoryService = secretReportHistoryService;
          this.followRecordLogService = followRecordLogService;
65610b54   张志伟   :art:
101
102
      }
  
b2f969bd   张志伟   :art:
103
104
105
106
107
108
109
      /**
       * 查询待办列表
       *
       * @param queryVO
       * @param currentUser
       * @return
       */
65610b54   张志伟   :art:
110
111
112
113
114
115
116
117
118
119
120
      public AppPage<FollowTodoListVO> todoList(FollowQueryVO queryVO, LoginAuthBean currentUser) {
          Integer pageSize = queryVO.getPageSize();
          Integer current = queryVO.getCurrent();
          Integer startIndex = (current - 1) * pageSize;
          FollowStrategy strategy = followMap.get(queryVO.getType());
          Assert.notNull(strategy, "strategy cannot be null");
          List<FollowTodoListVO> list = strategy.getList(startIndex, pageSize, currentUser.getUserId());
          AppPage<FollowTodoListVO> appPage = AppPage.empty(queryVO);
          appPage.setData(list);
          return appPage;
      }
b2f969bd   张志伟   :art:
121
122
123
124
125
126
  
      /**
       * 查询待办详情
       *
       * @param id
       * @param type
b2f969bd   张志伟   :art:
127
128
       * @return
       */
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
129
      public FollowDetailVO todoDetail(Long id, FollowTypeEnum type) {
b2f969bd   张志伟   :art:
130
131
          FollowStrategy strategy = followMap.get(type);
          Assert.notNull(strategy, "strategy cannot be null");
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
132
          return strategy.getDetail(id);
b2f969bd   张志伟   :art:
133
134
135
136
137
138
139
140
141
      }
  
      /**
       * 查询跟进历史
       *
       * @param taskId
       * @param type
       * @return
       */
51a118ce   张志伟   :sparkles:
142
143
144
145
146
147
148
149
150
      public List<FollowRecordVO> todoRecord(Long taskId, Integer type) {
          FollowTypeEnum typeEnum = FollowTypeEnum.ofValue(type);
          if (Objects.isNull(typeEnum)) {
              FollowTask task = followTaskService.getById(taskId);
              BV.notNull(task, () -> "跟进任务不存在");
              typeEnum = task.getType();
          }
          FollowStrategy strategy = followMap.get(typeEnum);
          BV.notNull(strategy, () -> "跟进类型不正确");
b2f969bd   张志伟   :art:
151
152
153
154
          return strategy.getRecordList(taskId);
      }
  
      /**
fa966283   张志伟   📝 v1.0.1调整
155
156
157
158
159
160
161
162
163
164
165
166
167
168
       * 查询跟进池详情
       *
       * @param taskId
       * @return
       */
      public FollowDetailVO followPoolDetail(Long taskId) {
          FollowTask task = followTaskService.getById(taskId);
          BV.notNull(task, () -> "跟进线索不存在,请刷新列表");
          FollowStrategy strategy = followMap.get(task.getType());
          Assert.notNull(strategy, "strategy cannot be null");
          return strategy.followPoolDetail(task);
      }
  
      /**
b2f969bd   张志伟   :art:
169
170
171
172
173
       * 完成跟进
       *
       * @param id
       * @param currentUser
       */
08704989   张志伟   :art:
174
      @Transactional(rollbackFor = Exception.class)
b2f969bd   张志伟   :art:
175
176
177
178
179
180
181
      public void completeRecord(Long id, FollowTypeEnum type, LoginAuthBean currentUser) {
          FollowStrategy strategy = followMap.get(type);
          Assert.notNull(strategy, "strategy cannot be null");
          strategy.completeRecord(id, currentUser);
      }
  
      /**
93dbde02   张志伟   :construction:
182
183
184
185
186
       * 完成跟进
       *
       * @param record
       */
      @Transactional(rollbackFor = Exception.class)
ee39ce19   张志伟   :sparkles:
187
      public void completeRecordAndEnd(FollowRecord record) {
93dbde02   张志伟   :construction:
188
189
          FollowStrategy strategy = followMap.get(record.getType());
          Assert.notNull(strategy, "strategy cannot be null");
ee39ce19   张志伟   :sparkles:
190
          strategy.completeRecordAndEnd(record);
93dbde02   张志伟   :construction:
191
192
193
      }
  
      /**
8587e21d   张志伟   :art:
194
       * 首保流失客户二次分配后更新跟进任务
dac2e8b1   张志伟   :art:
195
       *
8587e21d   张志伟   :art:
196
197
198
199
200
201
202
203
204
205
206
       * @param customerId
       * @param type
       */
      @Transactional(rollbackFor = Exception.class)
      public void updateTask(Long customerId, FollowTypeEnum type) {
          FollowStrategy strategy = followMap.get(type);
          Assert.notNull(strategy, "strategy cannot be null");
          strategy.updateTask(customerId);
      }
  
      /**
b688a252   张志伟   :art:
207
208
209
210
211
212
213
214
       * 开始任务
       *
       * @param task
       */
      @Transactional(rollbackFor = Exception.class)
      public void startTask(FollowTask task) {
          FollowStrategy strategy = followMap.get(task.getType());
          Assert.notNull(strategy, "strategy cannot be null");
cacb1a42   张志伟   :art:
215
          strategy.startTask(task, true);
b688a252   张志伟   :art:
216
217
218
      }
  
      /**
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
219
220
221
222
223
224
       * 查询待办详情
       *
       * @param id
       * @param type
       * @return
       */
51a118ce   张志伟   :sparkles:
225
226
227
228
229
230
231
232
233
      public FollowDetailVO approveDetail(Long id, Integer type) {
          FollowTypeEnum typeEnum = FollowTypeEnum.ofValue(type);
          if (Objects.isNull(typeEnum)) {
              FollowRecord record = followRecordService.getById(id);
              BV.notNull(record, () -> "跟进记录不存在");
              typeEnum = record.getType();
          }
          FollowStrategy strategy = followMap.get(typeEnum);
          BV.notNull(strategy, () -> "跟进类型不正确");
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
234
          FollowDetailVO detail = strategy.getDetail(id);
51a118ce   张志伟   :sparkles:
235
          detail.setType(typeEnum.getValue());
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
236
237
238
239
          ApproveRecord approveRecord = approveRecordService.getOne(Wrappers.<ApproveRecord>lambdaQuery()
                  .eq(ApproveRecord::getDataId, detail.getTaskId())
                  .last("limit 1")
          );
5c35d8ab   张志伟   :bug:
240
241
242
243
244
245
246
247
          if (Objects.nonNull(approveRecord)) {
              UserInfoDTO user = userService.user(approveRecord.getUserId());
              if (Objects.nonNull(user)) {
                  detail.setAdviserId(user.getId());
                  detail.setAdviserName(user.getUserName());
              }
              detail.setReason(approveRecord.getReason());
          }
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
248
249
250
251
252
253
254
255
256
257
258
259
          return detail;
      }
  
      /**
       * 主动战败
       *
       * @param currentUser
       * @param reason
       * @param recordId
       */
      @Transactional(rollbackFor = Exception.class)
      public void defeat(LoginAuthBean currentUser, String reason, Long recordId) {
fa966283   张志伟   📝 v1.0.1调整
260
261
          final String lockKey = getLockKey(recordId);
          Pair<Boolean, RLock> pair = distributedLocker.tryLock(lockKey, TimeUnit.SECONDS, 0, 15);
2b628098   张志伟   🚀 v1.0.1 服务顾问离职分配...
262
          BV.isTrue(Boolean.TRUE.equals(pair.getKey()), () -> "请勿重复提交");
fa966283   张志伟   📝 v1.0.1调整
263
          try {
fa966283   张志伟   📝 v1.0.1调整
264
265
266
267
268
269
270
271
272
273
274
              FollowRecord record = followRecordService.getById(recordId);
              BV.notNull(record, () -> "跟进记录不存在");
              FollowTask task = followTaskService.getById(record.getTaskId());
              BV.notNull(task, () -> "跟进信息不存在");
              boolean repetition = isRepetition(record.getTaskId().toString());
              BV.isFalse(repetition, () -> "正在审批处理中,请勿重复申请");
              FlowDto flowDto = FlowDto.create(currentUser.getGroupId(), getFlowNo(), currentUser.getUserId(), currentUser.getUserName(), task.getFollowShop());
              HashMap<String, String> param = new HashMap<>(2);
              param.put("recordId", recordId.toString());
              param.put("type", task.getType().getValue().toString());
              flowDto.setParam(param);
869ec3d1   张志伟   :construction:
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
              String name = "";
              String plate = "";
              FollowStrategy strategy = followMap.get(task.getType());
              Assert.notNull(strategy, "strategy cannot be null");
              FollowDetailVO vo = strategy.followPoolDetail(task);
              if (Objects.nonNull(vo)) {
                  name = vo.getName();
                  plate = vo.getPlateNo();
              }
              List<String> list = Arrays.asList(
                      "申请人: " + currentUser.getUserName(),
                      "客户: " + name,
                      "车辆: " + plate,
                      "跟进类型: " + task.getType().getName(),
                      "战败原因: " + reason
              );
fa966283   张志伟   📝 v1.0.1调整
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
              flowDto.setBriefContentList(list);
              String orderNo = flowApproveRpc.initiate(flowDto);
              ApproveRecord approveRecord = new ApproveRecord();
              approveRecord.setDataId(task.getId());
              approveRecord.setUserId(currentUser.getUserId());
              approveRecord.setOrderNo(orderNo);
              approveRecord.setReason(reason);
              approveRecord.setState(ApproveStateEnum.WAIT);
              approveRecord.setType(ApproveTypeEnum.FOLLOW_DEFEAT);
              approveRecord.setPassed(Boolean.FALSE);
              approveRecord.setCreateTime(DateUtil.localDateTime2Date(LocalDateTime.now()));
              approveRecord.setUpdateTime(DateUtil.localDateTime2Date(LocalDateTime.now()));
              approveRecordService.save(approveRecord);
          } catch (Exception e) {
              distributedLocker.unlock(lockKey);
              throw e;
          }
9e85c6e6   张志伟   ✨ 主动放弃跟进 100%
308
309
310
      }
  
      /**
b2f969bd   张志伟   :art:
311
312
313
314
       * 上传跟进附件
       *
       * @param dto
       */
08704989   张志伟   :art:
315
      @Transactional(rollbackFor = Exception.class)
b2f969bd   张志伟   :art:
316
      public void uploadAtt(FollowAttachmentDTO dto, LoginAuthBean currentUser) {
bff962f1   张志伟   :sparkles:
317
          FollowStrategy strategy = followMap.get(dto.getFollowTypeEnum());
b2f969bd   张志伟   :art:
318
319
320
          Assert.notNull(strategy, "strategy cannot be null");
          strategy.uploadAtt(dto, currentUser.getUserId());
      }
08704989   张志伟   :art:
321
322
323
324
325
326
327
328
  
      /**
       * 更新跟进任务
       *
       * @param setting
       * @param type
       * @param groupId
       */
ad395b9c   张志伟   :art:
329
      public void synFollowTask(List<SettingVO> setting, FollowTypeEnum type, Long groupId) {
08704989   张志伟   :art:
330
331
          FollowStrategy strategy = followMap.get(type);
          Assert.notNull(strategy, "strategy cannot be null");
ad395b9c   张志伟   :art:
332
          strategy.settingChanged(setting, groupId);
08704989   张志伟   :art:
333
334
335
336
337
338
339
340
341
      }
  
      /**
       * 当业务数据取消的时候
       *
       * @param event
       */
      public void onDataCancel(TaskCancelEvent event) {
          FollowTypeEnum typeEnum = conv(event.getDataTypeEnum());
ad395b9c   张志伟   :art:
342
          if (Objects.isNull(typeEnum) || FollowTypeEnum.AC.equals(typeEnum)) {
08704989   张志伟   :art:
343
344
345
346
347
348
349
              return;
          }
          FollowStrategy strategy = followMap.get(typeEnum);
          Assert.notNull(strategy, "strategy cannot be null");
          strategy.cancelFollowTask(event.getCustomerId(), event.getGenerateTime(), event.getGroupId());
      }
  
ad395b9c   张志伟   :art:
350
351
352
      /**
       * 元数据生成任务
       *
23b952c1   张志伟   :art:
353
354
       * @param originalData
       * @param typeEnum
ad395b9c   张志伟   :art:
355
       */
612d25d9   张志伟   :art:
356
      public boolean origin2task(OriginalData originalData, DataTypeEnum typeEnum) {
23b952c1   张志伟   :art:
357
          if (Objects.isNull(originalData)) {
612d25d9   张志伟   :art:
358
              return true;
ad395b9c   张志伟   :art:
359
360
361
362
          }
          FollowTypeEnum type = conv(typeEnum);
          FollowStrategy strategy = followMap.get(type);
          Assert.notNull(strategy, "strategy cannot be null");
dac2e8b1   张志伟   :art:
363
364
365
366
367
368
          try {
              return strategy.origin2task(originalData);
          } catch (Exception exception) {
              log.error("处理元数据失败 data: [{}]", originalData.toString(), exception);
              return false;
          }
23b952c1   张志伟   :art:
369
370
      }
  
612d25d9   张志伟   :art:
371
372
373
      /**
       * 创建跟进待办
       *
8587e21d   张志伟   :art:
374
375
376
377
378
379
380
381
       * @param cluePool
       */
      public void startClue(CustomerCluePool cluePool) {
          FollowStrategy strategy = followMap.get(cluePool.getClueType());
          Assert.notNull(strategy, "strategy cannot be null");
  
          strategy.startClue(cluePool);
      }
dac2e8b1   张志伟   :art:
382
  
8587e21d   张志伟   :art:
383
384
385
      /**
       * 创建跟进待办
       *
612d25d9   张志伟   :art:
386
387
       * @param task
       */
015d55a3   张志伟   :bug:
388
      @Transactional(rollbackFor = Exception.class)
8587e21d   张志伟   :art:
389
      public void endTask(FollowTask task) {
23b952c1   张志伟   :art:
390
391
          FollowStrategy strategy = followMap.get(task.getType());
          Assert.notNull(strategy, "strategy cannot be null");
9b497427   张志伟   :art:
392
393
394
395
396
          try {
              strategy.closeTask(task);
          } catch (Exception ex) {
              log.error("结束任务失败 taskId: [{}]", task.getId(), ex);
          }
612d25d9   张志伟   :art:
397
398
      }
  
8587e21d   张志伟   :art:
399
  
612d25d9   张志伟   :art:
400
401
402
403
404
405
406
407
408
409
      /**
       * 逾期处理
       *
       * @param record
       */
      public void overdueProcessing(FollowRecord record) {
          FollowStrategy strategy = followMap.get(record.getType());
          Assert.notNull(strategy, "strategy cannot be null");
  
          strategy.overdueProcessing(record);
ad395b9c   张志伟   :art:
410
411
      }
  
03b7b995   张志伟   ✨ 公共池后端逻辑 100%
412
413
414
415
      /**
       * 终止任务
       *
       * @param customerId
dac2e8b1   张志伟   :art:
416
       * @param groupId
03b7b995   张志伟   ✨ 公共池后端逻辑 100%
417
418
       */
      @Transactional(rollbackFor = Exception.class)
dac2e8b1   张志伟   :art:
419
      public void stopTask(Long customerId, Long groupId) {
03b7b995   张志伟   ✨ 公共池后端逻辑 100%
420
          List<FollowTypeEnum> typeList = Arrays.asList(FollowTypeEnum.FM, FollowTypeEnum.RM);
dac2e8b1   张志伟   :art:
421
          List<CustomerCluePool> cluePoolList = customerCluePoolService.list(Wrappers.<CustomerCluePool>lambdaQuery()
91c29e23   张志伟   :fire:
422
                  .eq(CustomerCluePool::getClueStatus, ClueStatusEnum.ONGOING)
dac2e8b1   张志伟   :art:
423
424
425
                  .in(CustomerCluePool::getClueType, typeList)
                  .eq(CustomerCluePool::getRefererId, customerId)
                  .eq(CustomerCluePool::getGroupId, groupId)
03b7b995   张志伟   ✨ 公共池后端逻辑 100%
426
          );
91c29e23   张志伟   :fire:
427
428
429
430
431
432
433
          if (!CollectionUtils.isEmpty(cluePoolList)) {
              for (CustomerCluePool clue : cluePoolList) {
                  FollowStrategy strategy = followMap.get(clue.getClueType());
                  if (Objects.nonNull(strategy)) {
                      strategy.forceStopClue(clue);
                  }
              }
91c29e23   张志伟   :fire:
434
435
436
437
438
439
440
441
442
          }
          List<CustomerCluePool> cluePoolWaitList = customerCluePoolService.list(Wrappers.<CustomerCluePool>lambdaQuery()
                  .eq(CustomerCluePool::getClueStatus, ClueStatusEnum.WAITING)
                  .in(CustomerCluePool::getClueType, typeList)
                  .eq(CustomerCluePool::getRefererId, customerId)
                  .eq(CustomerCluePool::getGroupId, groupId)
          );
  
          if (CollectionUtils.isEmpty(cluePoolWaitList)) {
03b7b995   张志伟   ✨ 公共池后端逻辑 100%
443
444
              return;
          }
e10073fa   张志伟   :bug:
445
446
447
448
          List<Long> ids = cluePoolWaitList.stream().map(CustomerCluePool::getId).filter(Objects::nonNull).collect(Collectors.toList());
          if (!CollectionUtils.isEmpty(ids)) {
              customerCluePoolService.removeByIds(ids);
          }
91c29e23   张志伟   :fire:
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
      }
  
      @Transactional(rollbackFor = Exception.class)
      public void onForbidden(Long customerId, Long groupId) {
          List<FollowTypeEnum> typeList = Arrays.asList(FollowTypeEnum.FM, FollowTypeEnum.RM, FollowTypeEnum.IR);
          List<CustomerCluePool> cluePoolList = customerCluePoolService.list(Wrappers.<CustomerCluePool>lambdaQuery()
                  .eq(CustomerCluePool::getClueStatus, ClueStatusEnum.ONGOING)
                  .in(CustomerCluePool::getClueType, typeList)
                  .eq(CustomerCluePool::getRefererId, customerId)
                  .eq(CustomerCluePool::getGroupId, groupId)
          );
          if (!CollectionUtils.isEmpty(cluePoolList)) {
              for (CustomerCluePool clue : cluePoolList) {
                  FollowStrategy strategy = followMap.get(clue.getClueType());
                  if (Objects.nonNull(strategy)) {
                      strategy.onForbiddenStopClue(clue);
                  }
03b7b995   张志伟   ✨ 公共池后端逻辑 100%
466
467
              }
          }
91c29e23   张志伟   :fire:
468
469
470
471
472
473
474
475
476
477
          List<CustomerCluePool> cluePoolWaitList = customerCluePoolService.list(Wrappers.<CustomerCluePool>lambdaQuery()
                  .eq(CustomerCluePool::getClueStatus, ClueStatusEnum.WAITING)
                  .in(CustomerCluePool::getClueType, typeList)
                  .eq(CustomerCluePool::getRefererId, customerId)
                  .eq(CustomerCluePool::getGroupId, groupId)
          );
  
          if (!CollectionUtils.isEmpty(cluePoolWaitList)) {
              customerCluePoolService.removeByIds(cluePoolWaitList);
          }
03b7b995   张志伟   ✨ 公共池后端逻辑 100%
478
479
      }
  
27223d59   张志伟   :bug:
480
481
482
483
484
485
486
      /**
       * 终止任务
       *
       * @param task
       */
      @Transactional(rollbackFor = Exception.class)
      public void stopTask(FollowTask task) {
dac2e8b1   张志伟   :art:
487
          CustomerCluePool cluePool = customerCluePoolService.getById(task.getClueId());
27223d59   张志伟   :bug:
488
489
          FollowStrategy strategy = followMap.get(task.getType());
          if (Objects.nonNull(strategy)) {
dac2e8b1   张志伟   :art:
490
              strategy.forceStopClue(cluePool);
27223d59   张志伟   :bug:
491
          }
27223d59   张志伟   :bug:
492
493
      }
  
bff962f1   张志伟   :sparkles:
494
495
496
497
498
499
      public void readCallReport(CallReportDTO dto, boolean accidentCar, Long... idArr) {
          if (Objects.isNull(dto) || idArr == null || idArr.length <= 0) {
              return;
          }
          final Long groupId = dto.getGroupId();
          final Long staffId = dto.getStaffId();
be4d1cc6   张志伟   :sparkles:
500
501
502
503
          final Long talkTime = dto.getTalkTime();
          if (Objects.isNull(talkTime) || talkTime <= 0) {
              return;
          }
bff962f1   张志伟   :sparkles:
504
505
506
507
508
509
510
511
512
513
          if (accidentCar) {
              CustomerCluePool cluePool = customerCluePoolService.getOne(Wrappers.<CustomerCluePool>lambdaQuery()
                      .eq(CustomerCluePool::getRefererId, idArr[0])
                      .eq(CustomerCluePool::getGroupId, groupId)
                      .eq(CustomerCluePool::getClueType, FollowTypeEnum.AC)
                      .eq(CustomerCluePool::getClueStatus, ClueStatusEnum.ONGOING)
                      .orderByDesc(CustomerCluePool::getId)
                      .last(" limit 1")
              );
              if (Objects.nonNull(cluePool)) {
8c7566e0   张志伟   :sparkles:
514
                  completeRecord(dto, cluePool.getId(), staffId, dto.getCallId());
bff962f1   张志伟   :sparkles:
515
516
517
518
519
520
521
522
              }
          } else {
              List<CustomerCluePool> list = customerCluePoolService.list(Wrappers.<CustomerCluePool>lambdaQuery()
                      .eq(CustomerCluePool::getGroupId, groupId)
                      .eq(CustomerCluePool::getClueStatus, ClueStatusEnum.ONGOING)
                      .in(CustomerCluePool::getRefererId, Arrays.asList(idArr))
              );
              if (!CollectionUtils.isEmpty(list)) {
8c7566e0   张志伟   :sparkles:
523
                  list.forEach(cluePool -> completeRecord(dto, cluePool.getId(), staffId, dto.getCallId()));
bff962f1   张志伟   :sparkles:
524
525
526
527
              }
          }
      }
  
612d25d9   张志伟   :art:
528
  
08704989   张志伟   :art:
529
530
      private FollowTypeEnum conv(DataTypeEnum type) {
          switch (type) {
ad395b9c   张志伟   :art:
531
532
              case AS:
                  return FollowTypeEnum.AC;
8bf24bfd   张志伟   ✨ 调整流失客户跟进、事故车跟进逻辑
533
              case OD:
6b850c74   张志伟   :bug:
534
              case FM:
8bf24bfd   张志伟   ✨ 调整流失客户跟进、事故车跟进逻辑
535
                  return FollowTypeEnum.FM;
08704989   张志伟   :art:
536
537
              case BI:
                  return FollowTypeEnum.IR;
8bf24bfd   张志伟   ✨ 调整流失客户跟进、事故车跟进逻辑
538
539
              case FS:
                  return FollowTypeEnum.RM;
08704989   张志伟   :art:
540
541
542
543
              default:
                  return null;
          }
      }
fa966283   张志伟   📝 v1.0.1调整
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
  
      private String getLockKey(Long recordId) {
          BV.notNull(recordId, "recordId cannot be null");
  
          return String.format("%s:lock:%s", getKeyPrefix(), recordId);
      }
  
      /**
       * 审批防重
       *
       * @param taskId
       * @return
       */
      private boolean isRepetition(String taskId) {
          return approveRecordService.count(Wrappers.<ApproveRecord>lambdaQuery()
                  .eq(ApproveRecord::getDataId, taskId)
                  .eq(ApproveRecord::getType, ApproveTypeEnum.FOLLOW_DEFEAT)
                  .eq(ApproveRecord::getState, ApproveStateEnum.WAIT)
          ) > 0;
      }
bff962f1   张志伟   :sparkles:
564
  
8c7566e0   张志伟   :sparkles:
565
      private void completeRecord(CallReportDTO reportDTO, final Long clueId, final Long staffId, final String callId) {
bff962f1   张志伟   :sparkles:
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
          FollowTask followTask = followTaskService.queryOngoingTaskByClueId(clueId);
          if (Objects.isNull(followTask)) {
              return;
          }
          FollowTypeEnum followType = followTask.getType();
          List<FollowRecord> list = followRecordService.list(Wrappers.<FollowRecord>lambdaQuery()
                  .eq(FollowRecord::getTaskId, followTask.getId())
                  .eq(FollowRecord::getUserId, staffId)
                  .eq(FollowRecord::getType, followType)
                  .eq(FollowRecord::getAddTodo, Boolean.TRUE)
                  .eq(FollowRecord::getOutTime, Boolean.FALSE)
                  .isNull(FollowRecord::getFollowTime)
          );
          if (CollectionUtils.isEmpty(list)) {
              return;
          }
  
          FollowStrategy strategy = followMap.get(followType);
          Assert.notNull(strategy, "strategy cannot be null");
8c7566e0   张志伟   :sparkles:
585
          List<SecretReportHistory> reportHistoryList = new ArrayList<>();
bff962f1   张志伟   :sparkles:
586
587
588
589
  
          for (FollowRecord record : list) {
              FollowAttachmentDTO dto = new FollowAttachmentDTO();
              dto.setAttachments(callId);
cbc29a25   张志伟   :bug:
590
              dto.setTaskId(record.getTaskId());
bff962f1   张志伟   :sparkles:
591
592
              dto.setFollowType(followType.getValue());
              dto.setRecordId(record.getId());
a62ccd41   张志伟   :sparkles:
593
              dto.setFeedbackType(FollowTypeEnum.AC.equals(followType) ? FeedbackTypeEnum.OTHER.getValue() : null);
bff962f1   张志伟   :sparkles:
594
595
              dto.setAttType(AttTypeEnum.SMART_PHONE.getValue());
              strategy.uploadAtt(dto, staffId);
8c7566e0   张志伟   :sparkles:
596
              reportHistoryList.add(createHistory(reportDTO, record, followType));
bff962f1   张志伟   :sparkles:
597
          }
8c7566e0   张志伟   :sparkles:
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
          secretReportHistoryService.saveBatch(reportHistoryList);
      }
  
  
      private SecretReportHistory createHistory(CallReportDTO reportDTO, FollowRecord record, FollowTypeEnum followTypeEnum) {
          SecretReportHistory history = new SecretReportHistory();
          history.setTaskId(record.getTaskId());
          history.setTaskType(followTypeEnum);
          history.setFollowRecordId(record.getId());
          history.setCallId(reportDTO.getCallId());
          history.setStaffId(reportDTO.getStaffId());
          history.setStaffName(reportDTO.getStaffName());
          history.setCustomerId(record.getCustomerId());
          history.setCallType(reportDTO.getDialType());
          history.setCallTime(reportDTO.getCallTime());
          history.setCallDuration(reportDTO.getTalkTime());
          history.setShopId(record.getShopId());
          history.setGroupId(record.getGroupId());
          int count = followRecordLogService.count(Wrappers.<FollowRecordLog>lambdaQuery()
                  .eq(FollowRecordLog::getTaskId, record.getTaskId())
                  .eq(FollowRecordLog::getAttType, AttTypeEnum.SMART_PHONE)
          );
          history.setFirstCall(count <= 0);
          return history;
bff962f1   张志伟   :sparkles:
622
      }
045bdcc2   张志伟   :art:
623
  }