package com.ruoyi.technology.service.impl; 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.technology.bean.dto.TechnologyRoutingOperationDto; import com.ruoyi.technology.bean.dto.TechnologyRoutingOperationParamSyncDto; import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo; import com.ruoyi.technology.mapper.TechnologyOperationMapper; import com.ruoyi.technology.mapper.TechnologyRoutingMapper; import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper; import com.ruoyi.technology.mapper.TechnologyRoutingOperationParamMapper; import com.ruoyi.technology.pojo.TechnologyOperation; import com.ruoyi.technology.pojo.TechnologyRouting; import com.ruoyi.technology.pojo.TechnologyRoutingOperation; import com.ruoyi.technology.pojo.TechnologyRoutingOperationParam; import com.ruoyi.technology.service.TechnologyRoutingOperationParamService; import com.ruoyi.technology.service.TechnologyRoutingOperationService; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) @RequiredArgsConstructor public class TechnologyRoutingOperationServiceImpl extends ServiceImpl implements TechnologyRoutingOperationService { private final TechnologyRoutingOperationMapper technologyRoutingOperationMapper; private final TechnologyRoutingMapper technologyRoutingMapper; private final TechnologyOperationMapper technologyOperationMapper; private final TechnologyRoutingOperationParamMapper technologyRoutingOperationParamMapper; private final TechnologyRoutingOperationParamService technologyRoutingOperationParamService; @Override public IPage pageTechnologyRoutingOperation(Page page, TechnologyRoutingOperationDto technologyRoutingOperationDto) { return technologyRoutingOperationMapper.pageTechnologyRoutingOperation(page, technologyRoutingOperationDto); } @Override public List listTechnologyRoutingOperation(TechnologyRoutingOperationDto technologyRoutingOperationDto) { return technologyRoutingOperationMapper.listTechnologyRoutingOperation(technologyRoutingOperationDto); } @Override public TechnologyRoutingOperationVo getTechnologyRoutingOperationInfo(Long id) { return technologyRoutingOperationMapper.getTechnologyRoutingOperationInfo(id); } @Override public boolean saveTechnologyRoutingOperation(TechnologyRoutingOperation technologyRoutingOperation) { if (technologyRoutingOperation.getTechnologyRoutingId() == null || technologyRoutingMapper.selectById(technologyRoutingOperation.getTechnologyRoutingId()) == null) { throw new RuntimeException("工艺路线不存在,无法保存工序"); } if (technologyRoutingOperation.getDragSort() == null || technologyRoutingOperation.getDragSort() <= 0) { technologyRoutingOperation.setDragSort(nextDragSort(technologyRoutingOperation.getTechnologyRoutingId())); } boolean saved = this.save(technologyRoutingOperation); if (saved) { TechnologyRoutingOperationParamSyncDto syncDto = new TechnologyRoutingOperationParamSyncDto(); syncDto.setTechnologyRoutingOperationId(technologyRoutingOperation.getId()); syncDto.setReplaceExisting(true); technologyRoutingOperationParamService.syncTechnologyRoutingOperationParam(syncDto); } return saved; } /** * 全量保存工艺路线工序: * 1) 按提交顺序作为工序顺序(dragSort 从 1 开始); * 2) 每道工序只允许出现一次,与“按BOM工序去重生成”保持一致; * 3) 工序产出规格固定为工艺路线的成品规格; * 4) 未回传的工序连同参数快照一并删除。 */ @Override public boolean saveRouteOperations(TechnologyRoutingOperationDto dto) { if (dto == null) { throw new ServiceException("参数不能为空"); } Long technologyRoutingId = dto.getTechnologyRoutingId() != null ? dto.getTechnologyRoutingId() : dto.getRouteId(); if (technologyRoutingId == null) { throw new ServiceException("工艺路线ID不能为空"); } TechnologyRouting technologyRouting = technologyRoutingMapper.selectById(technologyRoutingId); if (technologyRouting == null) { throw new ServiceException("工艺路线不存在"); } List operationList = dto.getOperationList() == null ? Collections.emptyList() : dto.getOperationList(); List dbList = this.list(Wrappers.lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRoutingId)); Set dbIds = dbList.stream().map(TechnologyRoutingOperation::getId).collect(Collectors.toSet()); Set submittedIds = new HashSet<>(); Set submittedOperationIds = new HashSet<>(); List insertList = new ArrayList<>(); List updateList = new ArrayList<>(); int dragSort = 1; for (TechnologyRoutingOperationDto item : operationList) { Long technologyOperationId = item.getTechnologyOperationId(); if (technologyOperationId == null) { throw new ServiceException("请为所有工序选择工艺工序"); } TechnologyOperation technologyOperation = technologyOperationMapper.selectById(technologyOperationId); if (technologyOperation == null) { throw new ServiceException("工艺工序不存在"); } if (!submittedOperationIds.add(technologyOperationId)) { throw new ServiceException("同一道工序不能重复出现在工艺路线中:" + technologyOperation.getName()); } TechnologyRoutingOperation entity = new TechnologyRoutingOperation(); entity.setTechnologyRoutingId(technologyRoutingId); entity.setProductModelId(technologyRouting.getProductModelId()); entity.setTechnologyOperationId(technologyOperationId); entity.setDragSort(dragSort++); entity.setIsQuality(technologyOperation.getIsQuality()); entity.setIsProduction(technologyOperation.getIsProduction()); entity.setType(technologyOperation.getType()); if (item.getId() == null) { insertList.add(entity); } else { if (!dbIds.contains(item.getId())) { throw new ServiceException("工艺路线工序不存在或不属于当前工艺路线"); } entity.setId(item.getId()); submittedIds.add(item.getId()); updateList.add(entity); } } Set deleteIds = new HashSet<>(dbIds); deleteIds.removeAll(submittedIds); if (!deleteIds.isEmpty()) { // 删除工序时同时清理其参数快照,避免留下孤立数据 technologyRoutingOperationParamMapper.delete(Wrappers.lambdaQuery() .in(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, deleteIds)); for (Long deleteId : deleteIds) { removeTechnologyRoutingOperation(deleteId); } } if (!updateList.isEmpty()) { this.updateBatchById(updateList); } for (TechnologyRoutingOperation insert : insertList) { saveTechnologyRoutingOperation(insert); } return true; } @Override public boolean removeTechnologyRoutingOperation(Long id) { TechnologyRoutingOperation technologyRoutingOperation = this.getById(id); if (technologyRoutingOperation == null) { return false; } boolean removed = this.removeById(id); if (removed) { resetDragSort(technologyRoutingOperation.getTechnologyRoutingId()); } return removed; } @Override public int sort(TechnologyRoutingOperation technologyRoutingOperation) { //查询被改动的这条数据 TechnologyRoutingOperation oldtechnologyRoutingOperation = technologyRoutingOperationMapper.selectById(technologyRoutingOperation.getId()); //查询该工艺路线的所有工序并按照顺序排序 List technologyRouteOperations = technologyRoutingOperationMapper.selectList(Wrappers.lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, oldtechnologyRoutingOperation.getTechnologyRoutingId()) .orderByAsc(TechnologyRoutingOperation::getDragSort)); // 获取目标位置(移动到第几个之后) Integer targetPosition = technologyRoutingOperation.getDragSort(); if (targetPosition != null && targetPosition >= 0) { // 移动元素到新的位置 technologyRouteOperations.remove(oldtechnologyRoutingOperation); technologyRouteOperations.add(targetPosition-1, oldtechnologyRoutingOperation); // 更新所有受影响的排序字段 for (int i = 0; i < technologyRouteOperations.size(); i++) { TechnologyRoutingOperation item = technologyRouteOperations.get(i); if (!item.getId().equals(oldtechnologyRoutingOperation.getId())) { // 检查是否需要更新排序值 if (item.getDragSort() != i+1) { item.setDragSort(i+1); technologyRoutingOperationMapper.updateById(item); } } else { // 更新原记录的新排序位置 oldtechnologyRoutingOperation.setDragSort(targetPosition); technologyRoutingOperationMapper.updateById(oldtechnologyRoutingOperation); } } return 1; } return 0; } private Integer nextDragSort(Long technologyRoutingId) { TechnologyRoutingOperation lastOperation = technologyRoutingOperationMapper.selectOne( Wrappers.lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRoutingId) .orderByDesc(TechnologyRoutingOperation::getDragSort) .last("limit 1") ); if (lastOperation == null || lastOperation.getDragSort() == null) { return 1; } return lastOperation.getDragSort() + 1; } private void resetDragSort(Long technologyRoutingId) { List operationList = technologyRoutingOperationMapper.selectList( Wrappers.lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRoutingId) .orderByAsc(TechnologyRoutingOperation::getDragSort) .orderByAsc(TechnologyRoutingOperation::getId) ); for (int i = 0; i < operationList.size(); i++) { TechnologyRoutingOperation item = operationList.get(i); int dragSort = i + 1; if (item.getDragSort() == null || item.getDragSort() != dragSort) { item.setDragSort(dragSort); technologyRoutingOperationMapper.updateById(item); } } } }