StammkundeBizService.java 7.38 KB
package cn.fw.valhalla.service.bus;

import cn.fw.valhalla.common.utils.DateUtil;
import cn.fw.valhalla.common.utils.GeoDistanceUtils;
import cn.fw.valhalla.domain.db.follow.FollowTask;
import cn.fw.valhalla.domain.dto.StammkundeAnalyseDTO;
import cn.fw.valhalla.domain.enums.FollowTypeEnum;
import cn.fw.valhalla.domain.enums.TaskStateEnum;
import cn.fw.valhalla.domain.query.StammkundeAnalyseQueryVO;
import cn.fw.valhalla.domain.vo.customer.StammkundeAddressAnalyseVO;
import cn.fw.valhalla.domain.vo.customer.StammkundeAnalyseVO;
import cn.fw.valhalla.service.data.CustomerService;
import cn.fw.valhalla.service.data.FollowTaskService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

import static cn.fw.common.businessvalidator.Validator.BV;

/**
 * @author : kurisu
 * @className : StammkundeBizService
 * @description : 保有客分析业务service
 * @date: 2021-01-21 15:29
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class StammkundeBizService {

    private final FollowTaskService followTaskService;
    private final CustomerService customerService;

    public List<StammkundeAddressAnalyseVO> taskAddressList(final StammkundeAnalyseQueryVO queryVO) {
        verifyParamsTime(queryVO);
        preparePoint(queryVO);
        List<FollowTask> tasks = followTaskService.list(Wrappers.<FollowTask>lambdaQuery()
                .ne(FollowTask::getType, FollowTypeEnum.AC)
                .eq(FollowTask::getState, TaskStateEnum.DEFEAT)
                .between(FollowTask::getCloseTime, queryVO.getStartTime(), queryVO.getEndTime())
        );
        if (CollectionUtils.isEmpty(tasks)) {
            return new ArrayList<>();
        }
        Set<Long> customerIds = tasks.stream().map(FollowTask::getCustomerId).collect(Collectors.toSet());
        queryVO.setCustomerIds(customerIds);
        List<StammkundeAnalyseDTO> list = customerService.analyseList(queryVO);
        return transfer2VO(list, queryVO);
    }

    public List<StammkundeAddressAnalyseVO> customerAddressList(final StammkundeAnalyseQueryVO queryVO) {
        BV.isNotEmpty(queryVO.getRegionCode(), () -> "必须选择一个地区");
        preparePoint(queryVO);
        List<StammkundeAnalyseDTO> list = customerService.analyseList(queryVO);
        return transfer2VO(list, queryVO);
    }

    public List<StammkundeAnalyseVO> stammkundeList(final StammkundeAnalyseQueryVO queryVO) {
        queryVO.setRegionCode(null);
        boolean verifyPoi = Objects.nonNull(queryVO.getLat()) && Objects.nonNull(queryVO.getLng());
        BV.isTrue(verifyPoi, () -> "中心点经纬度不正确");
        Double radius = queryVO.getRadius();
        boolean verifyRadius = Objects.nonNull(radius) && radius > 0;
        BV.isTrue(verifyRadius, () -> "半径范围不正确");
        BV.isTrue(radius <= 30000, () -> "半径范围不能大于30公里");

        preparePoint(queryVO);
        List<StammkundeAnalyseDTO> list = customerService.analyseList(queryVO);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        final GeoDistanceUtils.Poi centerPoint = new GeoDistanceUtils.Poi(queryVO.getLng().doubleValue(), queryVO.getLat().doubleValue());
        final double distance = queryVO.getRadius();
        return list.stream().filter(r -> GeoDistanceUtils.getDistanceByBd09(centerPoint, new GeoDistanceUtils.Poi(r.getLng().doubleValue(), r.getLat().doubleValue())) <= distance)
                .map(StammkundeAnalyseVO::with).collect(Collectors.toList());
    }

    private List<StammkundeAddressAnalyseVO> transfer2VO(List<StammkundeAnalyseDTO> list, StammkundeAnalyseQueryVO queryVO) {
        if (queryVO.hasRange()) {
            final GeoDistanceUtils.Poi centerPoint = new GeoDistanceUtils.Poi(queryVO.getLng().doubleValue(), queryVO.getLat().doubleValue());
            final double distance = queryVO.getRadius();
            list = list.stream().filter(r -> GeoDistanceUtils.getDistanceByBd09(centerPoint, new GeoDistanceUtils.Poi(r.getLng().doubleValue(), r.getLat().doubleValue())) <= distance).collect(Collectors.toList());
        }
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        List<StammkundeAddressAnalyseVO> analyseList = new ArrayList<>();
        Map<String, List<StammkundeAnalyseDTO>> map = list.stream().collect(Collectors.groupingBy(StammkundeAnalyseDTO::getRegionCode));
        for (Map.Entry<String, List<StammkundeAnalyseDTO>> entry : map.entrySet()) {
            StammkundeAddressAnalyseVO vo = new StammkundeAddressAnalyseVO();
            vo.setQuantity(entry.getValue().size());
            StammkundeAnalyseDTO dto = entry.getValue().get(0);
            vo.setRegionCode(dto.getRegionCode());
            vo.setRegionName(dto.getRegionName());
            analyseList.add(vo);
        }
        return analyseList;
    }


    private void verifyParamsTime(final StammkundeAnalyseQueryVO queryVO) {
        queryVO.setStartTime(DateUtil.getMonthFirstDay());
        queryVO.setEndTime(DateUtil.getEndInTime(DateUtil.getMonthEndDay()));

        String timeHorizon = queryVO.getTimeHorizon();
        BV.isNotBlank(timeHorizon, "时间范围不能为空");
        String[] times = timeHorizon.split(",");
        BV.isTrue(times.length > NumberUtils.INTEGER_ZERO, () -> "时间范围不正确");

        if (StringUtils.isNotBlank(times[0]) && NumberUtils.isDigits(times[0])) {
            LocalDateTime localDateTime = Instant.ofEpochMilli(NumberUtils.toLong(times[0])).atZone(ZoneId.systemDefault()).toLocalDateTime();
            queryVO.setStartTime(DateUtil.getBeginInTime(DateUtil.localDateTime2Date(localDateTime)));
        }
        if (times.length >= 2) {
            if (StringUtils.isNotBlank(times[1]) && NumberUtils.isDigits(times[1])) {
                LocalDateTime localDateTime = Instant.ofEpochMilli(NumberUtils.toLong(times[1])).atZone(ZoneId.systemDefault()).toLocalDateTime();
                queryVO.setEndTime(DateUtil.getEndInTime(DateUtil.localDateTime2Date(localDateTime)));
            }
        }
    }


    private void preparePoint(final StammkundeAnalyseQueryVO queryVO) {
        Double radius = queryVO.getRadius();
        if (Objects.isNull(radius) || radius <= 0) {
            return;
        }
        BigDecimal lat = queryVO.getLat();
        BigDecimal lng = queryVO.getLng();
        boolean bool = Objects.nonNull(lat) && Objects.nonNull(lng);
        if (!bool) {
            return;
        }
        GeoDistanceUtils.Square square = GeoDistanceUtils.calSquarePoint(new GeoDistanceUtils.Poi(lng.doubleValue(), lat.doubleValue()), radius);
        double minLat = square.getRightBottomPoint().getLatitude();
        double maxLat = square.getLeftTopPoint().getLatitude();

        double minLng = square.getLeftBottomPoint().getLongitude();
        double maxLng = square.getRightTopPoint().getLongitude();

        queryVO.setMinLat(BigDecimal.valueOf(minLat));
        queryVO.setMaxLat(BigDecimal.valueOf(maxLat));
        queryVO.setMinLng(BigDecimal.valueOf(minLng));
        queryVO.setMaxLng(BigDecimal.valueOf(maxLng));
    }
}