package cn.iocoder.yudao.module.mes.service.safety; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.safety.vo.org.SafetyOrgRespVO; import cn.iocoder.yudao.module.mes.controller.admin.safety.vo.org.SafetyOrgSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.safety.SafetyOrgDO; import cn.iocoder.yudao.module.mes.dal.mysql.safety.SafetyOrgMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.util.ArrayList; import java.util.List; import java.util.Map; 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 * * @author 超级管理员 */ @Service @Validated public class SafetyOrgService { @Resource private SafetyOrgMapper safetyOrgMapper; @Resource private SafetyRefResolver refResolver; public Long createOrg(SafetyOrgSaveReqVO reqVO) { reqVO.setId(null); validateParent(reqVO.getParentId(), null); SafetyOrgDO org = BeanUtils.toBean(reqVO, SafetyOrgDO.class); org.setParentId(reqVO.getParentId() == null ? 0L : reqVO.getParentId()); applyLeader(org, reqVO.getLeaderId()); safetyOrgMapper.insert(org); return org.getId(); } public void updateOrg(SafetyOrgSaveReqVO reqVO) { validateOrgExists(reqVO.getId()); validateParent(reqVO.getParentId(), reqVO.getId()); SafetyOrgDO org = BeanUtils.toBean(reqVO, SafetyOrgDO.class); org.setParentId(reqVO.getParentId() == null ? 0L : reqVO.getParentId()); applyLeader(org, reqVO.getLeaderId()); safetyOrgMapper.updateById(org); } /** * 负责人:从员工档案带出姓名与电话并落快照 */ private void applyLeader(SafetyOrgDO org, Long leaderId) { org.setLeaderId(leaderId); if (leaderId == null) { org.setLeaderName(""); return; } var employee = refResolver.requireEmployee(leaderId, SAFETY_EMPLOYEE_REQUIRED); org.setLeaderName(employee.getName()); org.setLeaderPhone(employee.getPhone()); } public void deleteOrg(Long id) { validateOrgExists(id); if (safetyOrgMapper.selectCountByParentId(id) > 0) { throw exception(SAFETY_ORG_HAS_CHILDREN); } safetyOrgMapper.deleteById(id); } public SafetyOrgDO getOrg(Long id) { return validateOrgExists(id); } /** * 取负责人最新档案(供单条查询回填用) */ public cn.iocoder.yudao.module.hrm.api.employee.dto.HrmEmployeeSimpleDTO getLeader(Long leaderId) { return refResolver.findEmployee(leaderId); } /** * 查询组织树 */ public List getOrgTree() { List all = safetyOrgMapper.selectListOrdered(); List nodes = BeanUtils.toBean(all, SafetyOrgRespVO.class); // 负责人用员工档案最新姓名覆盖快照,员工改名/调岗后树也同步 var employeeMap = refResolver.employeeMap( all.stream().map(SafetyOrgDO::getLeaderId).toList()); nodes.forEach(node -> { var employee = employeeMap.get(node.getLeaderId()); if (employee != null) { node.setLeaderName(employee.getName()); } }); Map> grouped = nodes.stream() .collect(Collectors.groupingBy(SafetyOrgRespVO::getParentId, Collectors.toList())); nodes.forEach(node -> node.setChildren(grouped.getOrDefault(node.getId(), new ArrayList<>()))); List roots = grouped.getOrDefault(0L, new ArrayList<>()); if (CollUtil.isEmpty(roots)) { // 兼容 parentId 为空的脏数据 roots = nodes.stream().filter(n -> n.getParentId() == null || n.getParentId() == 0L).toList(); } return roots; } private void validateParent(Long parentId, Long selfId) { if (parentId == null || parentId == 0L) { return; } if (parentId.equals(selfId)) { throw exception(SAFETY_ORG_PARENT_IS_SELF); } SafetyOrgDO parent = safetyOrgMapper.selectById(parentId); if (parent == null) { throw exception(SAFETY_ORG_PARENT_NOT_EXISTS); } // 防止把父节点挂到自己的子孙下,形成环 if (selfId != null && isDescendant(parentId, selfId)) { throw exception(SAFETY_ORG_PARENT_IS_CHILD); } } private boolean isDescendant(Long candidateId, Long ancestorId) { Long current = candidateId; int guard = 0; while (current != null && current != 0L && guard++ < 100) { if (current.equals(ancestorId)) { return true; } SafetyOrgDO node = safetyOrgMapper.selectById(current); if (node == null) { return false; } current = node.getParentId(); } return false; } private SafetyOrgDO validateOrgExists(Long id) { if (id == null) { throw exception(SAFETY_ORG_NOT_EXISTS); } SafetyOrgDO org = safetyOrgMapper.selectById(id); if (org == null) { throw exception(SAFETY_ORG_NOT_EXISTS); } return org; } }