gaoluyang
2 天以前 8c65f898ed6e5b0c7a94c792c4562f6ec831dccd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
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<MesProWageQualityRuleDO> getRulePage(MesProWageQualityRulePageReqVO pageReqVO) {
        return ruleMapper.selectPage(pageReqVO);
    }
 
    @Override
    public List<MesProWageQualityRuleDO> 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()));
            }
        }
    }
 
}