tuqin
8 天以前 2d79937de52efd14c1796620f1930d5a7cedba25
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
157
158
159
160
package cn.iocoder.yudao.module.mes.service.safety;
 
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.safety.vo.risk.MesSafetyRiskPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.safety.vo.risk.MesSafetyRiskSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.safety.MesSafetyRiskDO;
import cn.iocoder.yudao.module.mes.dal.mysql.safety.MesSafetyRiskMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
 
import java.math.BigDecimal;
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.*;
 
/**
 * 安全生产 - 风险清单 Service 实现
 *
 * LEC 法(格雷厄姆-金尼法):
 * D = L × E × C
 * 等级:D≥320 重大(1);160≤D<320 较大(2);70≤D<160 一般(3);D<70 低(4)
 *
 * @author 超级管理员
 */
@Service
@Validated
public class MesSafetyRiskServiceImpl implements MesSafetyRiskService {
 
    /** 风险等级阈值 */
    private static final BigDecimal LEVEL_1_THRESHOLD = new BigDecimal("320");
    private static final BigDecimal LEVEL_2_THRESHOLD = new BigDecimal("160");
    private static final BigDecimal LEVEL_3_THRESHOLD = new BigDecimal("70");
 
    @Resource
    private MesSafetyRiskMapper riskMapper;
 
    @Resource
    private MesSafetyRiskUnitService riskUnitService;
 
    @Override
    public PageResult<MesSafetyRiskDO> getRiskPage(MesSafetyRiskPageReqVO pageReqVO) {
        return riskMapper.selectPage(pageReqVO);
    }
 
    @Override
    public MesSafetyRiskDO getRisk(Long id) {
        return riskMapper.selectById(id);
    }
 
    @Override
    public Long createRisk(MesSafetyRiskSaveReqVO createReqVO) {
        // 1. 风险单元必须存在
        riskUnitService.validateRiskUnitExists(createReqVO.getUnitId());
        // 2. 编码唯一
        validateCodeUnique(null, createReqVO.getCode());
        // 3. 转换并计算 LEC
        MesSafetyRiskDO risk = BeanUtils.toBean(createReqVO, MesSafetyRiskDO.class);
        applyLecEvaluation(risk);
        riskMapper.insert(risk);
        return risk.getId();
    }
 
    @Override
    public void updateRisk(MesSafetyRiskSaveReqVO updateReqVO) {
        validateRiskExists(updateReqVO.getId());
        riskUnitService.validateRiskUnitExists(updateReqVO.getUnitId());
        validateCodeUnique(updateReqVO.getId(), updateReqVO.getCode());
        MesSafetyRiskDO updateObj = BeanUtils.toBean(updateReqVO, MesSafetyRiskDO.class);
        applyLecEvaluation(updateObj);
        riskMapper.updateById(updateObj);
    }
 
    @Override
    public void deleteRisk(Long id) {
        validateRiskExists(id);
        riskMapper.deleteById(id);
    }
 
    @Override
    public List<MesSafetyRiskDO> getRiskListByUnitId(Long unitId) {
        return riskMapper.selectListByUnitId(unitId);
    }
 
    @Override
    public MesSafetyRiskDO validateRiskExists(Long id) {
        if (id == null) {
            throw exception(MES_SAFETY_RISK_NOT_EXISTS);
        }
        MesSafetyRiskDO risk = riskMapper.selectById(id);
        if (risk == null) {
            throw exception(MES_SAFETY_RISK_NOT_EXISTS);
        }
        return risk;
    }
 
    @Override
    public BigDecimal calculateRiskValue(BigDecimal likelihood, BigDecimal exposure, BigDecimal consequence) {
        if (likelihood == null || exposure == null || consequence == null) {
            return null;
        }
        if (likelihood.compareTo(BigDecimal.ZERO) <= 0
                || exposure.compareTo(BigDecimal.ZERO) <= 0
                || consequence.compareTo(BigDecimal.ZERO) <= 0) {
            throw exception(MES_SAFETY_RISK_LEC_INVALID);
        }
        // D = L × E × C,保留 2 位小数
        return likelihood.multiply(exposure).multiply(consequence)
                .setScale(2, java.math.RoundingMode.HALF_UP);
    }
 
    @Override
    public Integer calculateRiskLevel(BigDecimal riskValue) {
        if (riskValue == null) {
            return null;
        }
        if (riskValue.compareTo(LEVEL_1_THRESHOLD) >= 0) {
            return 1; // 重大风险
        }
        if (riskValue.compareTo(LEVEL_2_THRESHOLD) >= 0) {
            return 2; // 较大风险
        }
        if (riskValue.compareTo(LEVEL_3_THRESHOLD) >= 0) {
            return 3; // 一般风险
        }
        return 4;     // 低风险
    }
 
    /**
     * 计算并回填 D 值与风险等级
     */
    private void applyLecEvaluation(MesSafetyRiskDO risk) {
        // L/E/C 都为空时视为未评估,保持空值
        if (risk.getLikelihood() == null && risk.getExposure() == null && risk.getConsequence() == null) {
            risk.setRiskValue(null);
            risk.setRiskLevel(null);
            return;
        }
        BigDecimal riskValue = calculateRiskValue(risk.getLikelihood(), risk.getExposure(), risk.getConsequence());
        risk.setRiskValue(riskValue);
        risk.setRiskLevel(calculateRiskLevel(riskValue));
    }
 
    /**
     * 校验编码唯一(id 为空表示新增)
     */
    private void validateCodeUnique(Long id, String code) {
        MesSafetyRiskDO exists = riskMapper.selectByCode(code);
        if (exists == null) {
            return;
        }
        if (id == null || !Objects.equals(exists.getId(), id)) {
            throw exception(MES_SAFETY_RISK_CODE_DUPLICATE);
        }
    }
 
}