package com.ruoyi.technology.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 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.utils.OrderUtils; import com.ruoyi.technology.bean.dto.TechnologyRoutingDto; import com.ruoyi.technology.bean.vo.TechnologyRoutingVo; import com.ruoyi.technology.mapper.TechnologyBomStructureMapper; import com.ruoyi.technology.mapper.TechnologyOperationMapper; import com.ruoyi.technology.mapper.TechnologyRoutingMapper; import com.ruoyi.technology.mapper.TechnologyRoutingOperationMapper; import com.ruoyi.technology.pojo.TechnologyBomStructure; import com.ruoyi.technology.pojo.TechnologyOperation; import com.ruoyi.technology.pojo.TechnologyRouting; import com.ruoyi.technology.pojo.TechnologyRoutingOperation; 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.LinkedHashMap; import java.util.List; import java.util.Map; @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; @Override public IPage pageTechnologyRouting(Page page, TechnologyRoutingDto technologyRoutingDto) { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery(); queryWrapper.eq(technologyRoutingDto.getId() != null, TechnologyRouting::getId, technologyRoutingDto.getId()) .eq(technologyRoutingDto.getProductModelId() != null, TechnologyRouting::getProductModelId, technologyRoutingDto.getProductModelId()) .eq(technologyRoutingDto.getBomId() != null, TechnologyRouting::getBomId, technologyRoutingDto.getBomId()) .like(isNotBlank(technologyRoutingDto.getProcessRouteCode()), TechnologyRouting::getProcessRouteCode, technologyRoutingDto.getProcessRouteCode()) .like(isNotBlank(technologyRoutingDto.getDescription()), TechnologyRouting::getDescription, technologyRoutingDto.getDescription()) .orderByDesc(TechnologyRouting::getId); Page entityPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal()); return this.page(entityPage, queryWrapper).convert(item -> BeanUtil.copyProperties(item, TechnologyRoutingVo.class)); } @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); // 带入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; } 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) { technologyRoutingOperationMapper.delete(Wrappers.lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, technologyRouting.getId())); if (technologyRouting.getBomId() == null) { return; } List bomStructures = technologyBomStructureMapper.selectList( Wrappers.lambdaQuery() .eq(TechnologyBomStructure::getBomId, Long.valueOf(technologyRouting.getBomId())) .isNotNull(TechnologyBomStructure::getOperationId) .orderByAsc(TechnologyBomStructure::getId) ); if (bomStructures.isEmpty()) { return; } // 同一个 BOM 中可能重复引用相同工序,这里按首次出现顺序去重。 Map uniqueOperationMap = new LinkedHashMap<>(); for (TechnologyBomStructure bomStructure : bomStructures) { uniqueOperationMap.putIfAbsent(bomStructure.getOperationId(), bomStructure); } int dragSort = 1; for (TechnologyBomStructure bomStructure : uniqueOperationMap.values()) { TechnologyRoutingOperation routingOperation = new TechnologyRoutingOperation(); routingOperation.setTechnologyRoutingId(technologyRouting.getId()); routingOperation.setProductModelId(technologyRouting.getProductModelId()); routingOperation.setTechnologyOperationId(bomStructure.getOperationId()); routingOperation.setDragSort(dragSort++); routingOperation.setIsQuality(getOperationQuality(bomStructure.getOperationId())); technologyRoutingOperationMapper.insert(routingOperation); } } /** * 质检标识以工序基础表定义为准。 */ 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(); } }