| | |
| | | package com.ruoyi.technology.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.technology.bean.dto.TechnologyBomStructureDto; |
| | | import com.ruoyi.technology.bean.vo.TechnologyBomStructureVo; |
| | | import com.ruoyi.technology.mapper.TechnologyBomMapper; |
| | | import com.ruoyi.technology.mapper.TechnologyBomStructureMapper; |
| | | import com.ruoyi.technology.mapper.TechnologyOperationMapper; |
| | | import com.ruoyi.technology.pojo.TechnologyBom; |
| | | import com.ruoyi.technology.pojo.TechnologyBomStructure; |
| | | import com.ruoyi.technology.service.TechnologyBomStructureService; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | /** |
| | | * <p> |
| | | * BOM产品结构表 服务实现类 |
| | | * </p> |
| | | * |
| | | * @author 芯导软件(江苏)有限公司 |
| | | * @since 2026-04-20 10:06:17 |
| | | */ |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class TechnologyBomStructureServiceImpl extends ServiceImpl<TechnologyBomStructureMapper, TechnologyBomStructure> implements TechnologyBomStructureService { |
| | | |
| | | private final TechnologyBomStructureMapper technologyBomStructureMapper; |
| | | private final TechnologyBomMapper technologyBomMapper; |
| | | private final ProductModelMapper productModelMapper; |
| | | private final TechnologyOperationMapper technologyOperationMapper; |
| | | |
| | | /** |
| | | * 全量同步 BOM 的扁平物料明细:一行只表示“某个物料规格在某道工序被消耗”。 |
| | | * 不再有父子层级、单位用量、需求数量和单位配置。 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Boolean addTechnologyBomStructure(TechnologyBomStructureDto dto) { |
| | | Long bomId = dto.getBomId(); |
| | | if (bomId == null) { |
| | | throw new ServiceException("BOM ID不能为空"); |
| | | } |
| | | TechnologyBom bom = technologyBomMapper.selectById(bomId); |
| | | if (bom == null) { |
| | | throw new ServiceException("BOM不存在"); |
| | | } |
| | | |
| | | List<TechnologyBomStructureDto> detailList = dto.getDetailList() == null |
| | | ? Collections.emptyList() |
| | | : dto.getDetailList(); |
| | | |
| | | List<TechnologyBomStructure> dbList = this.list(new LambdaQueryWrapper<TechnologyBomStructure>() |
| | | .eq(TechnologyBomStructure::getBomId, bomId)); |
| | | Set<Long> dbIds = new HashSet<>(); |
| | | for (TechnologyBomStructure dbItem : dbList) { |
| | | dbIds.add(dbItem.getId()); |
| | | } |
| | | |
| | | Set<Long> submittedIds = new HashSet<>(); |
| | | Set<String> relationKeys = new HashSet<>(); |
| | | List<TechnologyBomStructure> insertList = new ArrayList<>(); |
| | | List<TechnologyBomStructure> updateList = new ArrayList<>(); |
| | | |
| | | for (TechnologyBomStructureDto item : detailList) { |
| | | Long productModelId = item.getProductModelId(); |
| | | Long operationId = item.getOperationId(); |
| | | validateMaterial(bom, productModelId); |
| | | validateOperation(operationId); |
| | | if (!relationKeys.add(productModelId + "#" + operationId)) { |
| | | throw new ServiceException("同一物料规格在同一工序下不能重复配置"); |
| | | } |
| | | |
| | | TechnologyBomStructure entity = new TechnologyBomStructure(); |
| | | entity.setBomId(bomId); |
| | | entity.setProductModelId(productModelId); |
| | | entity.setOperationId(operationId); |
| | | // 扁平 BOM 不再使用层级和数量语义,历史列统一置空。 |
| | | entity.setParentId(null); |
| | | entity.setUnitQuantity(null); |
| | | entity.setDemandedQuantity(null); |
| | | entity.setUnit(null); |
| | | |
| | | if (item.getId() == null) { |
| | | insertList.add(entity); |
| | | } else { |
| | | if (!dbIds.contains(item.getId())) { |
| | | throw new ServiceException("BOM物料明细不存在或不属于当前BOM"); |
| | | } |
| | | entity.setId(item.getId()); |
| | | submittedIds.add(item.getId()); |
| | | updateList.add(entity); |
| | | } |
| | | } |
| | | |
| | | Set<Long> deleteIds = new HashSet<>(dbIds); |
| | | deleteIds.removeAll(submittedIds); |
| | | if (!deleteIds.isEmpty()) { |
| | | this.removeByIds(deleteIds); |
| | | } |
| | | if (!updateList.isEmpty()) { |
| | | this.updateBatchById(updateList); |
| | | } |
| | | if (!insertList.isEmpty()) { |
| | | this.saveBatch(insertList); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 根据BOM查询扁平物料明细,按稳定顺序返回。 |
| | | */ |
| | | @Override |
| | | public List<TechnologyBomStructureVo> listByBomId(Long bomId) { |
| | | if (bomId == null) { |
| | | return new ArrayList<>(); |
| | | } |
| | | return technologyBomStructureMapper.listByBomId(bomId); |
| | | } |
| | | |
| | | /** |
| | | * 校验物料规格:必须存在,且不能是 BOM 自身的成品规格。 |
| | | */ |
| | | private void validateMaterial(TechnologyBom bom, Long productModelId) { |
| | | if (productModelId == null) { |
| | | throw new ServiceException("请选择物料规格"); |
| | | } |
| | | ProductModel productModel = productModelMapper.selectById(productModelId); |
| | | if (productModel == null) { |
| | | throw new ServiceException("物料规格不存在"); |
| | | } |
| | | if (productModelId.equals(bom.getProductModelId())) { |
| | | throw new ServiceException("成品规格不能作为自身的物料"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 校验消耗工序必填且存在。 |
| | | */ |
| | | private void validateOperation(Long operationId) { |
| | | if (operationId == null) { |
| | | throw new ServiceException("请选择消耗工序"); |
| | | } |
| | | if (technologyOperationMapper.selectById(operationId) == null) { |
| | | throw new ServiceException("消耗工序不存在"); |
| | | } |
| | | } |
| | | } |