package cn.fw.morax.service.biz.calculator.salary; import cn.fw.morax.common.utils.DateUtil; import cn.fw.morax.domain.db.salary.*; import cn.fw.morax.domain.enums.ExtraSalaryTypeEnum; import cn.fw.morax.domain.enums.SalaryCalMethodEnum; import cn.fw.morax.domain.enums.SalaryTypeEnum; import cn.fw.morax.service.data.salary.SalaryExtraProjectService; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.YearMonth; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; /** * @author : kurisu * @version : 1.0 * @className : DynamicSalaryCalculator * @description : 动态薪资计算器 * @date : 2022-04-27 10:37 */ @Component @Slf4j public class DynamicSalaryCalculator extends SalaryBaseCalculator { private final SalaryExtraProjectService salaryExtraProjectService; @Autowired public DynamicSalaryCalculator(final SalaryExtraProjectService salaryExtraProjectService) { this.salaryExtraProjectService = salaryExtraProjectService; } @Override public BigDecimal calculate(SalaryGroupProject param1, SalaryGroupUser param2) { // 用不到这个计算器 // 动态金额类不在此计算 return null; } @Override public SalaryPoolDetail calcDynamicMoney(@NonNull SalaryPool pool, @NonNull LocalDate date, @NonNull ExtraSalaryTypeEnum extraSalaryTypeEnum) { SalaryPoolDetail poolDetail = createDetail(pool, date, extraSalaryTypeEnum); List projectList = queryProjectList(pool, date, extraSalaryTypeEnum); calculate(poolDetail, projectList); return poolDetail; } @Override public SalaryCalMethodEnum getCalMethod() { return SalaryCalMethodEnum.DYNAMIC; } private void calculate(SalaryPoolDetail poolDetail, List projectList) { BigDecimal actualSalaryAmount = projectList.stream() .filter(r -> !Boolean.TRUE.equals(r.getTimely())) .map(SalaryExtraProject::getMoney) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal processedAmount = projectList.stream() .filter(r -> Boolean.TRUE.equals(r.getTimely())) .map(SalaryExtraProject::getMoney) .reduce(BigDecimal.ZERO, BigDecimal::add); BigDecimal expectedAmount = actualSalaryAmount.add(processedAmount); poolDetail.setSalaryAmount(expectedAmount); poolDetail.setProcessedAmount(processedAmount); poolDetail.setActualSalaryAmount(actualSalaryAmount); } /** * 查询额外薪资记录 * * @param pool * @param date * @param extraSalaryTypeEnum * @return */ private List queryProjectList(SalaryPool pool, LocalDate date, ExtraSalaryTypeEnum extraSalaryTypeEnum) { LocalDate startTime = YearMonth.from(date).minusMonths(1L).atEndOfMonth(); LocalDateTime endTime = date.plusDays(1L).atStartOfDay(); //调岗前后还是同一个薪酬组,不算调岗。搜索调岗之前的门店,获取薪酬额外数据 List groupUsers = salaryGroupUserService.list(Wrappers.lambdaQuery() .eq(SalaryGroupUser::getSalaryGroupId, pool.getSalaryGroupId()) .eq(SalaryGroupUser::getPostId, pool.getPostId()) .eq(SalaryGroupUser::getUserId, pool.getUserId()) .ge(SalaryGroupUser::getDataDate, startTime) .le(SalaryGroupUser::getDataDate, date) .eq(SalaryGroupUser::getYn, Boolean.TRUE) ); List shopIds = groupUsers.stream().map(SalaryGroupUser::getShopId).distinct().collect(Collectors.toList()); List list = salaryExtraProjectService.list(Wrappers.lambdaQuery() .eq(SalaryExtraProject::getPostId, pool.getPostId()) .in(SalaryExtraProject::getShopId, shopIds) .eq(SalaryExtraProject::getUserId, pool.getUserId()) .eq(SalaryExtraProject::getSalaryType, extraSalaryTypeEnum) .gt(SalaryExtraProject::getDataDate, startTime) .lt(SalaryExtraProject::getDataDate, endTime) .eq(SalaryExtraProject::getYn, Boolean.TRUE) ); return Optional.ofNullable(list).orElse(new ArrayList<>()); } /** * 创建实体 * * @param pool * @param date * @param extraSalaryTypeEnum * @return */ private SalaryPoolDetail createDetail(SalaryPool pool, LocalDate date, ExtraSalaryTypeEnum extraSalaryTypeEnum) { SalaryPoolDetail poolDetail = new SalaryPoolDetail(); SalaryTypeEnum salaryTypeEnum = extraSalaryTypeTransform(extraSalaryTypeEnum); poolDetail.setSalaryPoolId(pool.getId()); poolDetail.setType(salaryTypeEnum); poolDetail.setSalaryAmount(BigDecimal.ZERO); poolDetail.setProcessedAmount(BigDecimal.ZERO); poolDetail.setActualSalaryAmount(BigDecimal.ZERO); poolDetail.setSalaryDate(date); poolDetail.setGroupId(pool.getGroupId()); poolDetail.setYn(Boolean.TRUE); return poolDetail; } /** * 枚举类型转换 * * @param extraSalaryTypeEnum * @return */ private SalaryTypeEnum extraSalaryTypeTransform(ExtraSalaryTypeEnum extraSalaryTypeEnum) { SalaryTypeEnum salaryTypeEnum = SalaryTypeEnum.AWARD; switch (extraSalaryTypeEnum) { case PENALTY: salaryTypeEnum = SalaryTypeEnum.PENALTY; break; case NECESSARY: salaryTypeEnum = SalaryTypeEnum.NECESSARY; break; case SUBSIDY: salaryTypeEnum = SalaryTypeEnum.SUBSIDY; break; case PERSON_TAX: salaryTypeEnum = SalaryTypeEnum.PERSON_TAX; break; default: break; } return salaryTypeEnum; } }