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
package cn.iocoder.yudao.module.mes.service.safety;
 
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.hrm.api.employee.HrmEmployeeApi;
import cn.iocoder.yudao.module.hrm.api.employee.dto.HrmEmployeeSimpleDTO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkshopDO;
import cn.iocoder.yudao.module.mes.dal.mysql.md.workstation.MesMdWorkshopMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
 
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
 
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.SafetyErrorCodeConstants.*;
 
/**
 * 安全生产 - 主数据引用解析器
 *
 * <p>模块内所有「人员」与「车间」字段统一走这里解析,避免每个 Service 重复写一遍。</p>
 *
 * <p>统一约定:业务表存 {@code xxxId} 关联主数据,同时保留 {@code xxxName} 作为快照。
 * 保存时从主数据把名称带出写快照;查询时用主数据最新值覆盖快照,
 * 这样员工调岗、车间改名后台账会自动跟着变,而主数据被删时老记录仍能靠快照展示。</p>
 *
 * @author 超级管理员
 */
@Component
public class SafetyRefResolver {
 
    @Resource
    private HrmEmployeeApi hrmEmployeeApi;
    @Resource
    private MesMdWorkshopMapper workshopMapper;
 
    // ==================== 员工 ====================
 
    /**
     * 按员工编号取员工,必须存在
     *
     * @throws cn.iocoder.yudao.framework.common.exception.ServiceException 员工不存在时抛出
     */
    public HrmEmployeeSimpleDTO requireEmployee(Long employeeId, cn.iocoder.yudao.framework.common.exception.ErrorCode errorCode) {
        if (employeeId == null) {
            throw exception(errorCode);
        }
        HrmEmployeeSimpleDTO employee = hrmEmployeeApi.getEmployee(employeeId);
        if (employee == null) {
            throw exception(errorCode);
        }
        return employee;
    }
 
    /**
     * 可空的员工解析:id 为空返回 null,不校验存在性(用于非必填字段)
     */
    public HrmEmployeeSimpleDTO findEmployee(Long employeeId) {
        return employeeId == null ? null : hrmEmployeeApi.getEmployee(employeeId);
    }
 
    /**
     * 批量取员工,返回 id -> 员工 的 Map
     */
    public Map<Long, HrmEmployeeSimpleDTO> employeeMap(Collection<Long> employeeIds) {
        // 注意:这里必须返回可接受 null key 的空 Map。
        // 调用方会直接 map.get(记录里的 xxxId),而 xxxId 允许为 null(例如组织未设负责人、
        // 证件未关联持证人),Map.of() 的 get(null) 会抛 NPE,导致列表接口 500。
        if (CollUtil.isEmpty(employeeIds)) {
            return new HashMap<>();
        }
        List<Long> ids = employeeIds.stream().filter(Objects::nonNull).distinct().toList();
        if (ids.isEmpty()) {
            return new HashMap<>();
        }
        return hrmEmployeeApi.getEmployeeList(ids).stream()
                .collect(Collectors.toMap(HrmEmployeeSimpleDTO::getId, e -> e, (a, b) -> a));
    }
 
    // ==================== 车间 ====================
 
    /**
     * 按车间编号取车间,必须存在
     */
    public MesMdWorkshopDO requireWorkshop(Long workshopId) {
        if (workshopId == null) {
            throw exception(SAFETY_WORKSHOP_NOT_EXISTS);
        }
        MesMdWorkshopDO workshop = workshopMapper.selectById(workshopId);
        if (workshop == null) {
            throw exception(SAFETY_WORKSHOP_NOT_EXISTS);
        }
        return workshop;
    }
 
    /**
     * 可空的车间解析
     */
    public MesMdWorkshopDO findWorkshop(Long workshopId) {
        return workshopId == null ? null : workshopMapper.selectById(workshopId);
    }
 
    /**
     * 批量取车间,返回 id -> 车间 的 Map
     */
    public Map<Long, MesMdWorkshopDO> workshopMap(Collection<Long> workshopIds) {
        // 同上:车间编号允许为 null,空集合必须返回可接受 null key 的 Map
        if (CollUtil.isEmpty(workshopIds)) {
            return new HashMap<>();
        }
        List<Long> ids = workshopIds.stream().filter(Objects::nonNull).distinct().toList();
        if (ids.isEmpty()) {
            return new HashMap<>();
        }
        return workshopMapper.selectBatchIds(ids).stream()
                .collect(Collectors.toMap(MesMdWorkshopDO::getId, w -> w, (a, b) -> a));
    }
 
}