package cn.fw.morax.service.biz.salary; import cn.fw.common.data.mybatis.pagination.PageData; import cn.fw.common.page.AppPage; import cn.fw.common.web.auth.LoginAuthBean; import cn.fw.morax.common.constant.Constant; import cn.fw.morax.common.utils.PublicUtil; import cn.fw.morax.common.utils.StringUtils; import cn.fw.morax.common.utils.ThreadPoolUtil; import cn.fw.morax.domain.db.kpi.*; import cn.fw.morax.domain.db.salary.*; import cn.fw.morax.domain.dto.query.PaySalaryQueryDTO; import cn.fw.morax.domain.dto.query.SalaryPoolQueryDTO; import cn.fw.morax.domain.enums.*; import cn.fw.morax.domain.vo.SelectorVO; import cn.fw.morax.domain.vo.salary.*; import cn.fw.morax.rpc.erp.ErpRpcService; import cn.fw.morax.service.biz.CommonService; import cn.fw.morax.service.data.kpi.IndicatorUserValueService; import cn.fw.morax.service.data.salary.*; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; 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.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.time.LocalDate; import java.time.YearMonth; import java.time.temporal.TemporalAdjusters; import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ThreadPoolExecutor; import java.util.function.Function; import java.util.stream.Collectors; import static cn.fw.common.businessvalidator.Validator.BV; /** * @author : kurisu * @version : 1.0 * @className : SalaryPoolBizService * @description : 薪酬池业务service * @date : 2022-05-05 11:10 */ @Service @Slf4j @RequiredArgsConstructor public class SalaryPoolBizService { private final SalaryGroupProjectSettinService salaryGroupProjectSettinService; private final SalaryGroupProjectService salaryGroupProjectService; private final SalaryGeneralSettinService salaryGeneralSettinService; private final SalaryGroupProjectHitLogService salaryGroupProjectHitLogService; private final SalaryPoolDetailService salaryPoolDetailService; private final SalaryGroupProjectPreconditionService salaryGroupProjectPreconditionService; private final SalaryGroupProjectParamService salaryGroupProjectParamService; private final SalaryGroupProjectTargetHitLogService salaryGroupProjectTargetHitLogService; private final IndicatorUserValueService indicatorUserValueService; private final SalaryGroupUserService salaryGroupUserService; private final SalaryPoolService salaryPoolService; private final CommonService commonService; private final ErpRpcService erpRpcService; @Value("${special-indicator-code.work-age}") @Getter private String workAgeCode; @Value("${special-indicator-code.base-salary}") @Getter private String baseSalaryCode; /** * 查询薪酬池 * * @param queryDTO 查询条件 * @return 薪酬池列表 */ public AppPage queryPool(final SalaryPoolQueryDTO queryDTO) { SalaryGeneralSettin settin = salaryGeneralSettinService.getOne(Wrappers.lambdaQuery() .eq(SalaryGeneralSettin::getGroupId, queryDTO.getGroupId()) .eq(SalaryGeneralSettin::getYn, Boolean.TRUE) , Boolean.FALSE); if (Objects.nonNull(settin)) { Boolean leaderVisibility = settin.getLeaderVisibility(); BV.isTrue(leaderVisibility, () -> "本集团不允许管理层查看员工薪资, 请联系集团管理员开通"); } if (PublicUtil.isNotEmpty(queryDTO.getManagerUserId())) { queryDTO.setManagerStaffList(commonService.queryManageStaffIds(queryDTO.getManagerUserId(), queryDTO.getMonthly())); } else { queryDTO.setManagerStaffList(commonService.queryManageStaffIds(queryDTO.getCurrentUserId(), queryDTO.getMonthly())); } prepareParams(queryDTO); log.info("薪酬池查询参数:{}", JSON.toJSONString(queryDTO)); AppPage page = AppPage.empty(queryDTO); long total = salaryPoolService.queryPagePoolTotal(queryDTO); if (total > 0) { page.setTotal(total); List salaryPoolList = salaryPoolService.queryPagePool(queryDTO); page.setData(salaryPoolList); } return page; } /** * 查询薪酬池详情 * * @param poolId 薪酬池id * @return 薪酬池详情 */ public StaffSalaryVO queryPoolDetail(final Long poolId, final YearMonth yearMonth) { SalaryPool pool = salaryPoolService.getById(poolId); boolean flag = Objects.nonNull(pool) && Boolean.TRUE.equals(pool.getYn()); BV.isTrue(flag, () -> "该人员薪酬数据不存在"); if (PublicUtil.isNotEmpty(yearMonth) && (!yearMonth.equals(pool.getMonthly()))) { List list = userSalaryPool(pool.getUserId(), yearMonth); BV.isNotEmpty(list, () -> "人员薪酬数据不存在"); pool = list.get(0); } return getPoolDetail(pool); } /** * 查询薪酬池详情 * * @param userId 用户id * @param yearMonth 月度 * @return 薪酬池详情 */ public StaffSalaryVO queryUserPoolDetail(final Long userId, final YearMonth yearMonth) { List list = userSalaryPool(userId, yearMonth); BV.isNotEmpty(list, () -> "人员薪酬数据不存在"); SalaryPool salaryPool = list.get(0); return getPoolDetail(salaryPool); } /** * 查询薪酬池选项 * * @param userId 用户id * @param yearMonth 月度 * @return 薪酬池选项 */ public Set salaryPoolSelector(final Long userId, final YearMonth yearMonth) { List list = userSalaryPool(userId, yearMonth); if (CollectionUtils.isEmpty(list)) { return new HashSet<>(); } return list.stream().map(r -> SelectorVO.whit(r.getId(), r.getShopName(), r.getPostName())).collect(Collectors.toSet()); } /** * 查询用户月度薪酬池列表 * * @param userId 用户id * @param yearMonth 月度 * @return 返回结果 */ @Cacheable(cacheNames = "salary", key = "':user:pool:'+ #yearMonth.toString() +':'+ #userId", unless = "#result.size() < 1") public List userSalaryPool(final Long userId, final YearMonth yearMonth) { List list = salaryPoolService.list(Wrappers.lambdaQuery() .eq(SalaryPool::getUserId, userId) .eq(SalaryPool::getMonthly, yearMonth) .eq(SalaryPool::getYn, Boolean.TRUE) .orderByDesc(SalaryPool::getId) ); if (CollectionUtils.isEmpty(list)) { return new ArrayList<>(); } return list; } /** * 查询详情 * * @param pool 薪酬池 * @return 详情 */ private StaffSalaryVO getPoolDetail(SalaryPool pool) { StaffSalaryVO vo = this.convertToSalaryVO(pool); buildPoolData(pool, vo); LocalDate dataDate = LocalDate.from(vo.getEndTime()); List salaryDetailList = salaryPoolDetailService.queryByPoolId(pool.getId(), pool.getSalaryGroupId(), dataDate); BV.isNotEmpty(salaryDetailList, () -> "该人员薪酬数据不存在"); Map> salaryTypeMap = salaryDetailList.stream().collect(Collectors.groupingBy(SalaryPoolDetailVO::getType)); for (Map.Entry> salaryDetail : salaryTypeMap.entrySet()) { detailClassification(vo, salaryDetail.getKey(), salaryDetail.getValue()); } Collections.sort(vo.getIncome()); Collections.sort(vo.getDeduct()); return vo; } /** * 查询薪酬开始日期,结束日期 * * @param salaryPool * @return */ public void buildPoolData(SalaryPool salaryPool, StaffSalaryVO vo) { SalaryGroupUser salaryGroupUser = salaryGroupUserService.getMonthLastData(salaryPool.getSgc(), salaryPool.getUserId(), salaryPool.getMonthly()); if (PublicUtil.isEmpty(salaryGroupUser)) { log.error("员工薪酬池:{},不存在绩效组人员数据", JSON.toJSONString(salaryPool)); vo.setEndTime(PublicUtil.getYesterdayOrEndOfMonthDay(salaryPool.getMonthly()).atTime(23, 59, 59)); vo.setStartTime(salaryPool.getMonthly().atDay(1).atTime(00, 00, 00)); return; } vo.setEndTime(salaryGroupUser.getDataDate().atTime(23, 59, 59)); SalaryGroupUser firstSalaryGroupUser = salaryGroupUserService.getMonthFirstData(salaryPool.getSgc(), salaryPool.getUserId(), salaryPool.getMonthly()); vo.setStartTime(firstSalaryGroupUser.getDataDate().atTime(00, 00, 00)); } /** * 查询薪酬结束日期 * * @param salaryPool * @return */ public LocalDate getPoolLastData(SalaryPool salaryPool) { SalaryGroupUser salaryGroupUser = salaryGroupUserService.getMonthLastData(salaryPool.getSgc(), salaryPool.getUserId(), salaryPool.getMonthly()); if (PublicUtil.isEmpty(salaryGroupUser)) { log.error("员工薪酬池:{},不存在绩效组人员数据", JSON.toJSONString(salaryPool)); return PublicUtil.getYesterdayOrEndOfMonthDay(salaryPool.getMonthly()); } return salaryGroupUser.getDataDate(); } /** * 详情分类 * * @param vo * @param type * @param list */ private void detailClassification(StaffSalaryVO vo, SalaryTypeEnum type, List list) { if (CollectionUtils.isEmpty(list)) { return; } summarySalaryRewards(vo, type, list); BigDecimal income = BigDecimal.ZERO; BigDecimal salaryTypeAmount = BigDecimal.ZERO; if (type.isPlus()) { List incomes = Lists.newArrayList(); for (SalaryPoolDetailVO detail : list) { income = income.add(detail.getActualSalaryAmount()); salaryTypeAmount = salaryTypeAmount.add(detail.getSalaryAmount()); IncomeProjectVO incomeProjectVO = this.convertToIncomeVO(detail); incomeProjectVO.setBaseWage(this.checkIsBaseWage(detail.getSalaryGroupProjectId())); incomes.add(incomeProjectVO); } vo.getIncome().add(new IncomeVO(type, salaryTypeAmount, incomes)); } else { List deducts = Lists.newArrayList(); for (SalaryPoolDetailVO detail : list) { salaryTypeAmount = salaryTypeAmount.add(detail.getSalaryAmount()); deducts.add(this.convertToDeductVO(detail)); } vo.getDeduct().add(new DeductVO(type, salaryTypeAmount, deducts)); } vo.setTotalWages(vo.getTotalWages().add(income)); } /** * 准备分页参数 * * @param queryVO */ private void prepareParams(SalaryPoolQueryDTO queryVO) { if (Objects.isNull(queryVO.getMonthly())) { queryVO.setMonthly(YearMonth.now()); } if (Objects.nonNull(queryVO.getOrder()) && StringUtils.isValid(queryVO.getOrderAtt())) { StringBuilder sb = new StringBuilder(" order by "); sb.append(StringUtils.toColumnName(queryVO.getOrderAtt()).toLowerCase()); if (queryVO.getOrder() == 1) { sb.append(" asc "); } else { sb.append(" desc "); } queryVO.setOrderString(sb.toString()); } if (PublicUtil.isEmpty(queryVO.getQueryStaffs()) && PublicUtil.isNotEmpty(queryVO.getQueryStaffs())) { List queryStaffIds = Arrays.stream(queryVO.getQueryStaffs().split(",")).map(Long::parseLong).collect(Collectors.toList()); queryVO.getManagerStaffList().retainAll(queryStaffIds); } } /** * 获取员工薪酬 * * @param staffIds * @param shopIds * @param yearMonth * @return */ public List getStaffsSalary(List staffIds, List shopIds, YearMonth yearMonth) { List pools = salaryPoolService.list(Wrappers.lambdaQuery() .in(PublicUtil.isNotEmpty(staffIds), SalaryPool::getUserId, staffIds) .in(PublicUtil.isNotEmpty(shopIds), SalaryPool::getShopId, shopIds) .eq(SalaryPool::getMonthly, yearMonth) .eq(SalaryPool::getYn, Boolean.TRUE) ); if (PublicUtil.isEmpty(pools)) { return new ArrayList<>(); } List staffSalaryVos = Lists.newArrayListWithCapacity(pools.size()); List poolIds = pools.stream().map(SalaryPool::getId).collect(Collectors.toList()); List poolDetails = salaryPoolDetailService.list(Wrappers.lambdaQuery() .in(SalaryPoolDetail::getSalaryPoolId, poolIds) .eq(SalaryPoolDetail::getYn, Boolean.TRUE) ); Map> poolDetailMap = poolDetails.stream().collect(Collectors.groupingBy(SalaryPoolDetail::getSalaryPoolId)); StaffSalaryDetailVO staffSalaryVo = null; for (SalaryPool salaryPool : pools) { staffSalaryVo = this.convertVo(salaryPool, poolDetailMap); staffSalaryVos.add(staffSalaryVo); } return staffSalaryVos; } /** * 汇总数据 * * @param vo * @param type * @param list */ private void summarySalaryRewards(StaffSalaryVO vo, SalaryTypeEnum type, List list) { switch (type) { case NECESSARY: { BigDecimal socialSecurity = list.stream() .map(SalaryPoolDetailVO::getActualSalaryAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); vo.setSocialSecurity(socialSecurity); break; } case AWARD: { BigDecimal paidRewards = list.stream() .map(SalaryPoolDetailVO::getProcessedAmount) .reduce(BigDecimal.ZERO, BigDecimal::add); vo.setPaidRewards(paidRewards); break; } case PENALTY: { BigDecimal paidRewards = list.stream() .map(detail -> { return detail.getActualSalaryAmount().subtract(detail.getProcessedAmount()); }) .reduce(BigDecimal.ZERO, BigDecimal::add); vo.setNoPaidPunishRewards(paidRewards); break; } } } /** * 转换为收入对象 * * @param detail * @return */ private IncomeProjectVO convertToIncomeVO(SalaryPoolDetailVO detail) { IncomeProjectVO incomeProjectVO = new IncomeProjectVO(); if (PublicUtil.isNotEmpty(detail.getSalaryGroupProjectId())) { incomeProjectVO.setSalaryGroupProjectId(detail.getSalaryGroupProjectId()); incomeProjectVO.setSalaryGroupProjectName(detail.getSalaryGroupProjectName()); } incomeProjectVO.setSalaryType(detail.getType()); incomeProjectVO.setCalMethod(detail.getCalMethod()); incomeProjectVO.setTotalAmount(detail.getSalaryAmount()); incomeProjectVO.setSendAmount(detail.getProcessedAmount()); incomeProjectVO.setNoSendAmount(detail.getActualSalaryAmount()); return incomeProjectVO; } /** * 转换为支出对象 * * @param detail * @return */ private DeductProjectVO convertToDeductVO(SalaryPoolDetailVO detail) { DeductProjectVO deductProjectVO = new DeductProjectVO(); if (PublicUtil.isNotEmpty(detail.getSalaryGroupProjectId())) { deductProjectVO.setSalaryGroupProjectId(detail.getSalaryGroupProjectId()); deductProjectVO.setSalaryGroupProjectName(detail.getSalaryGroupProjectName()); } deductProjectVO.setSalaryType(detail.getType()); deductProjectVO.setCalMethod(detail.getCalMethod()); deductProjectVO.setTotalAmount(detail.getSalaryAmount()); deductProjectVO.setPaidAmount(detail.getProcessedAmount()); deductProjectVO.setNoPaidAmount(detail.getActualSalaryAmount()); return deductProjectVO; } /** * 转换为员工薪酬vo * * @param pool * @return */ private StaffSalaryVO convertToSalaryVO(SalaryPool pool) { StaffSalaryVO vo = new StaffSalaryVO(); vo.setSalaryPoolId(pool.getId()); vo.setUserId(pool.getUserId()); vo.setUserName(pool.getUserName()); vo.setMonthly(pool.getMonthly()); vo.setPostId(pool.getPostId()); vo.setPostName(pool.getPostName()); vo.setShopId(pool.getShopId()); vo.setShopName(pool.getShopName()); vo.setWages(pool.getReward()); vo.setStarLevel(pool.getStarLevel()); vo.setTotalWages(BigDecimal.ZERO); vo.setIncome(new LinkedList<>()); vo.setDeduct(new LinkedList<>()); return vo; } /** * 转换为vo * * @param salaryPool * @param poolDetailMap * @return */ private StaffSalaryDetailVO convertVo(SalaryPool salaryPool, Map> poolDetailMap) { Long userId = salaryPool.getUserId(); Long poolId = salaryPool.getId(); StaffSalaryDetailVO staffSalaryVo = new StaffSalaryDetailVO(); staffSalaryVo.setId(salaryPool.getId()); staffSalaryVo.setSalaryGroupId(salaryPool.getSalaryGroupId()); staffSalaryVo.setUserId(userId); staffSalaryVo.setUserName(salaryPool.getUserName()); staffSalaryVo.setPostId(salaryPool.getPostId()); staffSalaryVo.setPostName(salaryPool.getPostName()); staffSalaryVo.setShopId(salaryPool.getShopId()); staffSalaryVo.setShopName(salaryPool.getShopName()); staffSalaryVo.setStarLevel(salaryPool.getStarLevel()); staffSalaryVo.setWages(salaryPool.getReward()); staffSalaryVo.setMonthly(salaryPool.getMonthly()); staffSalaryVo.setMonthlyStr(salaryPool.getMonthly().toString()); staffSalaryVo.setAward(BigDecimal.ZERO); staffSalaryVo.setRoyalties(BigDecimal.ZERO); staffSalaryVo.setSubsidy(BigDecimal.ZERO); staffSalaryVo.setNecessary(BigDecimal.ZERO); staffSalaryVo.setPenalty(BigDecimal.ZERO); if (!poolDetailMap.containsKey(poolId)) { return staffSalaryVo; } List staffSalaryDetails = poolDetailMap.get(poolId); for (SalaryPoolDetail salaryDetail : staffSalaryDetails) { BigDecimal amount = salaryDetail.getSalaryAmount(); switch (salaryDetail.getType()) { case AWARD: { staffSalaryVo.setAward(staffSalaryVo.getAward().add(amount)); break; } case ROYALTIES: { staffSalaryVo.setRoyalties(staffSalaryVo.getRoyalties().add(amount)); break; } case SUBSIDY: { staffSalaryVo.setSubsidy(staffSalaryVo.getSubsidy().add(amount)); break; } case NECESSARY: { staffSalaryVo.setNecessary(staffSalaryVo.getNecessary().add(amount)); break; } case PENALTY: { staffSalaryVo.setPenalty(staffSalaryVo.getPenalty().add(amount)); break; } } } return staffSalaryVo; } /** * 下载员工excel文件 * * @param currentUser * @param yearMonth * @param request * @param response */ public void downloadStaffsSalary(LoginAuthBean currentUser, YearMonth yearMonth, HttpServletRequest request, HttpServletResponse response) { BV.isTrue(erpRpcService.hasRole(currentUser.getUserId(), Constant.ROLE_CODE_WAGE_PAYMENT), "员工没有工资发放角色"); List shopIds = erpRpcService.queryUserRoleShopIds(currentUser.getUserId(), Constant.ROLE_CODE_WAGE_PAYMENT); List staffSalaryDetailVOS = this.getStaffsSalary(null, shopIds, yearMonth); String fileName = "工资清单.xlsx"; String encodeFileName = CommonService.getEncodeName(request, fileName); CommonService.downloadExcel(response, staffSalaryDetailVOS, encodeFileName, StaffSalaryDetailVO.class); } /** * 查询员工工资 * * @param dto * @return */ public AppPage getStaffsWages(PaySalaryQueryDTO dto) { if (!erpRpcService.hasRole(dto.getUserId(), Constant.ROLE_CODE_WAGE_PAYMENT)) { return new AppPage<>(); } // BV.isTrue(erpRpcService.hasRole(dto.getUserId(), Constant.ROLE_CODE_WAGE_PAYMENT), "员工没有工资发放角色"); List shopIds = erpRpcService.queryUserRoleShopIds(dto.getUserId(), Constant.ROLE_CODE_WAGE_PAYMENT); if (PublicUtil.isEmpty(shopIds)) { return new AppPage<>(); } PageData pageData = salaryPoolService.page(new PageData<>(dto.getCurrent(), dto.getPageSize()), Wrappers.lambdaQuery() .in(PublicUtil.isNotEmpty(shopIds), SalaryPool::getShopId, shopIds) .eq(SalaryPool::getMonthly, dto.getYearMonth()) .eq(SalaryPool::getYn, Boolean.TRUE) ); return PublicUtil.toPage(pageData, salaryPool -> { StaffSalaryInfoVO salaryInfoVO = PublicUtil.copy(salaryPool, StaffSalaryInfoVO.class); return salaryInfoVO; }); } /** * 绩效项目阶梯详情 * * @param salaryPoolId * @param salaryGroupProjectId * @param yearMonth * @return */ public SalaryGroupIndicatorDetailVO getHitProjectSetting(Long salaryPoolId, Long salaryGroupProjectId, YearMonth yearMonth) { SalaryPool pool = salaryPoolService.getById(salaryPoolId); BV.notNull(pool, "薪酬池不存在"); Long userId = pool.getUserId(); LocalDate localDate = getPoolLastData(pool); SalaryGroupIndicatorDetailVO detailVO = new SalaryGroupIndicatorDetailVO(); SalaryGroupProject salaryGroupProject = salaryGroupProjectService.getById(salaryGroupProjectId); BV.notNull(salaryGroupProject, "薪酬项目不存在"); if (PublicUtil.isNotEmpty(salaryGroupProject.getLaddersType())) { detailVO.setLaddersType(salaryGroupProject.getLaddersType()); } CountDownLatch countDownLatch = new CountDownLatch(3); ThreadPoolExecutor threadPool = ThreadPoolUtil.getInstance().getThreadPool(); threadPool.execute(() -> this.setSalaryGroupProjectParam(salaryGroupProjectId, userId, localDate, detailVO, countDownLatch)); threadPool.execute(() -> this.setSalaryGroupProjectPreconditionHitVos(salaryGroupProjectId, userId, localDate, detailVO, countDownLatch)); threadPool.execute(() -> this.setSalaryGroupProjectSetting(salaryGroupProject, userId, localDate, detailVO, countDownLatch)); detailVO.setName(salaryGroupProject.getName()); detailVO.setLadderParamAlias(salaryGroupProject.getLadderParamAlias()); detailVO.setCommissionParamAlias(salaryGroupProject.getCommissionParamAlias()); detailVO.setPreconditionAlias(salaryGroupProject.getPreconditionAlias()); detailVO.setCalMethod(salaryGroupProject.getCalMethod()); detailVO.setBeginDate(localDate.with(TemporalAdjusters.firstDayOfMonth()).atStartOfDay()); detailVO.setEndDate(localDate.atTime(23, 59, 59)); try { countDownLatch.await(); } catch (InterruptedException e) { log.error("绩效项目阶梯详情查询失败 -> salaryPoolId: [{}], salaryGroupProjectId: [{}], msg: [{}]", salaryPoolId, salaryGroupProjectId, e); } return detailVO; } /** * 设置阶梯 * * @param salaryGroupProject * @param userId * @param localDate * @param detailVO * @param countDownLatch */ public void setSalaryGroupProjectSetting(SalaryGroupProject salaryGroupProject, Long userId, LocalDate localDate, SalaryGroupIndicatorDetailVO detailVO, CountDownLatch countDownLatch) { Long salaryGroupProjectId = salaryGroupProject.getId(); List settings = salaryGroupProjectSettinService.list(Wrappers.lambdaQuery() .eq(SalaryGroupProjectSettin::getSalaryGroupProjectId, salaryGroupProjectId) .eq(SalaryGroupProjectSettin::getYn, Boolean.TRUE) .orderByAsc(SalaryGroupProjectSettin::getId) ); List salaryProjectHitLogs = salaryGroupProjectHitLogService.list(Wrappers.lambdaQuery() .eq(SalaryGroupProjectHitLog::getUserId, userId) .eq(SalaryGroupProjectHitLog::getSalaryGroupProjectId, salaryGroupProjectId) .eq(SalaryGroupProjectHitLog::getDataDate, localDate) .eq(SalaryGroupProjectHitLog::getYn, Boolean.TRUE) ); //固定提成 车系 switch (salaryGroupProject.getCalMethod()) { case CAR_SERIES: { this.setCarSeriesProjectDetail(salaryProjectHitLogs, settings, detailVO); break; } case LADDER: case FIXATION: case STAR: { this.setProjectDetail(salaryProjectHitLogs, settings, detailVO); break; } } countDownLatch.countDown(); } /** * 设置车系详情 * * @param salaryProjectHitLogs * @param settings * @param detailVO */ private void setProjectDetail(List salaryProjectHitLogs, List settings, SalaryGroupIndicatorDetailVO detailVO) { if (PublicUtil.isEmpty(salaryProjectHitLogs)) { detailVO.setSettings(settings.stream().map(setting -> { return PublicUtil.copy(setting, SalaryGroupProjectSettinVO.class); }).collect(Collectors.toList())); detailVO.setSalaryValue(new BigDecimal("0")); return; } SalaryGroupProjectHitLog salaryProjectHitLog = salaryProjectHitLogs.stream().findFirst().get(); Long hitSettingId = salaryProjectHitLog.getSalaryGroupProjectSettinId(); Boolean ratio = PublicUtil.isNotEmpty(detailVO.getLaddersType()) && DataTypeEnum.RATIO.equals(detailVO.getLaddersType()); detailVO.setSettings(settings.stream().map(setting -> { SalaryGroupProjectSettinVO settingVO = PublicUtil.copy(setting, SalaryGroupProjectSettinVO.class); settingVO.setHit((hitSettingId.equals(settingVO.getId()) ? Boolean.TRUE : Boolean.FALSE)); if (hitSettingId.equals(settingVO.getId())) { settingVO.setHitCommissionValue(salaryProjectHitLog.getHitCommissionValue()); settingVO.setHitLadderValue(salaryProjectHitLog.getHitLadderValue()); } if (ratio) { settingVO.processPercent(); } return settingVO; }).collect(Collectors.toList())); detailVO.setSalaryValue(salaryProjectHitLog.getSalaryValue()); if (PublicUtil.isEmpty(detailVO.getStarLevel())) { detailVO.setStarLevel(detailVO.getStarLevel()); } } /** * 设置车系详情 * * @param salaryProjectHitLogs * @param settings * @param detailVO */ private void setCarSeriesProjectDetail(List salaryProjectHitLogs, List settings, SalaryGroupIndicatorDetailVO detailVO) { Map hitMap = new HashMap<>(); if (PublicUtil.isNotEmpty(salaryProjectHitLogs)) { hitMap = salaryProjectHitLogs.stream().collect( Collectors.toMap(SalaryGroupProjectHitLog::getSalaryGroupProjectSettinId, Function.identity(), (v1, v2) -> v1)); } BigDecimal totalSalaryValue = new BigDecimal("0"); List settingVos = new ArrayList<>(); for (SalaryGroupProjectSettin setting : settings) { SalaryGroupProjectSettinVO settingVO = PublicUtil.copy(setting, SalaryGroupProjectSettinVO.class); if (hitMap.containsKey(setting.getId())) { SalaryGroupProjectHitLog hitLog = hitMap.get(setting.getId()); if (PublicUtil.isNotEmpty(hitLog)) { totalSalaryValue = totalSalaryValue.add(hitLog.getSalaryValue()); settingVO.setHit(Boolean.TRUE); settingVO.setSalaryValue(hitLog.getSalaryValue()); settingVO.setHitCommissionValue(hitLog.getHitCommissionValue()); } } settingVos.add(settingVO); } detailVO.setSettings(settingVos); detailVO.setSalaryValue(totalSalaryValue); } /** * 获取绩效参数 * * @param salaryGroupProjectId * @param userId * @param localDate * @return */ public void setSalaryGroupProjectParam(Long salaryGroupProjectId, Long userId, LocalDate localDate, SalaryGroupIndicatorDetailVO detailVO, CountDownLatch countDownLatch) { List params = salaryGroupProjectParamService.getSalaryGroupProjectParamVO(salaryGroupProjectId); if (PublicUtil.isEmpty(params)) { countDownLatch.countDown(); return ; } List targetParamIds = params.stream() .filter(param -> ! TargetTypeEnum.NO.equals(param.getTargetType())) .map(SalaryGroupProjectParamVO::getId).collect(Collectors.toList()); Map paramTargetHitLogMap = new HashMap<>(); if (PublicUtil.isNotEmpty(targetParamIds)) { List targetHitLogs = salaryGroupProjectTargetHitLogService.list(Wrappers.lambdaQuery() .in(SalaryGroupProjectTargetHitLog::getReferId, targetParamIds) .in(SalaryGroupProjectTargetHitLog::getTargetType, IndicatorTypeEnum.EXAMINE) .eq(SalaryGroupProjectTargetHitLog::getDataDate, localDate) .eq(SalaryGroupProjectTargetHitLog::getUserId, userId) .eq(SalaryGroupProjectTargetHitLog::getYn, Boolean.TRUE) ); paramTargetHitLogMap = targetHitLogs.stream() .collect(Collectors.toMap(SalaryGroupProjectTargetHitLog::getReferId, Function.identity(), (v1, v2) -> v1)); } List indicatorCodes = params.stream() .filter(param -> TargetTypeEnum.NO.equals(param.getTargetType())) .map(SalaryGroupProjectParamVO::getIndicatorCode).collect(Collectors.toList()); Map indicatorCodeValueMap = new HashMap<>(); if (PublicUtil.isNotEmpty(indicatorCodes)) { List indicatorUserValues = indicatorUserValueService.list(Wrappers.lambdaQuery() .in(IndicatorUserValue::getIndicatorCode, indicatorCodes) .eq(IndicatorUserValue::getDataDate, localDate) .eq(IndicatorUserValue::getUserId, userId) .eq(IndicatorUserValue::getYn, Boolean.TRUE) ); indicatorCodeValueMap = indicatorUserValues.stream() .collect(Collectors.toMap(IndicatorUserValue::getIndicatorCode, Function.identity(), (v1, v2) -> v1)); } List baseWageIndicatorCodes = new ArrayList(){{add(getWorkAgeCode());add(getBaseSalaryCode());}}; for (SalaryGroupProjectParamVO paramVO : params) { //有目标 if (paramTargetHitLogMap.containsKey(paramVO.getId())) { SalaryGroupProjectTargetHitLog targetHitLog = paramTargetHitLogMap.get(paramVO.getId()); paramVO.setReachValue(targetHitLog.getReachValue()); paramVO.setIndicatorValue(targetHitLog.getValue()); if (! TargetTypeEnum.NO.equals(paramVO.getTargetType())) { paramVO.setReachValue(targetHitLog.getReachValue().multiply(Constant.ONE_HUNDRED)); } if (DataTypeEnum.RATIO.equals(paramVO.getDataType())) { paramVO.setIndicatorValue(targetHitLog.getValue().multiply(Constant.ONE_HUNDRED)); } continue; } //无目标 if(indicatorCodeValueMap.containsKey(paramVO.getIndicatorCode())) { IndicatorUserValue indicatorUserValue = indicatorCodeValueMap.get(paramVO.getIndicatorCode()); BigDecimal indicatorOriginValue = commonService.queryIndicatorValue(paramVO.getIndicatorCode(), indicatorUserValue); switch (indicatorUserValue.getValueType()) { case WORK_AGE: case QUANTITY: { paramVO.setIndicatorValue(indicatorOriginValue); break; } case RATIO: { paramVO.setIndicatorValue(indicatorOriginValue.multiply(Constant.ONE_HUNDRED)); break; } } } paramVO.setBaseWage(baseWageIndicatorCodes.contains(paramVO.getIndicatorCode())); } Map> indicatorParamMap = params.stream() .collect(Collectors.groupingBy(SalaryGroupProjectParamVO::getParamType)); detailVO.setLadderParams(indicatorParamMap.getOrDefault(ParamTypeEnum.LADDER, new ArrayList<>())); detailVO.setCommissionParams(indicatorParamMap.getOrDefault(ParamTypeEnum.COMMISSION, new ArrayList<>())); countDownLatch.countDown(); } /** * 获取前置条件命中记录 * * @param salaryGroupProjectId * @param userId * @param localDate * @return */ public void setSalaryGroupProjectPreconditionHitVos(Long salaryGroupProjectId, Long userId, LocalDate localDate, SalaryGroupIndicatorDetailVO detailVO, CountDownLatch countDownLatch) { List preconditionVos = salaryGroupProjectPreconditionService.getHitVos(salaryGroupProjectId, userId, localDate); if (PublicUtil.isEmpty(preconditionVos)) { countDownLatch.countDown(); return; } List targetPreconditionIds = preconditionVos.stream() .filter(param -> ! TargetTypeEnum.NO.equals(param.getTargetType())) .map(SalaryGroupProjectPreconditionVO::getId).collect(Collectors.toList()); Map condTargetHitLogMap = new HashMap<>(); if (PublicUtil.isNotEmpty(targetPreconditionIds)) { List targetHitLogs = salaryGroupProjectTargetHitLogService.list(Wrappers.lambdaQuery() .in(SalaryGroupProjectTargetHitLog::getReferId, targetPreconditionIds) .in(SalaryGroupProjectTargetHitLog::getTargetType, IndicatorTypeEnum.PRE) .eq(SalaryGroupProjectTargetHitLog::getDataDate, localDate) .eq(SalaryGroupProjectTargetHitLog::getUserId, userId) .eq(SalaryGroupProjectTargetHitLog::getYn, Boolean.TRUE) ); condTargetHitLogMap = targetHitLogs.stream() .collect(Collectors.toMap(SalaryGroupProjectTargetHitLog::getReferId, Function.identity(), (v1, v2) -> v1)); } List indicatorCodes = preconditionVos.stream() .filter(param -> TargetTypeEnum.NO.equals(param.getTargetType())) .map(SalaryGroupProjectPreconditionVO::getIndicatorCode).collect(Collectors.toList()); Map indicatorCodeValueMap = new HashMap<>(); if (PublicUtil.isNotEmpty(indicatorCodes)) { List indicatorUserValues = indicatorUserValueService.list(Wrappers.lambdaQuery() .in(IndicatorUserValue::getIndicatorCode, indicatorCodes) .eq(IndicatorUserValue::getDataDate, localDate) .eq(IndicatorUserValue::getUserId, userId) .eq(IndicatorUserValue::getYn, Boolean.TRUE) ); indicatorCodeValueMap = indicatorUserValues.stream() .collect(Collectors.toMap(IndicatorUserValue::getIndicatorCode, Function.identity(), (v1, v2) -> v1)); } for (SalaryGroupProjectPreconditionVO preconditionVO : preconditionVos) { preconditionVO.setHit(Boolean.FALSE); //有目标 if (condTargetHitLogMap.containsKey(preconditionVO.getId())) { SalaryGroupProjectTargetHitLog targetHitLog = condTargetHitLogMap.get(preconditionVO.getId()); preconditionVO.setReachValue(targetHitLog.getReachValue()); preconditionVO.setIndicatorValue(targetHitLog.getValue()); if (! TargetTypeEnum.NO.equals(preconditionVO.getTargetType())) { preconditionVO.setReachValue(targetHitLog.getReachValue().multiply(Constant.ONE_HUNDRED)); } if (DataTypeEnum.RATIO.equals(preconditionVO.getDataType())) { preconditionVO.setIndicatorValue(targetHitLog.getValue().multiply(Constant.ONE_HUNDRED)); } preconditionVO.checkHit(); continue; } //无目标 if(indicatorCodeValueMap.containsKey(preconditionVO.getIndicatorCode())) { IndicatorUserValue indicatorUserValue = indicatorCodeValueMap.get(preconditionVO.getIndicatorCode()); BigDecimal indicatorOriginValue = commonService.queryIndicatorValue(preconditionVO.getIndicatorCode(), indicatorUserValue); switch (indicatorUserValue.getValueType()) { case WORK_AGE: case QUANTITY: { preconditionVO.setIndicatorValue(indicatorOriginValue); break; } case RATIO: { preconditionVO.setIndicatorValue(indicatorOriginValue.multiply(Constant.ONE_HUNDRED)); break; } } preconditionVO.checkHit(); } } detailVO.setConds(preconditionVos); countDownLatch.countDown(); } /** * 检查薪酬项是否是工龄工资、基本工资 * * @param salaryGroupProjectId * @return */ public Boolean checkIsBaseWage(Long salaryGroupProjectId) { List baseWageIndicatorCodes = new ArrayList(){{add(getWorkAgeCode());add(getBaseSalaryCode());}}; List salaryGroupProjectParams = salaryGroupProjectParamService.list(Wrappers.lambdaQuery() .eq(SalaryGroupProjectParam::getSalaryGroupProjectId, salaryGroupProjectId) .in(SalaryGroupProjectParam::getIndicatorCode, baseWageIndicatorCodes) .eq(SalaryGroupProjectParam::getYn, Boolean.TRUE) ); return PublicUtil.isNotEmpty(salaryGroupProjectParams); } }