From a8a78a1b733914ea97393ccc5a81bf7ea76ed5aa Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期四, 12 三月 2026 17:58:38 +0800
Subject: [PATCH] Merge branch 'dev_宁夏_中盛建材' of http://114.132.189.42:9002/r/product-inventory-management-after into dev_宁夏_中盛建材

---
 src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java |  271 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 271 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java
new file mode 100644
index 0000000..b319f53
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java
@@ -0,0 +1,271 @@
+package com.ruoyi.production.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+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;
+
+/**
+ * <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 List<ProductMaterialSkuDto> productMaterialSkuList(Long materialId) {
+
+        if (materialId == null) {
+            return Collections.emptyList();
+        }
+
+        LambdaQueryWrapper<ProductMaterialSku> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(ProductMaterialSku::getMaterialId, materialId)
+                .orderByAsc(ProductMaterialSku::getId);
+        List<ProductMaterialSku> skuList = this.list(queryWrapper);
+        if (skuList == null || skuList.isEmpty()) {
+            return Collections.emptyList();
+        }
+        // 鏌ヨ鐗╂枡淇℃伅
+        ProductMaterial material = productMaterialMapper.selectById(materialId);
+
+        String materialName = material != null ? material.getMaterialName() : null;
+        String baseUnit = material != null ? material.getBaseUnit() : null;
+        List<ProductMaterialSkuDto> result = new ArrayList<>(skuList.size());
+        for (ProductMaterialSku sku : skuList) {
+            ProductMaterialSkuDto dto = new ProductMaterialSkuDto();
+            dto.setMaterialId(materialId);
+            dto.setMaterialName(materialName);
+            dto.setBaseUnit(baseUnit);
+            dto.setSkuId(sku.getId());
+            dto.setSpecification(sku.getSpecification());
+            dto.setSupplyType(sku.getSupplyType());
+            result.add(dto);
+        }
+
+        return result;
+    }
+
+    /**
+     * 鏂板鐗╂枡瑙勬牸
+     */
+    @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<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.getMaterialId() == null) {
+            throw new ServiceException("鐗╂枡ID涓嶈兘涓虹┖");
+        }
+        if (StringUtils.isEmpty(sku.getSpecification())) {
+            throw new ServiceException("瑙勬牸涓嶈兘涓虹┖");
+        }
+    }
+
+    /**
+     * 鏍¢獙鏄惁瀛樺湪鐩稿悓瑙勬牸
+     */
+    private boolean existsSameSpecification(Long materialId, String specification, Long excludeId) {
+        LambdaQueryWrapper<ProductMaterialSku> 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<ProductMaterialSkuImportDto> excelUtil = new ExcelUtil<>(ProductMaterialSkuImportDto.class);
+        List<ProductMaterialSkuImportDto> importList;
+        try {
+            importList = excelUtil.importExcel(file.getInputStream());
+        } catch (Exception e) {
+            log.error("瀵煎叆鐗╂枡瑙勬牸Excel瑙f瀽澶辫触", e);
+            throw new ServiceException("Excel瑙f瀽澶辫触");
+        }
+
+        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.getSpecification())) {
+                continue;
+            }
+            String specification = dto.getSpecification().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::getMaterialId, materialId)
+                .in(ProductMaterialSku::getSpecification, specifications));
+        Map<String, ProductMaterialSku> existMap = existList.stream()
+                .collect(Collectors.toMap(ProductMaterialSku::getSpecification, 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.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());
+    }
+}

--
Gitblit v1.9.3