package com.ruoyi.production.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 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.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.production.dto.ProductMaterialSkuDto; import com.ruoyi.production.mapper.ProductMaterialMapper; import com.ruoyi.production.mapper.ProductMaterialSkuMapper; import com.ruoyi.production.pojo.ProductMaterial; import com.ruoyi.production.pojo.ProductMaterialSku; import com.ruoyi.production.pojo.ProductMaterialSkuImportDto; import com.ruoyi.production.service.ProductMaterialSkuService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; /** *
* 物料规格接口实现类 *
* * @author deslrey * @version 1.0 * @since 2026/03/12 10:05 */ @Slf4j @Service public class ProductMaterialSkuServiceImpl extends ServiceImpl implements ProductMaterialSkuService { @Autowired private ProductMaterialMapper productMaterialMapper; /** * 查询物料规格列表 */ @Override public Page productMaterialSkuList(Page page, ProductMaterialSkuDto dto) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); if (dto != null && dto.getMaterialId() != null) { queryWrapper.eq(ProductMaterialSku::getMaterialId, dto.getMaterialId()) .like(StringUtils.isNotBlank(dto.getSpecification()), ProductMaterialSku::getSpecification, dto.getSpecification()) .like(StringUtils.isNotBlank(dto.getMaterialCode()), ProductMaterialSku::getMaterialCode, dto.getMaterialCode()) .orderByAsc(ProductMaterialSku::getId); } Page skuPage = this.page(page, queryWrapper); List skuList = skuPage.getRecords(); if (skuList == null || skuList.isEmpty()) { return new Page<>(); } ProductMaterial material = productMaterialMapper.selectById(dto.getMaterialId()); String materialName = material != null ? material.getMaterialName() : null; String baseUnit = material != null ? material.getBaseUnit() : null; List result = new ArrayList<>(skuList.size()); for (ProductMaterialSku sku : skuList) { ProductMaterialSkuDto productMaterialSkuDto = new ProductMaterialSkuDto(); productMaterialSkuDto.setMaterialId(dto.getMaterialId()); productMaterialSkuDto.setMaterialName(materialName); productMaterialSkuDto.setMaterialCode(sku.getMaterialCode()); productMaterialSkuDto.setBaseUnit(baseUnit); productMaterialSkuDto.setSkuId(sku.getId()); productMaterialSkuDto.setSpecification(sku.getSpecification()); productMaterialSkuDto.setSupplyType(sku.getSupplyType()); result.add(productMaterialSkuDto); } Page dtoPage = new Page<>(); dtoPage.setCurrent(skuPage.getCurrent()); dtoPage.setSize(skuPage.getSize()); dtoPage.setTotal(skuPage.getTotal()); dtoPage.setRecords(result); return dtoPage; } /** * 新增物料规格 */ @Override public void addProductMaterialSku(ProductMaterialSku sku) { validateProductMaterialSku(sku, false); // 校验物料是否存在 ProductMaterial material = productMaterialMapper.selectById(sku.getMaterialId()); if (material == null) { throw new ServiceException("物料不存在"); } // 校验规格是否重复 if (existsSameSpecification(sku.getMaterialId(), sku.getSpecification(), null)) { throw new ServiceException("该物料已存在相同规格"); } LocalDateTime now = LocalDateTime.now(); if (sku.getCreateTime() == null) { sku.setCreateTime(now); } sku.setUpdateTime(now); if (!this.save(sku)) { throw new ServiceException("新增物料规格失败"); } log.info("新增物料规格成功 materialId={}, specification={}", sku.getMaterialId(), sku.getSpecification()); } /** * 修改物料规格 */ @Override public void updateProductMaterialSku(ProductMaterialSku sku) { validateProductMaterialSku(sku, true); // 校验规格是否重复 if (existsSameSpecification(sku.getMaterialId(), sku.getSpecification(), sku.getId())) { throw new ServiceException("该物料已存在相同规格"); } sku.setUpdateTime(LocalDateTime.now()); if (!this.updateById(sku)) { throw new ServiceException("修改物料规格失败"); } log.info("修改物料规格成功 id={}", sku.getId()); } /** * 删除物料规格 */ @Override public void deleteProductMaterialSku(List ids) { if (ids == null || ids.isEmpty()) { throw new ServiceException("请选择至少一条数据"); } if (!this.removeByIds(ids)) { throw new ServiceException("删除物料规格失败"); } log.info("删除物料规格成功 ids={}", ids); } /** * 参数校验 */ private void validateProductMaterialSku(ProductMaterialSku sku, boolean requireId) { if (sku == null) { throw new ServiceException("参数不能为空"); } if (requireId && sku.getId() == null) { throw new ServiceException("主键ID不能为空"); } if (sku.getMaterialId() == null) { throw new ServiceException("物料ID不能为空"); } if (StringUtils.isEmpty(sku.getSpecification())) { throw new ServiceException("规格不能为空"); } } /** * 校验是否存在相同规格 */ private boolean existsSameSpecification(Long materialId, String specification, Long excludeId) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(ProductMaterialSku::getMaterialId, materialId) .eq(ProductMaterialSku::getSpecification, specification); if (excludeId != null) { queryWrapper.ne(ProductMaterialSku::getId, excludeId); } return this.count(queryWrapper) > 0; } @Override @Transactional(rollbackFor = Exception.class) public void importProdData(MultipartFile file, Long materialId) { if (materialId == null) { throw new ServiceException("物料ID不能为空"); } if (file == null || file.isEmpty()) { throw new ServiceException("导入文件不能为空"); } ProductMaterial material = productMaterialMapper.selectById(materialId); if (material == null) { throw new ServiceException("物料不存在"); } ExcelUtil excelUtil = new ExcelUtil<>(ProductMaterialSkuImportDto.class); List importList; try { importList = excelUtil.importExcel(file.getInputStream()); } catch (Exception e) { log.error("导入物料规格Excel解析失败", e); throw new ServiceException("Excel解析失败"); } if (importList == null || importList.isEmpty()) { throw new ServiceException("Excel没有数据"); } Map specMap = new LinkedHashMap<>(); for (ProductMaterialSkuImportDto dto : importList) { if (dto == null || StringUtils.isEmpty(dto.getSpecification())) { continue; } String specification = dto.getSpecification().trim(); if (specification.isEmpty()) { continue; } specMap.putIfAbsent(specification, dto); } if (specMap.isEmpty()) { throw new ServiceException("Excel没有有效的规格数据"); } Set specifications = specMap.keySet(); List existList = this.list(new LambdaQueryWrapper() .eq(ProductMaterialSku::getMaterialId, materialId) .in(ProductMaterialSku::getSpecification, specifications)); Map existMap = existList.stream() .collect(Collectors.toMap(ProductMaterialSku::getSpecification, sku -> sku, (a, b) -> a)); LocalDateTime now = LocalDateTime.now(); List saveList = new ArrayList<>(); List updateList = new ArrayList<>(); for (Map.Entry entry : specMap.entrySet()) { String specification = entry.getKey(); ProductMaterialSkuImportDto dto = entry.getValue(); String supplyType = StringUtils.isNotEmpty(dto.getSupplyType()) ? dto.getSupplyType().trim() : null; ProductMaterialSku exist = existMap.get(specification); if (exist == null) { ProductMaterialSku sku = new ProductMaterialSku(); sku.setMaterialId(materialId); sku.setSpecification(specification); sku.setSupplyType(supplyType); sku.setCreateTime(now); sku.setUpdateTime(now); saveList.add(sku); } else { boolean needUpdate = false; if (supplyType != null && !supplyType.equals(exist.getSupplyType())) { exist.setSupplyType(supplyType); needUpdate = true; } if (needUpdate) { exist.setUpdateTime(now); updateList.add(exist); } } } if (saveList.isEmpty() && updateList.isEmpty()) { throw new ServiceException("Excel与现有数据一致,无需导入"); } if (!saveList.isEmpty()) { this.saveBatch(saveList); } if (!updateList.isEmpty()) { this.updateBatchById(updateList); } log.info("物料规格导入完成 materialId={}, 新增{}条,更新{}条", materialId, saveList.size(), updateList.size()); } }