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.*; /** * 安全生产 - 主数据引用解析器 * *

模块内所有「人员」与「车间」字段统一走这里解析,避免每个 Service 重复写一遍。

* *

统一约定:业务表存 {@code xxxId} 关联主数据,同时保留 {@code xxxName} 作为快照。 * 保存时从主数据把名称带出写快照;查询时用主数据最新值覆盖快照, * 这样员工调岗、车间改名后台账会自动跟着变,而主数据被删时老记录仍能靠快照展示。

* * @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 employeeMap(Collection employeeIds) { // 注意:这里必须返回可接受 null key 的空 Map。 // 调用方会直接 map.get(记录里的 xxxId),而 xxxId 允许为 null(例如组织未设负责人、 // 证件未关联持证人),Map.of() 的 get(null) 会抛 NPE,导致列表接口 500。 if (CollUtil.isEmpty(employeeIds)) { return new HashMap<>(); } List 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 workshopMap(Collection workshopIds) { // 同上:车间编号允许为 null,空集合必须返回可接受 null key 的 Map if (CollUtil.isEmpty(workshopIds)) { return new HashMap<>(); } List 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)); } }