package com.ruoyi.technology.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.technology.bean.dto.TechnologyRoutingDto; import com.ruoyi.technology.bean.vo.TechnologyRoutingVo; import com.ruoyi.technology.mapper.*; import com.ruoyi.technology.pojo.*; import com.ruoyi.technology.service.TechnologyRoutingService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) @RequiredArgsConstructor public class TechnologyRoutingServiceImpl extends ServiceImpl implements TechnologyRoutingService { private final TechnologyRoutingMapper technologyRoutingMapper; private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; private final TechnologyBomStructureMapper technologyBomStructureMapper; private final TechnologyOperationMapper technologyOperationMapper; private final TechnologyOperationParamMapper technologyOperationParamMapper; private final TechnologyParamMapper technologyParamMapper; private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper; @Override public IPage pageTechnologyRouting(Page page, TechnologyRoutingDto technologyRoutingDto) { return technologyRoutingMapper.pageTechnologyRouting(page, technologyRoutingDto); } @Override public TechnologyRoutingVo getTechnologyRoutingInfo(Long id) { TechnologyRouting technologyRouting = this.getById(id); if (technologyRouting == null) { return null; } return BeanUtil.copyProperties(technologyRouting, TechnologyRoutingVo.class); } @Override public Long saveTechnologyRouting(TechnologyRouting technologyRouting) { String code = OrderUtils.countTodayByCreateTime(technologyRoutingMapper, "GYLX", "process_route_code"); technologyRouting.setProcessRouteCode(code); technologyRoutingMapper.insert(technologyRouting); // 带入bom产品结构 syncRoutingOperationsByBom(technologyRouting); return technologyRouting.getId(); } @Override public boolean updateTechnologyRouting(TechnologyRouting technologyRouting) { boolean updated = this.updateById(technologyRouting); if (updated) { TechnologyRouting currentRouting = this.getById(technologyRouting.getId()); syncRoutingOperationsByBom(currentRouting); } return updated; } @Override public boolean removeTechnologyRouting(List ids) { if (ids == null || ids.isEmpty()) { return false; } List routingOperationList = technologyRoutingOperationMapper.selectList( Wrappers.lambdaQuery() .in(TechnologyRoutingOperation::getTechnologyRoutingId, ids)); if (!routingOperationList.isEmpty()) { List routingOperationIdList = routingOperationList.stream().map(TechnologyRoutingOperation::getId).collect(Collectors.toList()); technologyRoutingOperationParamMapper.delete(Wrappers.lambdaQuery() .in(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, routingOperationIdList)); } technologyRoutingOperationMapper.delete(Wrappers.lambdaQuery() .in(TechnologyRoutingOperation::getTechnologyRoutingId, ids)); return this.removeByIds(ids); } /** * 按当前选择的 BOM 重建工艺路线工序: * 1. 先删除该工艺路线下已有工序 * 2. 读取 BOM 结构中的 operation_id * 3. 按 BOM 出现顺序去重后重新写入工艺路线工序表 */ private void syncRoutingOperationsByBom(TechnologyRouting technologyRouting) { List oldRoutingOperationList = technologyRoutingOperationMapper.selectList( Wrappers.lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId())); if (!oldRoutingOperationList.isEmpty()) { List oldRoutingOperationIdList = oldRoutingOperationList.stream().map(TechnologyRoutingOperation::getId).collect(Collectors.toList()); technologyRoutingOperationParamMapper.delete(Wrappers.lambdaQuery() .in(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, oldRoutingOperationIdList)); technologyRoutingOperationMapper.delete(Wrappers.lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId())); } if (technologyRouting.getBomId() == null) { return; } List bomStructures = technologyBomStructureMapper.selectList( Wrappers.lambdaQuery() .eq(TechnologyBomStructure::getBomId, technologyRouting.getBomId()) .isNotNull(TechnologyBomStructure::getOperationId) .orderByDesc(TechnologyBomStructure::getId) ); if (bomStructures.isEmpty()) { throw new ServiceException("bom产品结构为空!"); } // 同一个 BOM 中可能重复引用相同工序,按照上一层的父节点的产品是否相同和工序是否相同 Map structureById = new HashMap<>(); for (TechnologyBomStructure bomStructure : bomStructures) { if (bomStructure != null && bomStructure.getId() != null) { structureById.put(bomStructure.getId(), bomStructure); } } Map uniqueOperationMap = new LinkedHashMap<>(); for (TechnologyBomStructure bomStructure : bomStructures) { Long outputProductModelId = resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId()); uniqueOperationMap.putIfAbsent(buildBomOperationDedupKey(bomStructure, outputProductModelId), bomStructure); } int dragSort = 1; for (TechnologyBomStructure bomStructure : uniqueOperationMap.values()) { TechnologyRoutingOperation routingOperation = new TechnologyRoutingOperation(); routingOperation.setTechnologyRoutingId(technologyRouting.getId()); routingOperation.setProductModelId(resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId())); routingOperation.setTechnologyOperationId(bomStructure.getOperationId()); routingOperation.setDragSort(dragSort++); routingOperation.setIsQuality(getOperationQuality(bomStructure.getOperationId())); technologyRoutingOperationMapper.insert(routingOperation); syncRoutingOperationParams(routingOperation.getId(), bomStructure.getOperationId()); } } private String buildBomOperationDedupKey(TechnologyBomStructure bomStructure, Long outputProductModelId) { Long operationId = bomStructure == null ? null : bomStructure.getOperationId(); Long parentId = bomStructure == null ? null : bomStructure.getParentId(); return operationId + "#" + outputProductModelId + "#" + parentId; } private Long resolveOutputProductModelId(TechnologyBomStructure bomStructure, Map structureById, Long routingProductModelId) { if (bomStructure == null) { return routingProductModelId; } Long parentId = bomStructure.getParentId(); if (parentId == null) { return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId(); } TechnologyBomStructure parent = structureById.get(parentId); if (parent != null && parent.getProductModelId() != null) { return parent.getProductModelId(); } return routingProductModelId != null ? routingProductModelId : bomStructure.getProductModelId(); } private void syncRoutingOperationParams(Long technologyRoutingOperationId, Long technologyOperationId) { List operationParamList = technologyOperationParamMapper.selectList( Wrappers.lambdaQuery() .eq(TechnologyOperationParam::getTechnologyOperationId, technologyOperationId) .orderByAsc(TechnologyOperationParam::getId)); if (operationParamList.isEmpty()) { return; } for (TechnologyOperationParam operationParam : operationParamList) { TechnologyParam technologyParam = technologyParamMapper.selectById(operationParam.getTechnologyParamId()); if (technologyParam == null) { continue; } TechnologyRoutingOperationParam snapshot = new TechnologyRoutingOperationParam(); snapshot.setTechnologyRoutingOperationId(technologyRoutingOperationId); snapshot.setTechnologyOperationParamId(operationParam.getId()); snapshot.setTechnologyOperationId(operationParam.getTechnologyOperationId()); snapshot.setParamId(technologyParam.getId()); snapshot.setParamCode(technologyParam.getParamCode()); snapshot.setParamName(technologyParam.getParamName()); snapshot.setParamType(technologyParam.getParamType()); snapshot.setParamFormat(technologyParam.getParamFormat()); snapshot.setUnit(technologyParam.getUnit()); snapshot.setIsRequired(technologyParam.getIsRequired()); snapshot.setRemark(technologyParam.getRemark()); snapshot.setStandardValue(operationParam.getStandardValue()); technologyRoutingOperationParamMapper.insert(snapshot); } } /** * 质检标识以工序基础表定义为准。 */ private Boolean getOperationQuality(Long operationId) { TechnologyOperation technologyOperation = technologyOperationMapper.selectById(operationId); return technologyOperation != null ? technologyOperation.getIsQuality() : null; } private String buildProcessRouteCode(Long id) { String dateStr = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")); String idStr = String.format("%06d", id); return "GYLX" + dateStr + idStr; } private boolean isNotBlank(String value) { return value != null && !value.trim().isEmpty(); } }