SalaryGroupTask.java 6.75 KB
package cn.fw.morax.server.task;

import cn.fw.common.cache.locker.DistributedLocker;
import cn.fw.morax.common.constant.TimeTaskConstant;
import cn.fw.morax.common.utils.DateUtil;
import cn.fw.morax.common.utils.PublicUtil;
import cn.fw.morax.domain.db.salary.SalaryGroup;
import cn.fw.morax.domain.dto.query.SalaryGroupRepeatQueryDTO;
import cn.fw.morax.domain.enums.SettingStatusEnum;
import cn.fw.morax.service.biz.salary.SalaryGroupDataService;
import cn.fw.morax.service.biz.salary.SalaryGroupUserBizService;
import cn.fw.morax.service.data.salary.SalaryGroupService;
import cn.hutool.core.date.StopWatch;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

/**
 * @author : jiangchao
 * @className : SalaryGroupTask
 * @description : 薪酬组配置状态定时器
 * @date : 2022-04-07 15:29
 */
@Component
@Slf4j
@RequiredArgsConstructor
@ConditionalOnProperty(prefix = "task", name = "switch", havingValue = "on")
public class SalaryGroupTask {

    private final SalaryGroupUserBizService salaryGroupUserBizService;
    private final SalaryGroupDataService salaryGroupDataService;
    private final SalaryGroupService salaryGroupService;
    private final DistributedLocker distributedLocker;

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

    /**
     * 每个月1号凌晨3点执行
     * 1. 将待生效数据改为生效中
     * 2. 将之前的配置设置为失效
     * 3. 处理重复数据,合并、拆分门店的绩效组配置需要把其他的重复配置失效
     */
    @Scheduled(cron = TimeTaskConstant.SALARY_GROUP)
    @Transactional(rollbackFor = Exception.class)
    public void processCurMonthEffectSalaryGroup() {
        Lock lock = distributedLocker.lock(getSalaryGroupKey());
        if (((RLock) lock).isLocked()) {
            try {
                log.info("定时任务【每月薪酬组配置状态改变】开始执行");
                //查找待生效数据
                LocalDate currentTime = LocalDate.now();
                List<SalaryGroup> beEffectiveSalaryGroups = salaryGroupService.list(Wrappers.<SalaryGroup>lambdaQuery()
                        .eq(SalaryGroup::getStatus, SettingStatusEnum.BE_EFFECTIVE)
                        .eq(SalaryGroup::getBeginTime, currentTime)
                );
                if (PublicUtil.isEmpty(beEffectiveSalaryGroups)) {
                    log.info("绩效组定时器:暂无即将生效的绩效组配置");
                    return;
                }
                //之前配置都设置为无效(之前配置一定被使用过)
                List<Long> preIds = beEffectiveSalaryGroups.stream()
                        .filter(kpiGroup -> PublicUtil.isNotEmpty(kpiGroup.getPreId()))
                        .map(SalaryGroup::getPreId).collect(Collectors.toList());
                salaryGroupDataService.modifyStatusByIds(preIds, SettingStatusEnum.INEFFECTIVE);

                //以岗位、门店的维度,出现重复的配置,将创建时间最早的设置为失效
                this.processEffectiveRepeatGroup(beEffectiveSalaryGroups);

                //生效的配置
                salaryGroupDataService.modifyStatusBySalaryGroups(beEffectiveSalaryGroups, SettingStatusEnum.EFFECTIVE);
            } catch (Exception e){
                log.error(e.getMessage(), e);
            } finally {
                lock.unlock();
            }
        }
    }

    /**
     * 处理当月之前的重复生效数据
     *
     * @param beEffectiveSalaryGroups
     */
    @Transactional(rollbackFor = Exception.class)
    public void processEffectiveRepeatGroup(List<SalaryGroup> beEffectiveSalaryGroups) {
        Map<Long, List<SalaryGroup>> groupKpiMap = beEffectiveSalaryGroups.stream().collect(Collectors.groupingBy(SalaryGroup::getGroupId));
        Long groupId = null;
        Long postId = null;
        List<SalaryGroup> kpis = null;
        Set<Long> shopIds = null;
        List<SalaryGroup> beEffectiveKpis = null;
        Map<Long, List<SalaryGroup>> postKpiMap = null;
        for (Map.Entry<Long, List<SalaryGroup>> entry : groupKpiMap.entrySet()) {
            groupId = entry.getKey();
            beEffectiveKpis = entry.getValue();
            postKpiMap = beEffectiveKpis.stream().collect(Collectors.groupingBy(SalaryGroup::getPostId));
            for (Map.Entry<Long, List<SalaryGroup>> postKpi : postKpiMap.entrySet()) {
                postId = postKpi.getKey();
                kpis = postKpi.getValue();
                shopIds = new HashSet<>();
                for (SalaryGroup salaryGroup : kpis) {
                    shopIds.addAll(salaryGroup.getShopIds());
                }
                SalaryGroupRepeatQueryDTO repeatQueryDTO = SalaryGroupRepeatQueryDTO.builder()
                        .shopIds(new ArrayList<>(shopIds))
                        .status(SettingStatusEnum.EFFECTIVE)
                        .groupId(groupId)
                        .postId(postId)
                        .build();
                List<SalaryGroup> effectSalaryGroups = salaryGroupService.queryRepeatSalaryGroup(repeatQueryDTO);
                salaryGroupDataService.modifyStatusBySalaryGroups(effectSalaryGroups, SettingStatusEnum.INEFFECTIVE);
            }
        }
    }


    /**
     * 生成昨日薪酬组人员
     */
    @Scheduled(cron = TimeTaskConstant.SALARY_GROUP_USER)
    public void asyncSalaryGroupUser() {
        final String lockKey = ":asyncSalaryGroupUser";
        Lock lock = distributedLocker.lock(lockKey);
        if (((RLock) lock).isLocked()) {
            log.info("薪酬组人员更新定时任务");
            StopWatch stopWatch = new StopWatch();
            stopWatch.start("薪酬组人员更新定时任务");
            LocalDateTime queryTime = LocalDateTime.now().minusDays(1);
            List<SalaryGroup> list = salaryGroupService.getAllEffectGroups(DateUtil.localDateTime2Date(queryTime));
            for (SalaryGroup salaryGroup : list) {
                salaryGroupUserBizService.asyncSalaryGroupUser(salaryGroup, queryTime.toLocalDate());
            }
            stopWatch.stop();
            log.info(stopWatch.prettyPrint(TimeUnit.SECONDS));
            lock.unlock();
        }
    }

}