Blame view

fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/CustomerRetentionRatioBizService.java 13.1 KB
c3b33c0a   张志伟   :sparkles:
1
  package cn.fw.valhalla.service.report;
395e025e   张志伟   :art:
2
3
4
  
  import cn.fw.valhalla.common.constant.RoleCode;
  import cn.fw.valhalla.common.utils.DateUtil;
fbd8af07   张志伟   :bug:
5
  import cn.fw.valhalla.common.utils.StringUtils;
e6612d03   张志伟   :sparkles:
6
  import cn.fw.valhalla.domain.db.customer.CustomerReachLog;
34b20e3a   张志伟   :sparkles:
7
  import cn.fw.valhalla.domain.db.follow.ClueTask;
395e025e   张志伟   :art:
8
9
  import cn.fw.valhalla.domain.db.pool.StammkundePool;
  import cn.fw.valhalla.domain.db.report.CustomerRetentionRatio;
9526ebe3   张志伟   :sparkles:
10
  import cn.fw.valhalla.domain.enums.*;
3fc19e59   张志伟   升级erpsdk
11
12
  import cn.fw.valhalla.rpc.ehr.EhrRpcService;
  import cn.fw.valhalla.rpc.ehr.dto.StaffInfoDTO;
395e025e   张志伟   :art:
13
14
  import cn.fw.valhalla.rpc.erp.UserService;
  import cn.fw.valhalla.rpc.erp.dto.PostUserDTO;
395e025e   张志伟   :art:
15
16
  import cn.fw.valhalla.rpc.oop.OopService;
  import cn.fw.valhalla.rpc.oop.dto.ShopDTO;
34b20e3a   张志伟   :sparkles:
17
  import cn.fw.valhalla.service.data.ClueTaskService;
e6612d03   张志伟   :sparkles:
18
  import cn.fw.valhalla.service.data.CustomerReachLogService;
395e025e   张志伟   :art:
19
  import cn.fw.valhalla.service.data.CustomerRetentionRatioService;
395e025e   张志伟   :art:
20
21
22
23
  import cn.fw.valhalla.service.data.StammkundePoolService;
  import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  import lombok.RequiredArgsConstructor;
  import lombok.extern.slf4j.Slf4j;
90474509   张志伟   :construction:
24
  import org.springframework.beans.BeanUtils;
395e025e   张志伟   :art:
25
26
27
28
29
  import org.springframework.stereotype.Service;
  import org.springframework.transaction.annotation.Transactional;
  import org.springframework.util.CollectionUtils;
  
  import java.sql.Timestamp;
fbd06803   张志伟   :sparkles:
30
  import java.time.LocalDateTime;
e6612d03   张志伟   :sparkles:
31
  import java.time.YearMonth;
566fc4b1   张志伟   :construction:
32
  import java.util.*;
714c2054   张志伟   :construction:
33
  import java.util.stream.Stream;
395e025e   张志伟   :art:
34
35
36
37
38
39
40
41
42
43
44
45
46
  
  /**
   * @author : kurisu
   * @className : CustomerRetentionRatioBizService
   * @description : 客户保持率
   * @date: 2020-11-24 15:59
   */
  @Service
  @Slf4j
  @RequiredArgsConstructor
  public class CustomerRetentionRatioBizService {
      private final OopService oopService;
      private final UserService userService;
3fc19e59   张志伟   升级erpsdk
47
      private final EhrRpcService ehrRpcService;
395e025e   张志伟   :art:
48
49
      private final CustomerRetentionRatioService customerRetentionRatioService;
      private final StammkundePoolService stammkundePoolService;
34b20e3a   张志伟   :sparkles:
50
      private final ClueTaskService clueTaskService;
e6612d03   张志伟   :sparkles:
51
      private final CustomerReachLogService customerReachLogService;
395e025e   张志伟   :art:
52
53
54
55
  
      @Transactional(rollbackFor = Exception.class)
      public void extracting(Date nowDate) {
          log.info("开始抽取保有客保持率数据,日期:{}", DateUtil.getStringDateShort(nowDate));
714c2054   张志伟   :construction:
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
          Stream.of(1L, 2L).forEach(groupId -> {
              List<StammkundePool> pools = Optional.ofNullable(stammkundePoolService.list(Wrappers.<StammkundePool>query()
                      .select("DISTINCT shop_id").eq("group_id", groupId))
              ).orElse(new ArrayList<>());
              List<ShopDTO> allShops = Optional.ofNullable(oopService.getAllShops(groupId)).orElse(new ArrayList<>());
              Set<ShopInfo> set = new HashSet<>();
              for (StammkundePool pool : pools) {
                  ShopDTO shop = oopService.shop(pool.getShopId());
                  if (Objects.nonNull(shop)) {
                      set.add(new ShopInfo(pool.getShopId(), shop.getShortName()));
                  } else {
                      set.add(new ShopInfo(pool.getShopId(), String.valueOf(pool.getShopId())));
                  }
              }
              for (ShopDTO allShop : allShops) {
                  set.add(new ShopInfo(allShop.getId(), allShop.getShortName()));
              }
              if (CollectionUtils.isEmpty(set)) {
                  return;
              }
              Timestamp day = DateUtil.getExpiredDay(nowDate, -1);
              customerRetentionRatioService.removeByDate(DateUtil.startDate(day));
              for (ShopInfo shop : set) {
9a324d59   张志伟   :sparkles:
79
80
81
                  if (146L == shop.getId()) {
                      continue;
                  }
714c2054   张志伟   :construction:
82
83
84
                  extractingPerson(shop, day);
              }
          });
5b538595   张志伟   feature(*): 新增查询线...
85
          log.info("~~~~~~~保有客保持率抽取结束~~~~~~~~~~~");
395e025e   张志伟   :art:
86
87
      }
  
714c2054   张志伟   :construction:
88
      private void extractingPerson(ShopInfo shop, Date nowDate) {
fbd06803   张志伟   :sparkles:
89
          final String dayString = DateUtil.getStringDateShort(nowDate);
7b139315   张志伟   :bug:
90
          Date monthStart = DateUtil.localDateTime2Date(DateUtil.date2LocalDate(nowDate).minusYears(1L).atStartOfDay());
7355dcae   张志伟   :bug:
91
          final String monthStartStr = DateUtil.getStringDateShort(monthStart);
714c2054   张志伟   :construction:
92
          List<StammkundePool> pools = Optional.ofNullable(stammkundePoolService.list(Wrappers.<StammkundePool>query()
5588019f   张志伟   :bug:
93
94
95
                          .select("DISTINCT adviser_id", "adviser_name")
                          .eq("pool_status", 1)
                          .eq("shop_id", shop.getId())
7355dcae   张志伟   :bug:
96
                          .apply("(DATE_FORMAT(reject_time, '%Y-%m-%d') >= {0} or reject_time is null) and DATE_FORMAT(activation_time, '%Y-%m-%d') <= {1}", monthStartStr, dayString)
5588019f   张志伟   :bug:
97
                  )
714c2054   张志伟   :construction:
98
          ).orElse(new ArrayList<>());
566fc4b1   张志伟   :construction:
99
100
101
          List<PostUserDTO> userDTOS = Optional.ofNullable(userService.getUserByRole(shop.getId(), RoleCode.FWGW)).orElse(new ArrayList<>());
          Set<UserInfo> set = new HashSet<>();
          for (StammkundePool pool : pools) {
fbd8af07   张志伟   :bug:
102
103
104
              Long adviserId = pool.getAdviserId();
              String adviserName = pool.getAdviserName();
              if (StringUtils.isEmpty(adviserName)) {
3fc19e59   张志伟   升级erpsdk
105
106
                  StaffInfoDTO staffInfoDTO = ehrRpcService.queryStaffInfo(adviserId);
                  adviserName = Objects.nonNull(staffInfoDTO) ? staffInfoDTO.getName() : adviserName;
fbd8af07   张志伟   :bug:
107
108
              }
              set.add(new UserInfo(adviserId, adviserName));
566fc4b1   张志伟   :construction:
109
110
111
112
          }
          for (PostUserDTO pool : userDTOS) {
              set.add(new UserInfo(pool.getUserId(), pool.getUserName()));
          }
566fc4b1   张志伟   :construction:
113
          if (CollectionUtils.isEmpty(set)) {
395e025e   张志伟   :art:
114
115
              return;
          }
395e025e   张志伟   :art:
116
          List<CustomerRetentionRatio> list = new ArrayList<>();
566fc4b1   张志伟   :construction:
117
          for (UserInfo userInfo : set) {
e6612d03   张志伟   :sparkles:
118
              fillPersonData(shop, userInfo, nowDate, list);
395e025e   张志伟   :art:
119
120
121
122
          }
          customerRetentionRatioService.saveBatch(list);
      }
  
e6612d03   张志伟   :sparkles:
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
      private void fillPersonData(ShopInfo shop, UserInfo userInfo, Date nowDate, List<CustomerRetentionRatio> list) {
          YearMonth yearMonth = YearMonth.from(DateUtil.date2LocalDate(nowDate));
          Date monthStart = DateUtil.localDateTime2Date(yearMonth.atDay(1).atStartOfDay());
          CustomerRetentionRatio ratio = new CustomerRetentionRatio();
          ratio.setDataDate(nowDate);
          ratio.setDimensions(1);
          ratio.setUserId(userInfo.getUserId());
          ratio.setUserName(userInfo.getUserName());
          ratio.setShopId(shop.getId());
          ratio.setShopName(shop.getName());
          int reachCount = customerReachLogService.count(Wrappers.<CustomerReachLog>lambdaUpdate()
                  .eq(CustomerReachLog::getAdviserId, userInfo.getUserId())
                  .eq(CustomerReachLog::getShopId, shop.getId())
                  .gt(CustomerReachLog::getArrivalTime, monthStart)
                  .lt(CustomerReachLog::getArrivalTime, DateUtil.getEndInTime(nowDate))
          );
          ratio.setReachNum(reachCount);
          StammkundePool pool = firstOne(userInfo.getUserId(), shop.getId());
          if (Objects.isNull(pool)) {
              ratio.setInitialNum(0);
              ratio.setDefeatNum(0);
              List<CustomerRetentionRatio> allZero = createAllZero(ratio);
              list.addAll(allZero);
          } else {
              int initialNum = initialNum(userInfo.getUserId(), shop.getId(), nowDate);
              ratio.setInitialNum(initialNum);
              ratio.setPublicNum(publicNum(userInfo.getUserId(), shop.getId(), nowDate));
              for (DefeatReasonEnum reasonEnum : DefeatReasonEnum.values()) {
                  CustomerRetentionRatio r = new CustomerRetentionRatio();
                  BeanUtils.copyProperties(ratio, r);
                  r.setType(reasonEnum);
                  r.setDefeatNum(defeatNum(userInfo.getUserId(), shop.getId(), reasonEnum, nowDate));
                  list.add(r);
              }
          }
      }
  
90474509   张志伟   :construction:
160
161
162
163
164
165
166
167
168
169
170
171
      private List<CustomerRetentionRatio> createAllZero(CustomerRetentionRatio ratio) {
          DefeatReasonEnum[] values = DefeatReasonEnum.values();
          List<CustomerRetentionRatio> list = new ArrayList<>(values.length);
          for (DefeatReasonEnum reasonEnum : values) {
              CustomerRetentionRatio r = new CustomerRetentionRatio();
              BeanUtils.copyProperties(ratio, r);
              r.setType(reasonEnum);
              list.add(r);
          }
          return list;
      }
  
395e025e   张志伟   :art:
172
173
174
      private StammkundePool firstOne(Long userId, Long shopId) {
          return stammkundePoolService.getOne(Wrappers.<StammkundePool>lambdaQuery()
                  .eq(Objects.nonNull(userId), StammkundePool::getAdviserId, userId)
714c2054   张志伟   :construction:
175
                  .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE)
395e025e   张志伟   :art:
176
177
178
179
180
181
182
                  .eq(StammkundePool::getShopId, shopId)
                  .orderByAsc(StammkundePool::getActivationTime)
                  .last(" limit 1")
          );
      }
  
      private int initialNum(Long userId, Long shopId, Date expire) {
fbd06803   张志伟   :sparkles:
183
          final Date endInTime = DateUtil.getEndInTime(expire);
395e025e   张志伟   :art:
184
185
186
187
          return stammkundePoolService.count(Wrappers.<StammkundePool>lambdaQuery()
                  .eq(StammkundePool::getAdviserId, userId)
                  .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE)
                  .eq(StammkundePool::getShopId, shopId)
fbd06803   张志伟   :sparkles:
188
189
                  .le(StammkundePool::getActivationTime, endInTime)
                  .and(w1 -> w1.gt(StammkundePool::getRejectTime, endInTime).or().isNull(StammkundePool::getRejectTime))
395e025e   张志伟   :art:
190
191
192
          );
      }
  
e6612d03   张志伟   :sparkles:
193
      private int publicNum(Long userId, Long shopId, Date nowDate) {
f9e65c46   张志伟   :bug:
194
          Date endDay = DateUtil.getEndInTime(nowDate);
8c9d89dd   张志伟   :sparkles:
195
196
          return stammkundePoolService.count(Wrappers.<StammkundePool>lambdaQuery()
                  .eq(StammkundePool::getAdviserId, userId)
9526ebe3   张志伟   :sparkles:
197
                  .eq(StammkundePool::getSources, StammkundeSourcesEnum.PUBLIC_POOL)
8c9d89dd   张志伟   :sparkles:
198
199
                  .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE)
                  .eq(StammkundePool::getShopId, shopId)
f9e65c46   张志伟   :bug:
200
                  .le(StammkundePool::getActivationTime, endDay)
9526ebe3   张志伟   :sparkles:
201
202
203
204
          );
      }
  
      private int twiceNum(Long userId, Long shopId, Date preMonthEndDay, Date nowDate, FollowTypeEnum typeEnum) {
f9e65c46   张志伟   :bug:
205
          Date endDay = DateUtil.getEndInTime(nowDate);
34b20e3a   张志伟   :sparkles:
206
207
208
209
210
211
212
213
          return clueTaskService.count(Wrappers.<ClueTask>lambdaQuery()
                  .eq(ClueTask::getState, TaskStateEnum.COMPLETE)
                  .eq(ClueTask::getRedistribution, Boolean.TRUE)
                  .eq(ClueTask::getType, typeEnum)
                  .eq(ClueTask::getFollowShop, shopId)
                  .eq(ClueTask::getFollowUser, userId)
                  .gt(ClueTask::getCloseTime, preMonthEndDay)
                  .le(ClueTask::getCloseTime, endDay)
8c9d89dd   张志伟   :sparkles:
214
215
216
          );
      }
  
fbd06803   张志伟   :sparkles:
217
      private int defeatNum(Long userId, Long shopId, DefeatReasonEnum reason, Date nowDate) {
2cd48965   张志伟   :sparkles:
218
          LocalDateTime yearAgo = DateUtil.date2LocalDate(nowDate).minusYears(1L).atStartOfDay();
fbd06803   张志伟   :sparkles:
219
          Date yearAgoTime = DateUtil.localDateTime2Date(yearAgo);
8f82f213   张志伟   :construction_wor...
220
          Date endDay = DateUtil.getEndInTime(nowDate);
395e025e   张志伟   :art:
221
222
223
224
          return stammkundePoolService.count(Wrappers.<StammkundePool>lambdaQuery()
                  .eq(StammkundePool::getAdviserId, userId)
                  .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE)
                  .eq(StammkundePool::getShopId, shopId)
9a324d59   张志伟   :sparkles:
225
                  .eq(StammkundePool::getAktiv, Boolean.FALSE)
90474509   张志伟   :construction:
226
                  .eq(StammkundePool::getReason, reason)
fbd06803   张志伟   :sparkles:
227
                  .gt(StammkundePool::getRejectTime, yearAgoTime)
395e025e   张志伟   :art:
228
229
230
231
                  .le(StammkundePool::getRejectTime, endDay)
  
          );
      }
566fc4b1   张志伟   :construction:
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
  
      class UserInfo {
          private Long userId;
          private String userName;
  
          public UserInfo(Long userId, String userName) {
              this.userId = userId;
              this.userName = userName;
          }
  
          public Long getUserId() {
              return userId;
          }
  
          public void setUserId(Long userId) {
              this.userId = userId;
          }
  
          public String getUserName() {
              return userName;
          }
  
          public void setUserName(String userName) {
              this.userName = userName;
          }
  
          @Override
          public boolean equals(Object o) {
              if (this == o) {
                  return true;
              }
              if (o == null || getClass() != o.getClass()) {
                  return false;
              }
              UserInfo userInfo = (UserInfo) o;
              return Objects.equals(userId, userInfo.userId) && Objects.equals(userName, userInfo.userName);
          }
  
          @Override
          public int hashCode() {
              return Objects.hash(userId, userName);
          }
      }
714c2054   张志伟   :construction:
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
  
      class ShopInfo {
          private Long id;
          private String name;
  
          public ShopInfo(Long id, String name) {
              this.id = id;
              this.name = name;
          }
  
          public Long getId() {
              return id;
          }
  
          public void setId(Long id) {
              this.id = id;
          }
  
          public String getName() {
              return name;
          }
  
          public void setName(String name) {
              this.name = name;
          }
  
          @Override
          public boolean equals(Object o) {
              if (this == o) {
                  return true;
              }
              if (o == null || getClass() != o.getClass()) {
                  return false;
              }
              ShopInfo shopInfo = (ShopInfo) o;
              return Objects.equals(id, shopInfo.id) && Objects.equals(name, shopInfo.name);
          }
  
          @Override
          public int hashCode() {
              return Objects.hash(id, name);
          }
      }
395e025e   张志伟   :art:
318
  }