CustomerRetentionRatioBizService.java 10.4 KB
package cn.fw.valhalla.service.bus;

import cn.fw.valhalla.common.constant.RoleCode;
import cn.fw.valhalla.common.utils.DateUtil;
import cn.fw.valhalla.domain.db.pool.StammkundePool;
import cn.fw.valhalla.domain.db.report.CustomerRetentionRatio;
import cn.fw.valhalla.domain.enums.DefeatReasonEnum;
import cn.fw.valhalla.domain.enums.StammkundeStatusEnum;
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.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.LocalDate;
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 CustomerRetentionRatioService customerRetentionRatioService;
    private final StammkundePoolService stammkundePoolService;

    @Transactional(rollbackFor = Exception.class)
    public void extracting(Date nowDate) {
        log.info("开始抽取保有客保持率数据,日期:{}", DateUtil.getStringDateShort(nowDate));
        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) {
                extractingPerson(shop, day);
            }
        });
    }

    private void extractingPerson(ShopInfo shop, Date nowDate) {
        List<StammkundePool> pools = Optional.ofNullable(stammkundePoolService.list(Wrappers.<StammkundePool>query()
                .select("DISTINCT adviser_id", "adviser_name").eq("shop_id", shop.getId()))
        ).orElse(new ArrayList<>());
        List<PostUserDTO> userDTOS = Optional.ofNullable(userService.getUserByRole(shop.getId(), RoleCode.FWGW)).orElse(new ArrayList<>());
        Set<UserInfo> set = new HashSet<>();
        for (StammkundePool pool : pools) {
            set.add(new UserInfo(pool.getAdviserId(), pool.getAdviserName()));
        }
        for (PostUserDTO pool : userDTOS) {
            set.add(new UserInfo(pool.getUserId(), pool.getUserName()));
        }

        if (CollectionUtils.isEmpty(set)) {
            return;
        }
        Timestamp expiredDay = DateUtil.getExpiredMonth(nowDate, -1);
        Date monthEndDay = DateUtil.getMonthEndDay(expiredDay);
        final LocalDate initialDay = DateUtil.date2LocalDate(monthEndDay);

        List<CustomerRetentionRatio> list = new ArrayList<>();
        for (UserInfo userInfo : set) {
            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());
            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 {
                Date startDay = DateUtil.getMonthEndDay(pool.getActivationTime());
                LocalDate acTime = DateUtil.date2LocalDate(startDay);
                if (initialDay.isBefore(acTime)) {
                    if (startDay.after(nowDate)) {
                        startDay = nowDate;
                    }
                    int initialNum = initialNum(userInfo.getUserId(), shop.getId(), startDay);
                    ratio.setInitialNum(initialNum);
                    for (DefeatReasonEnum reasonEnum : DefeatReasonEnum.values()) {
                        CustomerRetentionRatio r = new CustomerRetentionRatio();
                        BeanUtils.copyProperties(ratio, r);
                        r.setType(reasonEnum);
                        r.setDefeatNum(defeatNum(userInfo.getUserId(), shop.getId(), startDay, reasonEnum));
                        list.add(r);
                    }
                } else {
                    int initialNum = initialNum(userInfo.getUserId(), shop.getId(), monthEndDay);
                    ratio.setInitialNum(initialNum);
                    for (DefeatReasonEnum reasonEnum : DefeatReasonEnum.values()) {
                        CustomerRetentionRatio r = new CustomerRetentionRatio();
                        BeanUtils.copyProperties(ratio, r);
                        r.setType(reasonEnum);
                        r.setDefeatNum(defeatNum(userInfo.getUserId(), shop.getId(), monthEndDay, reasonEnum));
                        list.add(r);
                    }
                }
            }
        }
        customerRetentionRatioService.saveBatch(list);
    }

    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;
    }

    private StammkundePool firstOne(Long userId, Long shopId) {
        return stammkundePoolService.getOne(Wrappers.<StammkundePool>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) {
        return stammkundePoolService.count(Wrappers.<StammkundePool>lambdaQuery()
                .eq(StammkundePool::getAdviserId, userId)
                .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE)
                .eq(StammkundePool::getShopId, shopId)
                .le(StammkundePool::getActivationTime, expire)
        );
    }

    private int defeatNum(Long userId, Long shopId, Date expire, DefeatReasonEnum reason) {
        Timestamp endDay = DateUtil.getExpiredDay(expire, 30);
        return stammkundePoolService.count(Wrappers.<StammkundePool>lambdaQuery()
                .eq(StammkundePool::getAdviserId, userId)
                .eq(StammkundePool::getPoolStatus, StammkundeStatusEnum.KUNDE)
                .eq(StammkundePool::getShopId, shopId)
                .eq(StammkundePool::getReason, reason)
                .lt(StammkundePool::getActivationTime, expire)
                .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);
        }
    }
}