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;
|
|
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("消耗工序不存在");
|
}
|
}
|
}
|