package cn.iocoder.yudao.module.mes.service.pro.wage; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.pro.wage.vo.MesProWageQualityRulePageReqVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.wage.vo.MesProWageQualityRuleResolveRespVO; import cn.iocoder.yudao.module.mes.controller.admin.pro.wage.vo.MesProWageQualityRuleSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.process.MesProProcessDO; import cn.iocoder.yudao.module.mes.dal.dataobject.pro.wage.MesProWageQualityRuleDO; import cn.iocoder.yudao.module.mes.dal.mysql.pro.wage.MesProWageQualityRuleMapper; import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.util.Comparator; import java.util.List; import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; /** * MES 质量工资规则 Service 实现类 * * @author 超级管理员 */ @Service @Validated public class MesProWageQualityRuleServiceImpl implements MesProWageQualityRuleService { @Resource private MesProWageQualityRuleMapper ruleMapper; @Resource private MesProProcessService processService; @Override public PageResult getRulePage(MesProWageQualityRulePageReqVO pageReqVO) { return ruleMapper.selectPage(pageReqVO); } @Override public List getRuleListByProcessId(Long processId) { return ruleMapper.selectListByProcessId(processId); } @Override public Long createRule(MesProWageQualityRuleSaveReqVO createReqVO) { validateRule(createReqVO); MesProWageQualityRuleDO rule = BeanUtils.toBean(createReqVO, MesProWageQualityRuleDO.class) .setId(null) .setStatus(ObjUtil.defaultIfNull(createReqVO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) .setPriority(ObjUtil.defaultIfNull(createReqVO.getPriority(), 0)); ruleMapper.insert(rule); return rule.getId(); } @Override public void updateRule(MesProWageQualityRuleSaveReqVO updateReqVO) { validateRuleExists(updateReqVO.getId()); validateRule(updateReqVO); ruleMapper.updateById(BeanUtils.toBean(updateReqVO, MesProWageQualityRuleDO.class)); } @Override public void deleteRule(Long id) { validateRuleExists(id); ruleMapper.deleteById(id); } @Override public MesProWageQualityRuleResolveRespVO resolve(Long processId, Long routeId, BigDecimal passRate) { MesProWageQualityRuleResolveRespVO resp = new MesProWageQualityRuleResolveRespVO() .setProcessId(processId).setRouteId(routeId).setPassRate(passRate); if (processId == null || passRate == null) { return resp; } MesProWageQualityRuleDO rule = ruleMapper.selectListByProcessId(processId).stream() .filter(item -> Objects.equals(item.getStatus(), CommonStatusEnum.ENABLE.getStatus())) .filter(item -> item.getRouteId() == null || Objects.equals(item.getRouteId(), routeId)) .filter(item -> matchRate(item, passRate)) .sorted(Comparator // 路线更具体的优先 .comparingInt((MesProWageQualityRuleDO item) -> item.getRouteId() != null ? 1 : 0).reversed() .thenComparing(Comparator.comparingInt( (MesProWageQualityRuleDO item) -> ObjUtil.defaultIfNull(item.getPriority(), 0)).reversed()) .thenComparing(Comparator.comparing(MesProWageQualityRuleDO::getId).reversed())) .findFirst().orElse(null); if (rule == null) { return resp; } resp.setRuleId(rule.getId()).setRuleType(rule.getRuleType()) .setCoefficient(rule.getCoefficient()).setDeductionPerUnit(rule.getDeductionPerUnit()); return resp; } private static boolean matchRate(MesProWageQualityRuleDO rule, BigDecimal passRate) { if (rule.getMinRate() != null && passRate.compareTo(rule.getMinRate()) < 0) { return false; } return rule.getMaxRate() == null || passRate.compareTo(rule.getMaxRate()) < 0; } private MesProWageQualityRuleDO validateRuleExists(Long id) { MesProWageQualityRuleDO rule = ruleMapper.selectById(id); if (rule == null) { throw exception(PRO_WAGE_QUALITY_RULE_NOT_EXISTS); } return rule; } private void validateRule(MesProWageQualityRuleSaveReqVO reqVO) { MesProProcessDO process = processService.getProcess(reqVO.getProcessId()); if (process == null) { throw exception(PRO_FEEDBACK_PROCESS_NOT_EXISTS, reqVO.getProcessId()); } Integer ruleType = reqVO.getRuleType(); if (!Objects.equals(ruleType, MesProWageQualityRuleDO.RULE_TYPE_COEFFICIENT) && !Objects.equals(ruleType, MesProWageQualityRuleDO.RULE_TYPE_DEDUCTION)) { throw new ServiceException(PRO_WAGE_QUALITY_RULE_VALUE_INVALID.getCode(), StrUtil.format("工序[{}]的质量规则类型[{}]不合法;期望 1-合格率系数 / 2-不合格扣款,请重新选择", process.getName(), ruleType)); } BigDecimal minRate = reqVO.getMinRate(); BigDecimal maxRate = reqVO.getMaxRate(); if (minRate == null || maxRate == null) { throw new ServiceException(PRO_WAGE_QUALITY_RULE_RANGE_INVALID.getCode(), StrUtil.format("工序[{}]的质量规则合格率区间不完整:下限[{}],上限[{}];请同时填写下限与上限后重试", process.getName(), minRate, maxRate)); } if (minRate.compareTo(maxRate) >= 0) { throw new ServiceException(PRO_WAGE_QUALITY_RULE_RANGE_INVALID.getCode(), StrUtil.format("工序[{}]的质量规则合格率区间不合法:下限[{}%]必须小于上限[{}%];请调整区间后重试", process.getName(), minRate, maxRate)); } if (Objects.equals(ruleType, MesProWageQualityRuleDO.RULE_TYPE_COEFFICIENT)) { if (reqVO.getCoefficient() == null || reqVO.getCoefficient().signum() <= 0) { throw new ServiceException(PRO_WAGE_QUALITY_RULE_VALUE_INVALID.getCode(), StrUtil.format("工序[{}]的质量规则为「合格率系数」,期望系数大于 0,实际为[{}];请填写系数后重试", process.getName(), reqVO.getCoefficient())); } } else { if (reqVO.getDeductionPerUnit() == null || reqVO.getDeductionPerUnit().signum() < 0) { throw new ServiceException(PRO_WAGE_QUALITY_RULE_VALUE_INVALID.getCode(), StrUtil.format("工序[{}]的质量规则为「不合格扣款」,期望每件扣款不小于 0,实际为[{}];请填写扣款金额后重试", process.getName(), reqVO.getDeductionPerUnit())); } } } }