KpiGroupRankBizService.java 14.6 KB
package cn.fw.morax.service.biz.kpi;

import cn.fw.common.data.mybatis.pagination.PageData;
import cn.fw.common.exception.BusinessException;
import cn.fw.common.page.AppPage;
import cn.fw.morax.common.constant.Constant;
import cn.fw.morax.common.utils.MessageFormatUtil;
import cn.fw.morax.common.utils.PublicUtil;
import cn.fw.morax.domain.db.kpi.KpiGroup;
import cn.fw.morax.domain.db.kpi.KpiGroupRank;
import cn.fw.morax.domain.db.kpi.KpiGroupRankStarLadders;
import cn.fw.morax.domain.db.salary.SalaryPoolDetail;
import cn.fw.morax.domain.dto.KpiGroupRankDto;
import cn.fw.morax.domain.dto.KpiGroupRankStarLaddersDTO;
import cn.fw.morax.domain.dto.query.KpiGroupRankQueryDTO;
import cn.fw.morax.domain.enums.SettingStatusEnum;
import cn.fw.morax.domain.enums.StarEvaluationEnum;
import cn.fw.morax.domain.enums.StarLevelEnum;
import cn.fw.morax.domain.vo.kpi.KpiGroupRankStarLaddersVO;
import cn.fw.morax.domain.vo.kpi.KpiGroupRankVO;
import cn.fw.morax.domain.vo.kpi.KpiGroupVO;
import cn.fw.morax.domain.vo.kpi.KpiStarLaddersVO;
import cn.fw.morax.service.biz.CommonService;
import cn.fw.morax.service.data.kpi.KpiGroupRankService;
import cn.fw.morax.service.data.kpi.KpiGroupRankStarLaddersService;
import cn.fw.morax.service.data.kpi.KpiGroupService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.RoundingMode;
import java.time.YearMonth;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

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

@RequiredArgsConstructor
@Service
@Slf4j
public class KpiGroupRankBizService {

    private final KpiGroupRankStarLaddersService kpiGroupRankStarLaddersService;
    private final KpiGroupRankService kpiGroupRankService;
    private final KpiGroupService kpiGroupService;

    @Value("${spring.cache.custom.global-prefix}:kpi:group:save:")
    @Getter
    private String savePrefix;

    /**
     * 绩效排名列表
     *
     * @param dto
     * @return
     */
    public AppPage<KpiGroupRankVO> kpiGroupRankPage(KpiGroupRankQueryDTO dto) {
        AppPage<KpiGroupRankVO> page = AppPage.empty(dto);
        List<String> queryKgcs = getKgcsByPostId(dto);
        if (PublicUtil.isNotEmpty(dto.getPostId()) && PublicUtil.isEmpty(queryKgcs)) {
            return page;
        }
        dto.setKgcs(queryKgcs);
        Long total = kpiGroupRankService.queryPageRankTotal(dto);
        if (total <= 0) {
            return page;
        }

        List<KpiGroupRankVO> kpiGroupRankVOS = kpiGroupRankService.queryPageRank(dto);
        List<String> kgcs = kpiGroupRankVOS.stream().map(KpiGroupRankVO::getKgcs).collect(ArrayList::new, List::addAll, List::addAll);
        List<KpiGroup> kpiGroups = kpiGroupService.list(Wrappers.<KpiGroup>lambdaQuery()
                .eq(KpiGroup::getStatus, SettingStatusEnum.EFFECTIVE)
                .in(KpiGroup::getKgc, kgcs)
        );
        Map<String, KpiGroup> kgcKpiGroupMap = kpiGroups.stream().collect(Collectors.toMap(KpiGroup::getKgc, Function.identity(), (v1, v2) -> v1));
        for (KpiGroupRankVO kpiGroupRankVO : kpiGroupRankVOS) {
            kpiGroupRankVO.setPostIds(new ArrayList<>());
            kpiGroupRankVO.setPostNames(new HashSet<>());
            kpiGroupRankVO.setShopIds(new ArrayList<>());
            kpiGroupRankVO.setShopNames(new HashSet<>());
            kpiGroupRankVO.setKpiGroupNames(new ArrayList<>());
            for (String kgc : kpiGroupRankVO.getKgcs()) {
                if (kgcKpiGroupMap.containsKey(kgc)) {
                    KpiGroup kpiGroup = kgcKpiGroupMap.get(kgc);
                    kpiGroupRankVO.getPostIds().add(kpiGroup.getPostId());
                    kpiGroupRankVO.getPostNames().add(kpiGroup.getPostName());
                    kpiGroupRankVO.getShopIds().addAll(kpiGroup.getShopIds());
                    kpiGroupRankVO.getShopNames().addAll(kpiGroup.getShopNames());
                    if (PublicUtil.isNotEmpty(kpiGroup.getName())) {
                        kpiGroupRankVO.getKpiGroupNames().add(kpiGroup.getName());
                    }
                }
            }
        }
        page.setTotal(total);
        page.setData(kpiGroupRankVOS);
        return page;
    }

    /**
     * 根据岗位查询绩效组
     *
     * @param dto
     * @return
     */
    public List<String> getKgcsByPostId(KpiGroupRankQueryDTO dto) {
        if (PublicUtil.isEmpty(dto.getPostId())) {
            return null;
        }
        List<KpiGroup> kpiGroups = kpiGroupService.list(Wrappers.<KpiGroup>lambdaQuery()
                .eq(KpiGroup::getStatus, SettingStatusEnum.EFFECTIVE)
                .eq(KpiGroup::getYn, Boolean.TRUE)
                .eq(KpiGroup::getPostId, dto.getPostId())
        );
        if (PublicUtil.isEmpty(kpiGroups)) {
            return null;
        }
        return kpiGroups.stream().map(KpiGroup::getKgc).collect(Collectors.toList());
    }



    /**
     * 未选择绩效组列表
     *
     * @param dto
     * @return
     */
    public AppPage<KpiGroupVO> restKpiGroupPage(KpiGroupRankQueryDTO dto) {
        PageData<KpiGroup> pageData = kpiGroupService.page(new PageData<>(dto.getCurrent(), dto.getPageSize()),
                Wrappers.<KpiGroup>lambdaQuery()
                        .eq(KpiGroup::getStatus, SettingStatusEnum.EFFECTIVE.getValue())
                        .eq(KpiGroup::getGroupId, dto.getGroupId())
                        .eq(PublicUtil.isNotEmpty(dto.getPostId()), KpiGroup::getPostId, dto.getPostId())
                        .eq(KpiGroup::getYn, Boolean.TRUE)
        );
        return PublicUtil.toPage(pageData, kpiGroup -> {
            KpiGroupVO kpiGroupVo = PublicUtil.copy(kpiGroup, KpiGroupVO.class);
            kpiGroupVo.setBeginTime(YearMonth.from(kpiGroup.getBeginTime()));
            return kpiGroupVo;
        });
    }


    /**
     * 绩效组排名组合详情
     *
     * @param id
     * @return
     */
    public KpiGroupRankVO kpiGroupRankDetail(Long id) {
        KpiGroupRank kpiGroupRank = kpiGroupRankService.getById(id);
        KpiGroupRankVO kpiGroupRankVO = PublicUtil.copy(kpiGroupRank, KpiGroupRankVO.class);
        List<KpiGroup> kpiGroups = kpiGroupService.list(Wrappers.<KpiGroup>lambdaQuery()
                .eq(KpiGroup::getStatus, SettingStatusEnum.EFFECTIVE)
                .in(KpiGroup::getKgc, kpiGroupRankVO.getKgcs())
        );
        List<KpiGroupVO> kpiGroupVOS = PublicUtil.copyList(kpiGroups, KpiGroupVO.class);
        kpiGroupRankVO.setKpiGroups(kpiGroupVOS);

        List<KpiGroupRankStarLadders> starLadders = kpiGroupRankStarLaddersService.list(Wrappers.<KpiGroupRankStarLadders>lambdaQuery()
                .eq(KpiGroupRankStarLadders::getKpiGroupRankId, id)
                .eq(KpiGroupRankStarLadders::getYn, Boolean.TRUE)
        );
        List<KpiGroupRankStarLaddersVO> starLaddersVOS = PublicUtil.copyList(starLadders, KpiGroupRankStarLaddersVO.class);
        for (KpiGroupRankStarLaddersVO starLaddersVO : starLaddersVOS) {
            starLaddersVO.setUpper(starLaddersVO.getUpper().multiply(Constant.ONE_HUNDRED));
            starLaddersVO.setLower(starLaddersVO.getLower().multiply(Constant.ONE_HUNDRED));
        }
        kpiGroupRankVO.setStarLadders(starLaddersVOS);
        if (PublicUtil.isNotEmpty(kpiGroupRankVO.getRevokedScoreRatio())) {
            kpiGroupRankVO.setRevokedScoreRatio(kpiGroupRankVO.getRevokedScoreRatio().multiply(Constant.ONE_HUNDRED));
        }
        return kpiGroupRankVO;
    }


    /**
     * 绩效组排名配置保存
     *
     * @param dto
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveKpiGroupRank(KpiGroupRankDto dto) {
        checkKgcRepetition(dto.getId(), dto.getKgcs());
        checkNameRepetition(dto.getId(), dto.getName());
        checkStarLadders(dto.getStarLadders(), dto.getStarEvaluationType());

        KpiGroupRank kpiGroupRank = this.convertPO(dto);
        kpiGroupRankService.saveOrUpdate(kpiGroupRank);
        this.saveKpiGroupRankStarLadders(dto, kpiGroupRank);
    }

    /**
     * 转换对象
     *
     * @param dto
     * @return
     */
    public KpiGroupRank convertPO(KpiGroupRankDto dto) {
        KpiGroupRank kpiGroupRank = null;
        if (PublicUtil.isNotEmpty(dto.getId())) {
            kpiGroupRank = kpiGroupRankService.getById(dto.getId());
            BV.notNull(kpiGroupRank, "绩效组排名不存在");
            kpiGroupRank.setId(dto.getId());
        } else {
            kpiGroupRank = new KpiGroupRank();
        }
        kpiGroupRank.setGroupId(dto.getGroupId());
        kpiGroupRank.setYn(Boolean.TRUE);
        kpiGroupRank.setName(dto.getName());
        kpiGroupRank.setKgcs(dto.getKgcs());
        kpiGroupRank.setStarEvaluationType(dto.getStarEvaluationType());
        if (PublicUtil.isNotEmpty(dto.getRevokedScoreRatio())) {
            kpiGroupRank.setRevokedScoreRatio(dto.getRevokedScoreRatio().divide(Constant.ONE_HUNDRED, 2, RoundingMode.HALF_UP));
        }
        return kpiGroupRank;
    }

    /**
     * 检查绩效组排名名称是否重复
     *
     * @param id
     * @param name
     */
    public void checkNameRepetition(Long id, String name) {
        int count = kpiGroupRankService.count(Wrappers.<KpiGroupRank>lambdaQuery()
                .eq(KpiGroupRank::getName, name)
                .ne(PublicUtil.isNotEmpty(id), KpiGroupRank::getId, id)
                .eq(KpiGroupRank::getYn, Boolean.TRUE)
        );
        BV.isTrue(count <= 0, "绩效组排名名称重复,请重新输入");
    }

    /**
     * 检查绩效组排名名称是否重复
     *
     * @param kgcs
     */
    public void checkKgcRepetition(Long id, List<String> kgcs) {
        List<KpiGroupRankVO> kpiGroupRankVOS = kpiGroupRankService.queryByKgcs(kgcs, id);
        List<String> allKgcs = kpiGroupRankVOS.stream().map(KpiGroupRankVO::getKgcs).collect(ArrayList::new, List::addAll, List::addAll);
        if (PublicUtil.isEmpty(allKgcs)) {
            return;
        }
        allKgcs.retainAll(kgcs);
        List<KpiGroup> repetitionKpis = kpiGroupService.list(Wrappers.<KpiGroup>lambdaQuery()
                .eq(KpiGroup::getStatus, SettingStatusEnum.BE_EFFECTIVE)
                .eq(KpiGroup::getYn, Boolean.TRUE)
                .in(KpiGroup::getKgc, allKgcs)
        );
        String kpiName = repetitionKpis.stream().map(KpiGroup::getName).collect(Collectors.joining(","));
        BV.isEmpty(kpiGroupRankVOS, "绩效组【" + kpiName + "】已经在其他排名包中,请重试");
    }

    /**
     * 保存绩效星级评定阶梯
     *
     * @param dto
     * @param kpiGroupRank
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveKpiGroupRankStarLadders(KpiGroupRankDto dto, KpiGroupRank kpiGroupRank) {
        if (PublicUtil.isNotEmpty(dto.getId())) {
            kpiGroupRankStarLaddersService.update(Wrappers.<KpiGroupRankStarLadders>lambdaUpdate()
                    .eq(KpiGroupRankStarLadders::getKpiGroupRankId, dto.getId())
                    .eq(KpiGroupRankStarLadders::getYn, Boolean.TRUE)
                    .set(KpiGroupRankStarLadders::getYn, Boolean.FALSE)
            );
        }
        List<KpiGroupRankStarLaddersDTO> starLaddersDtos = dto.getStarLadders();
        List<KpiGroupRankStarLadders> starLadders = Lists.newArrayListWithCapacity(starLaddersDtos.size());
        Long kpiGroupRankId = kpiGroupRank.getId();
        KpiGroupRankStarLadders starLadder = null;
        for (KpiGroupRankStarLaddersDTO starLaddersDto : starLaddersDtos) {
            starLadder = PublicUtil.copy(starLaddersDto, KpiGroupRankStarLadders.class);
            starLadder.setUpper(starLadder.getUpper().divide(Constant.ONE_HUNDRED, 2, RoundingMode.HALF_UP));
            starLadder.setLower(starLadder.getLower().divide(Constant.ONE_HUNDRED, 2, RoundingMode.HALF_UP));
            starLadder.setKpiGroupRankId(kpiGroupRankId);
            starLadders.add(starLadder);
        }
        kpiGroupRankStarLaddersService.saveBatch(starLadders);
    }

    /**
     * 检查星级阶梯分值
     * 1. 赋初始值
     * 2. 校验连续性、上限下限大小、所有星级都已经配置
     * @param laddersDTOS
     */
    private void checkStarLadders(List<KpiGroupRankStarLaddersDTO> laddersDTOS, StarEvaluationEnum starEvaluationType) {
        Set<StarLevelEnum> levelEnumSet = Arrays.stream(StarLevelEnum.values()).collect(Collectors.toSet());
        Collections.sort(laddersDTOS, new Comparator<KpiGroupRankStarLaddersDTO>() {
            @Override
            public int compare(KpiGroupRankStarLaddersDTO o1, KpiGroupRankStarLaddersDTO o2) {
                if (starEvaluationType.equals(StarEvaluationEnum.SCORING_RATE)) {
                    return o2.getLevel().getValue() - o1.getLevel().getValue();
                } else {
                    return o1.getLevel().getValue() - o2.getLevel().getValue();
                }
            }
        });
        //校验阶梯
        CommonService.checkLadders(laddersDTOS);
        //阶梯值校验  标准分不能超过指标基础分,阶梯值必须连续
        for (KpiGroupRankStarLaddersDTO dto : laddersDTOS) {
            if (! levelEnumSet.remove(dto.getLevel())) {
                throw new BusinessException("【" + dto.getLevel().getName() + "】级的阶梯配置重复");
            }
        }
        if (levelEnumSet.size() != 0) {
            List<String> levels = levelEnumSet.stream().map(level -> {
                return level.getName() + "级";
            }).collect(Collectors.toList());
            throw new BusinessException("【" + String.join(",", levels) + "】阶梯未配置");
        }
    }

    /**
     * 根据id删除绩效组排名包
     * @param id
     */
    public void removeById(Long id) {
        kpiGroupRankService.removeById(id);
    }

    public static void main(String[] args) {
        List<KpiGroupRankVO> kpiGroupRankVOS = new ArrayList<>();
        KpiGroupRankVO kpiGroupRankVO1 = new KpiGroupRankVO();
        KpiGroupRankVO kpiGroupRankVO2 = new KpiGroupRankVO();
        kpiGroupRankVOS.add(kpiGroupRankVO1);
        kpiGroupRankVOS.add(kpiGroupRankVO2);
        kpiGroupRankVO1.setKgcs(new ArrayList<String>(){{add("123");add("234");}});
        kpiGroupRankVO2.setKgcs(new ArrayList<String>(){{add("333");add("444");}});
        List<String> kgcs = kpiGroupRankVOS.stream().map(KpiGroupRankVO::getKgcs).collect(ArrayList::new, List::addAll, List::addAll);
        System.out.println(JSON.toJSONString(kgcs));
    }

}