From c3b33c0a020b954a928d4902efede18729229a7a Mon Sep 17 00:00:00 2001 From: Kurisu Date: Thu, 4 May 2023 15:15:56 +0800 Subject: [PATCH] :sparkles: feature(*): 准备公共池报表数据 --- doc/public_report/sql.sql | 31 +++++++++++++++++++++++++++++++ fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/app/CommonController.java | 2 +- fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/ReportPrepareTask.java | 36 ++++++++++++++++++++++++++++++------ fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/CustomerRetentionRatioBizService.java | 318 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/CustomerRetentionRatioBizService.java | 318 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/PublicReportBizService.java | 35 +++++++++++++++++++++++++++++++++++ 6 files changed, 415 insertions(+), 325 deletions(-) create mode 100644 doc/public_report/sql.sql delete mode 100644 fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/CustomerRetentionRatioBizService.java create mode 100644 fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/CustomerRetentionRatioBizService.java create mode 100644 fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/PublicReportBizService.java diff --git a/doc/public_report/sql.sql b/doc/public_report/sql.sql new file mode 100644 index 0000000..174093c --- /dev/null +++ b/doc/public_report/sql.sql @@ -0,0 +1,31 @@ +create table public_report_data +( + id bigint auto_increment, + data_date date not null, + user_id bigint not null comment '用户id', + user_name varchar(64) null comment '用户名称', + shop_id bigint not null comment '门店id', + shop_name varchar(256) null comment '门店名称', + month_initial int default 0 null comment '每月初始数', + day_increase int default 0 null comment '日新增', + month_increase int default 0 null comment '月新增', + current_quantity int default 0 null, + day_stand_quantity int default 0 null, + month_stand_quantity int default 0 null, + day_natural_quantity int default 0 null, + month_natural_quantity int default 0 null, + group_id bigint not null comment '集团id', + create_time datetime null comment '创建日期', + update_time datetime null comment '更新日期', + constraint public_report_data_pk + primary key (id) +) + comment '公共池报表数据'; + +create index public_report_data_shop_id_index + on public_report_data (shop_id); + +create index public_report_data_user_id_index + on public_report_data (user_id); + + diff --git a/fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/app/CommonController.java b/fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/app/CommonController.java index 4a6b06b..239866e 100644 --- a/fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/app/CommonController.java +++ b/fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/app/CommonController.java @@ -9,10 +9,10 @@ import cn.fw.valhalla.common.utils.DateUtil; import cn.fw.valhalla.domain.vo.PostUserVO; import cn.fw.valhalla.service.bus.CommonService; import cn.fw.valhalla.service.bus.CustomerImportBizService; -import cn.fw.valhalla.service.bus.CustomerRetentionRatioBizService; import cn.fw.valhalla.service.bus.LeaveNeedDoBizService; import cn.fw.valhalla.service.bus.follow.FollowBizService; import cn.fw.valhalla.service.bus.pub.PubStandBizService; +import cn.fw.valhalla.service.report.CustomerRetentionRatioBizService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; diff --git a/fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/ReportPrepareTask.java b/fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/ReportPrepareTask.java index 1d58ae7..9403ce2 100644 --- a/fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/ReportPrepareTask.java +++ b/fw-valhalla-server/src/main/java/cn/fw/valhalla/controller/task/ReportPrepareTask.java @@ -1,16 +1,18 @@ package cn.fw.valhalla.controller.task; import cn.fw.valhalla.common.utils.DateUtil; -import cn.fw.valhalla.common.utils.ThreadPoolUtil; -import cn.fw.valhalla.service.bus.CustomerRetentionRatioBizService; +import cn.fw.valhalla.rpc.oop.OopService; +import cn.fw.valhalla.rpc.oop.dto.GroupDTO; +import cn.fw.valhalla.service.report.CustomerRetentionRatioBizService; +import cn.fw.valhalla.service.report.PublicReportBizService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; +import java.time.LocalDate; import java.util.Date; -import java.util.concurrent.CompletableFuture; +import java.util.List; /** * @author : kurisu @@ -22,11 +24,33 @@ import java.util.concurrent.CompletableFuture; @Component @Slf4j public class ReportPrepareTask { + private final OopService oopService; private final CustomerRetentionRatioBizService retentionRatioBizService; + private final PublicReportBizService publicReportBizService; + /** + * 保持率进站率报表数据准备 + */ @Scheduled(cron = "0 0 0 ? * * ") - @Transactional(rollbackFor = Exception.class) public void extractingData() { - CompletableFuture.runAsync(() -> retentionRatioBizService.extracting(DateUtil.startDate(new Date())), ThreadPoolUtil.getInstance().getExecutor()); +// CompletableFuture.runAsync(() -> retentionRatioBizService.extracting(DateUtil.startDate(new Date())), ThreadPoolUtil.getInstance().getExecutor()); + retentionRatioBizService.extracting(DateUtil.startDate(new Date())); + } + + /** + * 公共池报表数据准备 + */ + @Scheduled(cron = "0 30 0 ? * * ") + public void extractingPublicData() { + final List groupList = oopService.allGroup(); + final LocalDate now = LocalDate.now(); + + for (GroupDTO group : groupList) { + try { + publicReportBizService.extracting(now, group.getId()); + } catch (Exception e) { + log.warn("准备公共池报表数据失败[groupId: {} data: {}]", group.getId(), now, e); + } + } } } diff --git a/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/CustomerRetentionRatioBizService.java b/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/CustomerRetentionRatioBizService.java deleted file mode 100644 index 2f8da89..0000000 --- a/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/bus/CustomerRetentionRatioBizService.java +++ /dev/null @@ -1,318 +0,0 @@ -package cn.fw.valhalla.service.bus; - -import cn.fw.valhalla.common.constant.RoleCode; -import cn.fw.valhalla.common.utils.DateUtil; -import cn.fw.valhalla.common.utils.StringUtils; -import cn.fw.valhalla.domain.db.customer.CustomerReachLog; -import cn.fw.valhalla.domain.db.follow.ClueTask; -import cn.fw.valhalla.domain.db.pool.StammkundePool; -import cn.fw.valhalla.domain.db.report.CustomerRetentionRatio; -import cn.fw.valhalla.domain.enums.*; -import cn.fw.valhalla.rpc.ehr.EhrRpcService; -import cn.fw.valhalla.rpc.ehr.dto.StaffInfoDTO; -import cn.fw.valhalla.rpc.erp.UserService; -import cn.fw.valhalla.rpc.erp.dto.PostUserDTO; -import cn.fw.valhalla.rpc.oop.OopService; -import cn.fw.valhalla.rpc.oop.dto.ShopDTO; -import cn.fw.valhalla.service.data.ClueTaskService; -import cn.fw.valhalla.service.data.CustomerReachLogService; -import cn.fw.valhalla.service.data.CustomerRetentionRatioService; -import cn.fw.valhalla.service.data.StammkundePoolService; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.BeanUtils; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; - -import java.sql.Timestamp; -import java.time.LocalDateTime; -import java.time.YearMonth; -import java.util.*; -import java.util.stream.Stream; - -/** - * @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; - private final EhrRpcService ehrRpcService; - private final CustomerRetentionRatioService customerRetentionRatioService; - private final StammkundePoolService stammkundePoolService; - private final ClueTaskService clueTaskService; - private final CustomerReachLogService customerReachLogService; - - @Transactional(rollbackFor = Exception.class) - public void extracting(Date nowDate) { - log.info("开始抽取保有客保持率数据,日期:{}", DateUtil.getStringDateShort(nowDate)); - Stream.of(1L, 2L).forEach(groupId -> { - List pools = Optional.ofNullable(stammkundePoolService.list(Wrappers.query() - .select("DISTINCT shop_id").eq("group_id", groupId)) - ).orElse(new ArrayList<>()); - List allShops = Optional.ofNullable(oopService.getAllShops(groupId)).orElse(new ArrayList<>()); - Set 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) { - if (146L == shop.getId()) { - continue; - } - extractingPerson(shop, day); - } - }); - log.info("~~~~~~~保有客保持率抽取结束~~~~~~~~~~~"); - } - - private void extractingPerson(ShopInfo shop, Date nowDate) { - final String dayString = DateUtil.getStringDateShort(nowDate); - Date monthStart = DateUtil.localDateTime2Date(DateUtil.date2LocalDate(nowDate).minusYears(1L).atStartOfDay()); - final String monthStartStr = DateUtil.getStringDateShort(monthStart); - List pools = Optional.ofNullable(stammkundePoolService.list(Wrappers.query() - .select("DISTINCT adviser_id", "adviser_name") - .eq("pool_status", 1) - .eq("shop_id", shop.getId()) - .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) - ) - ).orElse(new ArrayList<>()); - List userDTOS = Optional.ofNullable(userService.getUserByRole(shop.getId(), RoleCode.FWGW)).orElse(new ArrayList<>()); - Set set = new HashSet<>(); - for (StammkundePool pool : pools) { - Long adviserId = pool.getAdviserId(); - String adviserName = pool.getAdviserName(); - if (StringUtils.isEmpty(adviserName)) { - StaffInfoDTO staffInfoDTO = ehrRpcService.queryStaffInfo(adviserId); - adviserName = Objects.nonNull(staffInfoDTO) ? staffInfoDTO.getName() : adviserName; - } - set.add(new UserInfo(adviserId, adviserName)); - } - for (PostUserDTO pool : userDTOS) { - set.add(new UserInfo(pool.getUserId(), pool.getUserName())); - } - if (CollectionUtils.isEmpty(set)) { - return; - } - List list = new ArrayList<>(); - for (UserInfo userInfo : set) { - fillPersonData(shop, userInfo, nowDate, list); - } - customerRetentionRatioService.saveBatch(list); - } - - private void fillPersonData(ShopInfo shop, UserInfo userInfo, Date nowDate, List 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.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 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); - } - } - } - - private List createAllZero(CustomerRetentionRatio ratio) { - DefeatReasonEnum[] values = DefeatReasonEnum.values(); - List 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; - } - - private StammkundePool firstOne(Long userId, Long shopId) { - return stammkundePoolService.getOne(Wrappers.lambdaQuery() - .eq(Objects.nonNull(userId), StammkundePool::getAdviserId, userId) - .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE) - .eq(StammkundePool::getShopId, shopId) - .orderByAsc(StammkundePool::getActivationTime) - .last(" limit 1") - ); - } - - private int initialNum(Long userId, Long shopId, Date expire) { - final Date endInTime = DateUtil.getEndInTime(expire); - return stammkundePoolService.count(Wrappers.lambdaQuery() - .eq(StammkundePool::getAdviserId, userId) - .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE) - .eq(StammkundePool::getShopId, shopId) - .le(StammkundePool::getActivationTime, endInTime) - .and(w1 -> w1.gt(StammkundePool::getRejectTime, endInTime).or().isNull(StammkundePool::getRejectTime)) - ); - } - - private int publicNum(Long userId, Long shopId, Date nowDate) { - Date endDay = DateUtil.getEndInTime(nowDate); - return stammkundePoolService.count(Wrappers.lambdaQuery() - .eq(StammkundePool::getAdviserId, userId) - .eq(StammkundePool::getSources, StammkundeSourcesEnum.PUBLIC_POOL) - .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE) - .eq(StammkundePool::getShopId, shopId) - .le(StammkundePool::getActivationTime, endDay) - ); - } - - private int twiceNum(Long userId, Long shopId, Date preMonthEndDay, Date nowDate, FollowTypeEnum typeEnum) { - Date endDay = DateUtil.getEndInTime(nowDate); - return clueTaskService.count(Wrappers.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) - ); - } - - private int defeatNum(Long userId, Long shopId, DefeatReasonEnum reason, Date nowDate) { - LocalDateTime yearAgo = DateUtil.date2LocalDate(nowDate).minusYears(1L).atStartOfDay(); - Date yearAgoTime = DateUtil.localDateTime2Date(yearAgo); - Date endDay = DateUtil.getEndInTime(nowDate); - return stammkundePoolService.count(Wrappers.lambdaQuery() - .eq(StammkundePool::getAdviserId, userId) - .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE) - .eq(StammkundePool::getShopId, shopId) - .eq(StammkundePool::getAktiv, Boolean.FALSE) - .eq(StammkundePool::getReason, reason) - .gt(StammkundePool::getRejectTime, yearAgoTime) - .le(StammkundePool::getRejectTime, endDay) - - ); - } - - 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); - } - } - - 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); - } - } -} diff --git a/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/CustomerRetentionRatioBizService.java b/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/CustomerRetentionRatioBizService.java new file mode 100644 index 0000000..0c1e6cf --- /dev/null +++ b/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/CustomerRetentionRatioBizService.java @@ -0,0 +1,318 @@ +package cn.fw.valhalla.service.report; + +import cn.fw.valhalla.common.constant.RoleCode; +import cn.fw.valhalla.common.utils.DateUtil; +import cn.fw.valhalla.common.utils.StringUtils; +import cn.fw.valhalla.domain.db.customer.CustomerReachLog; +import cn.fw.valhalla.domain.db.follow.ClueTask; +import cn.fw.valhalla.domain.db.pool.StammkundePool; +import cn.fw.valhalla.domain.db.report.CustomerRetentionRatio; +import cn.fw.valhalla.domain.enums.*; +import cn.fw.valhalla.rpc.ehr.EhrRpcService; +import cn.fw.valhalla.rpc.ehr.dto.StaffInfoDTO; +import cn.fw.valhalla.rpc.erp.UserService; +import cn.fw.valhalla.rpc.erp.dto.PostUserDTO; +import cn.fw.valhalla.rpc.oop.OopService; +import cn.fw.valhalla.rpc.oop.dto.ShopDTO; +import cn.fw.valhalla.service.data.ClueTaskService; +import cn.fw.valhalla.service.data.CustomerReachLogService; +import cn.fw.valhalla.service.data.CustomerRetentionRatioService; +import cn.fw.valhalla.service.data.StammkundePoolService; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.sql.Timestamp; +import java.time.LocalDateTime; +import java.time.YearMonth; +import java.util.*; +import java.util.stream.Stream; + +/** + * @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; + private final EhrRpcService ehrRpcService; + private final CustomerRetentionRatioService customerRetentionRatioService; + private final StammkundePoolService stammkundePoolService; + private final ClueTaskService clueTaskService; + private final CustomerReachLogService customerReachLogService; + + @Transactional(rollbackFor = Exception.class) + public void extracting(Date nowDate) { + log.info("开始抽取保有客保持率数据,日期:{}", DateUtil.getStringDateShort(nowDate)); + Stream.of(1L, 2L).forEach(groupId -> { + List pools = Optional.ofNullable(stammkundePoolService.list(Wrappers.query() + .select("DISTINCT shop_id").eq("group_id", groupId)) + ).orElse(new ArrayList<>()); + List allShops = Optional.ofNullable(oopService.getAllShops(groupId)).orElse(new ArrayList<>()); + Set 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) { + if (146L == shop.getId()) { + continue; + } + extractingPerson(shop, day); + } + }); + log.info("~~~~~~~保有客保持率抽取结束~~~~~~~~~~~"); + } + + private void extractingPerson(ShopInfo shop, Date nowDate) { + final String dayString = DateUtil.getStringDateShort(nowDate); + Date monthStart = DateUtil.localDateTime2Date(DateUtil.date2LocalDate(nowDate).minusYears(1L).atStartOfDay()); + final String monthStartStr = DateUtil.getStringDateShort(monthStart); + List pools = Optional.ofNullable(stammkundePoolService.list(Wrappers.query() + .select("DISTINCT adviser_id", "adviser_name") + .eq("pool_status", 1) + .eq("shop_id", shop.getId()) + .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) + ) + ).orElse(new ArrayList<>()); + List userDTOS = Optional.ofNullable(userService.getUserByRole(shop.getId(), RoleCode.FWGW)).orElse(new ArrayList<>()); + Set set = new HashSet<>(); + for (StammkundePool pool : pools) { + Long adviserId = pool.getAdviserId(); + String adviserName = pool.getAdviserName(); + if (StringUtils.isEmpty(adviserName)) { + StaffInfoDTO staffInfoDTO = ehrRpcService.queryStaffInfo(adviserId); + adviserName = Objects.nonNull(staffInfoDTO) ? staffInfoDTO.getName() : adviserName; + } + set.add(new UserInfo(adviserId, adviserName)); + } + for (PostUserDTO pool : userDTOS) { + set.add(new UserInfo(pool.getUserId(), pool.getUserName())); + } + if (CollectionUtils.isEmpty(set)) { + return; + } + List list = new ArrayList<>(); + for (UserInfo userInfo : set) { + fillPersonData(shop, userInfo, nowDate, list); + } + customerRetentionRatioService.saveBatch(list); + } + + private void fillPersonData(ShopInfo shop, UserInfo userInfo, Date nowDate, List 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.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 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); + } + } + } + + private List createAllZero(CustomerRetentionRatio ratio) { + DefeatReasonEnum[] values = DefeatReasonEnum.values(); + List 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; + } + + private StammkundePool firstOne(Long userId, Long shopId) { + return stammkundePoolService.getOne(Wrappers.lambdaQuery() + .eq(Objects.nonNull(userId), StammkundePool::getAdviserId, userId) + .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE) + .eq(StammkundePool::getShopId, shopId) + .orderByAsc(StammkundePool::getActivationTime) + .last(" limit 1") + ); + } + + private int initialNum(Long userId, Long shopId, Date expire) { + final Date endInTime = DateUtil.getEndInTime(expire); + return stammkundePoolService.count(Wrappers.lambdaQuery() + .eq(StammkundePool::getAdviserId, userId) + .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE) + .eq(StammkundePool::getShopId, shopId) + .le(StammkundePool::getActivationTime, endInTime) + .and(w1 -> w1.gt(StammkundePool::getRejectTime, endInTime).or().isNull(StammkundePool::getRejectTime)) + ); + } + + private int publicNum(Long userId, Long shopId, Date nowDate) { + Date endDay = DateUtil.getEndInTime(nowDate); + return stammkundePoolService.count(Wrappers.lambdaQuery() + .eq(StammkundePool::getAdviserId, userId) + .eq(StammkundePool::getSources, StammkundeSourcesEnum.PUBLIC_POOL) + .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE) + .eq(StammkundePool::getShopId, shopId) + .le(StammkundePool::getActivationTime, endDay) + ); + } + + private int twiceNum(Long userId, Long shopId, Date preMonthEndDay, Date nowDate, FollowTypeEnum typeEnum) { + Date endDay = DateUtil.getEndInTime(nowDate); + return clueTaskService.count(Wrappers.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) + ); + } + + private int defeatNum(Long userId, Long shopId, DefeatReasonEnum reason, Date nowDate) { + LocalDateTime yearAgo = DateUtil.date2LocalDate(nowDate).minusYears(1L).atStartOfDay(); + Date yearAgoTime = DateUtil.localDateTime2Date(yearAgo); + Date endDay = DateUtil.getEndInTime(nowDate); + return stammkundePoolService.count(Wrappers.lambdaQuery() + .eq(StammkundePool::getAdviserId, userId) + .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE) + .eq(StammkundePool::getShopId, shopId) + .eq(StammkundePool::getAktiv, Boolean.FALSE) + .eq(StammkundePool::getReason, reason) + .gt(StammkundePool::getRejectTime, yearAgoTime) + .le(StammkundePool::getRejectTime, endDay) + + ); + } + + 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); + } + } + + 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); + } + } +} diff --git a/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/PublicReportBizService.java b/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/PublicReportBizService.java new file mode 100644 index 0000000..3e493fc --- /dev/null +++ b/fw-valhalla-service/src/main/java/cn/fw/valhalla/service/report/PublicReportBizService.java @@ -0,0 +1,35 @@ +package cn.fw.valhalla.service.report; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.time.LocalDate; + +/** + * 公共池报表数据服务 + * + * @author : kurisu + * @version : 2.0 + * @className : PublicReportBizService + * @description : 公共池报表数据服务 + * @date : 2023-05-04 15:07 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class PublicReportBizService { + + /** + * 抽取集团公共池数据 + * + * @param nowDate 日期 + * @param groupId 集团id + */ + @Transactional(rollbackFor = Exception.class) + public void extracting(LocalDate nowDate, Long groupId) { + log.info("开始抽取公共池报表数据,日期:{} 集团:{}", nowDate, groupId); + // TODO: 2023/5/4 完成方法 + } +} -- libgit2 0.22.2