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.dto.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.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Set;
|
import java.util.stream.Collectors;
|
|
/**
|
* <br>
|
* 物料规格接口实现类
|
* </br>
|
*
|
* @author deslrey
|
* @version 1.0
|
* @since 2026/03/12 10:05
|
*/
|
@Slf4j
|
@Service
|
public class ProductMaterialSkuServiceImpl extends ServiceImpl<ProductMaterialSkuMapper, ProductMaterialSku> implements ProductMaterialSkuService {
|
|
@Autowired
|
private ProductMaterialMapper productMaterialMapper;
|
|
/**
|
* 查询物料规格列表
|
*/
|
@Override
|
public Page<ProductMaterialSkuDto> productMaterialSkuList(Page<ProductMaterialSkuDto> page, ProductMaterialSkuDto dto, Integer type) {
|
return baseMapper.selectSkuWithMaterialPage(page, dto, type);
|
}
|
|
/**
|
* 新增物料规格
|
*/
|
@Override
|
public void addProductMaterialSku(ProductMaterialSku sku) {
|
validateProductMaterialSku(sku, false);
|
// 校验物料是否存在
|
ProductMaterial material = productMaterialMapper.selectById(sku.getProductId());
|
if (material == null) {
|
throw new ServiceException("物料不存在");
|
}
|
// 校验规格是否重复
|
if (existsSameSpecification(sku.getProductId(), sku.getModel(), 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.getProductId(), sku.getModel());
|
}
|
|
/**
|
* 修改物料规格
|
*/
|
@Override
|
public void updateProductMaterialSku(ProductMaterialSku sku) {
|
validateProductMaterialSku(sku, true);
|
// 校验规格是否重复
|
if (existsSameSpecification(sku.getProductId(), sku.getModel(), 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<Long> 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.getProductId() == null) {
|
throw new ServiceException("物料ID不能为空");
|
}
|
if (StringUtils.isEmpty(sku.getModel())) {
|
throw new ServiceException("规格不能为空");
|
}
|
}
|
|
/**
|
* 校验是否存在相同规格
|
*/
|
private boolean existsSameSpecification(Long materialId, String specification, Long excludeId) {
|
LambdaQueryWrapper<ProductMaterialSku> queryWrapper = new LambdaQueryWrapper<>();
|
queryWrapper.eq(ProductMaterialSku::getProductId, materialId)
|
.eq(ProductMaterialSku::getModel, 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<ProductMaterialSkuImportDto> excelUtil = new ExcelUtil<>(ProductMaterialSkuImportDto.class);
|
List<ProductMaterialSkuImportDto> 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<String, ProductMaterialSkuImportDto> specMap = new LinkedHashMap<>();
|
for (ProductMaterialSkuImportDto dto : importList) {
|
if (dto == null || StringUtils.isEmpty(dto.getModel())) {
|
continue;
|
}
|
String specification = dto.getModel().trim();
|
if (specification.isEmpty()) {
|
continue;
|
}
|
specMap.putIfAbsent(specification, dto);
|
}
|
|
if (specMap.isEmpty()) {
|
throw new ServiceException("Excel没有有效的规格数据");
|
}
|
|
Set<String> specifications = specMap.keySet();
|
|
List<ProductMaterialSku> existList = this.list(new LambdaQueryWrapper<ProductMaterialSku>()
|
.eq(ProductMaterialSku::getProductId, materialId)
|
.in(ProductMaterialSku::getModel, specifications));
|
Map<String, ProductMaterialSku> existMap = existList.stream()
|
.collect(Collectors.toMap(ProductMaterialSku::getModel, sku -> sku, (a, b) -> a));
|
|
LocalDateTime now = LocalDateTime.now();
|
List<ProductMaterialSku> saveList = new ArrayList<>();
|
List<ProductMaterialSku> updateList = new ArrayList<>();
|
|
for (Map.Entry<String, ProductMaterialSkuImportDto> 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.setProductId(materialId);
|
sku.setModel(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());
|
}
|
}
|