package com.ruoyi.basic.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.basic.dto.*; import com.ruoyi.basic.mapper.ProductMapper; import com.ruoyi.basic.mapper.ProductModelMapper; import com.ruoyi.basic.pojo.Product; import com.ruoyi.basic.pojo.ProductModel; import com.ruoyi.basic.service.IProductModelService; import com.ruoyi.common.enums.FileNameType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.OrderUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.common.utils.uuid.IdUtils; import com.ruoyi.other.mapper.TempFileMapper; import com.ruoyi.other.service.impl.TempFileServiceImpl; import com.ruoyi.production.mapper.ProductProcessMapper; import com.ruoyi.production.pojo.ProductProcess; import com.ruoyi.sales.mapper.CommonFileMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.sales.service.impl.CommonFileServiceImpl; import lombok.AllArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; /** * 【请填写功能名称】Service业务层处理 * * @author ruoyi * @date 2025-05-19 */ @Service @AllArgsConstructor public class ProductModelServiceImpl extends ServiceImpl implements IProductModelService { private final ProductMapper productMapper; private final SalesLedgerProductMapper salesLedgerProductMapper; private ProductModelMapper productModelMapper; private final CommonFileServiceImpl commonFileService; private final ProductProcessMapper productProcessMapper; private final TempFileServiceImpl tempFileService; @Override public int addOrEditProductModel(ProductModelDto productModelDto) throws IOException { if(StringUtils.isEmpty(productModelDto.getProductName())){ throw new RuntimeException("产品名称不能为空"); } Product product = productMapper.selectOne(new LambdaQueryWrapper() // .eq(Product::getModel, productModelDto.getModel()) .eq(Product::getProductName, productModelDto.getProductName())); if (productModelDto.getId() == null) { if(product == null){ product = new Product(); product.setProductName(productModelDto.getProductName()); productMapper.insert(product); } ProductModel productModel = new ProductModel(); BeanUtils.copyProperties(productModelDto,productModel); productModel.setProductId(product.getId()); productModelMapper.insert(productModel); if(CollectionUtils.isNotEmpty(productModelDto.getTempFileIds())){ commonFileService.migrateTempFilesToFormal(productModel.getId(), productModelDto.getTempFileIds()); } return 1; } else { Product product1 = productMapper.selectById(productModelDto.getProductId()); if(product1 != null){ product1.setProductName(productModelDto.getProductName()); productMapper.updateById(product1); } commonFileService.deleteByBusinessIds(Collections.singletonList(productModelDto.getId()), FileNameType.PRODUCT_MODEL.getValue()); if(CollectionUtils.isNotEmpty(productModelDto.getTempFileIds())){ commonFileService.migrateTempFilesToFormal(productModelDto.getId(), productModelDto.getTempFileIds()); } return productModelMapper.updateById(productModelDto); } } @Override public int delProductModel(Long[] ids) { List salesLedgerProducts = salesLedgerProductMapper.selectList(new QueryWrapper() .lambda().in(SalesLedgerProduct::getProductModelId, ids)); if (salesLedgerProducts != null && salesLedgerProducts.size() > 0) { throw new RuntimeException("已经存在该产品的销售台账和采购台账"); } return productModelMapper.deleteBatchIds(Arrays.asList(ids)); } @Override public List selectModelList(ProductDto productDto) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ProductModel::getProductId, productDto.getId()); return productModelMapper.selectList(queryWrapper); } /** * 根据id查询产品规格分页查询 * @param page * @param productDto * @return */ @Override public IPage modelListPage(Page page, ProductDto productDto) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ProductModel::getProductId, productDto.getId()); return productModelMapper.selectPage(page, queryWrapper); } @Override @Transactional(rollbackFor = Exception.class) public Boolean importProduct(MultipartFile file) { try { ExcelUtil productModelExcelUtil = new ExcelUtil<>(ProductModelExcelCopyDto.class); List productModelList = productModelExcelUtil.importExcel(file.getInputStream()); if(CollectionUtils.isNotEmpty(productModelList)){ // 2. 按产品名称,图纸编号分组 Map, List> groupedByProductNameAndDrawingNumber = productModelList.stream() .collect(Collectors.groupingBy( dto -> new AbstractMap.SimpleEntry<>( dto.getProductName(), dto.getModel() ) )); // 2. 遍历分组结果处理数据 for (Map.Entry, List> entry : groupedByProductNameAndDrawingNumber.entrySet()) { Map.Entry groupKey = entry.getKey(); String productName = groupKey.getKey(); // 产品名称 String drawingNumber = groupKey.getValue(); // 图纸编号 List dtoList = entry.getValue(); // 空列表跳过,避免后续NPE if (CollectionUtils.isEmpty(dtoList)) { continue; } ProductModelExcelCopyDto firstDto = dtoList.get(0); String model = firstDto.getModel(); // 3. 查询/新增产品(按产品名称+图纸编号,更精准) Product product = getOrCreateProduct(productName, drawingNumber); // 4. 批量处理产品型号(按图纸编号+型号) processProductModel(dtoList, product.getId(), model, drawingNumber); } } return true; }catch (Exception e) { e.printStackTrace(); } return false; } /** * 抽取通用方法:查询或新增产品 */ private Product getOrCreateProduct(String productName, String model) { // 精准查询:产品名称+型号(避免同名不同型号的问题) Product product = productMapper.selectOne(new LambdaQueryWrapper() .eq(Product::getProductName, productName) // .eq(Product::getModel, model) .last("limit 1")); if (product == null) { product = new Product(); product.setProductName(productName); // product.setModel(model); // 补充型号,字段更完整 product.setParentId(null); productMapper.insert(product); } return product; } /** * 抽取通用方法:处理产品型号(新增/更新) */ private void processProductModel(List dtoList, Long productId, String model, String drawingNumber) { // 查询所有工艺路线 List productRoutes = productProcessMapper.selectList(new QueryWrapper()); if(CollectionUtils.isEmpty(productRoutes)){ throw new ServiceException("请先创建产品工艺路线"); } for (ProductModelExcelCopyDto dto : dtoList) { // 查询条件:型号+图纸编号(更精准,符合分组逻辑) ProductModel productModel = productModelMapper.selectOne(new LambdaQueryWrapper() .eq(ProductModel::getModel, model) .last("limit 1")); // 通过工艺路线名称匹配最新一条工艺路线 ProductProcess productRoute = productRoutes.stream() .filter(route -> route.getName().equals(dto.getProcessRoute())) .max(Comparator.comparing(ProductProcess::getCreateTime)) .orElse(null); if (productModel == null) { productModel = new ProductModel(); BeanUtils.copyProperties(dto, productModel); if (productRoute != null) { productModel.setRouteId(productRoute.getId()); } // 兜底默认值,避免空值 if (productModel.getProductType() == null) { productModel.setProductType(1); } productModel.setProductId(productId); productModelMapper.insert(productModel); } else { productModel.setRouteId(productRoute != null ? productRoute.getId() : null); BeanUtils.copyProperties(dto, productModel); productModel.setProductId(productId); productModelMapper.updateById(productModel); } } } /** * 递归导入树形产品数据 * @param excelDto Excel解析后的树形节点 * @param parentId 父节点ID(顶级节点传null/0) */ @Transactional(rollbackFor = Exception.class) // 事务保证,失败则回滚 public void recursiveSaveProduct(ProductModelExcelDto excelDto, Long parentId) { // 1. 构建当前节点的Product实体 Product product = new Product(); product.setProductName(excelDto.getProductName()); product.setParentId(parentId); // 父节点ID // 2. 插入当前节点,MyBatis会自动回填product的id属性 productMapper.insert(product); Long currentId = product.getId(); // 获取当前节点主键 // 3. 递归处理子节点 if (excelDto.getChildren() != null && !excelDto.getChildren().isEmpty()) { for (ProductModelExcelDto childDto : excelDto.getChildren()) { recursiveSaveProduct(childDto, currentId); // 父ID为当前节点ID } } // 4. (可选)处理items数据(如果需要插入到关联表) if (excelDto.getItems() != null && !excelDto.getItems().isEmpty()) { for (ProductModelExcelItemDto item : excelDto.getItems()) { // 插入item关联数据,关联currentId // 构建ProductModel实体 ProductModel productModel = new ProductModel(); productModel.setProductId(currentId); // 关联当前产品节点ID productModel.setModel(item.getModel()); // 从ItemDTO获取型号 productModel.setUnit(item.getUnit()); // 从ItemDTO获取单位 productModel.setDrawingNumber(item.getDrawingNumber()); // 图纸编号 productModel.setProductType(item.getProductType()); // 插入product_model表 productModelMapper.insert(productModel); } } } }