From 52e93e45d7c989483693f53ded1b4483891fb055 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 12 三月 2026 14:44:28 +0800
Subject: [PATCH] feat: 物料类型与存货类别的新增、删除和修改,物料规格的导入数据

---
 src/main/java/com/ruoyi/production/service/ProductMaterialService.java                |    4 
 src/main/java/com/ruoyi/production/service/impl/ProductMaterialServiceImpl.java       |   18 +-
 src/main/java/com/ruoyi/production/dto/ProductMaterialGroupDto.java                   |   30 +++
 src/main/java/com/ruoyi/production/pojo/ProductMaterialSkuImportDto.java              |   35 ++++
 src/main/java/com/ruoyi/production/controller/ProductMaterialController.java          |   56 +++++-
 src/main/java/com/ruoyi/production/service/impl/ProductMaterialConfigServiceImpl.java |   96 ++++++++++++
 src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java    |  105 +++++++++++++
 src/main/java/com/ruoyi/production/service/ProductMaterialSkuService.java             |    3 
 src/main/java/com/ruoyi/production/enums/MaterialConfigTypeEnum.java                  |   45 +++++
 src/main/java/com/ruoyi/production/service/ProductMaterialConfigService.java          |   12 +
 src/main/java/com/ruoyi/production/controller/ProductMaterialSkuController.java       |   32 +++-
 src/main/java/com/ruoyi/production/dto/ProductMaterialConfigDto.java                  |   24 +++
 12 files changed, 429 insertions(+), 31 deletions(-)

diff --git a/src/main/java/com/ruoyi/production/controller/ProductMaterialController.java b/src/main/java/com/ruoyi/production/controller/ProductMaterialController.java
index e95379f..184499e 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductMaterialController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductMaterialController.java
@@ -3,20 +3,17 @@
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.production.dto.ProductMaterialConfigDto;
+import com.ruoyi.production.dto.ProductMaterialGroupDto;
 import com.ruoyi.production.pojo.ProductMaterial;
+import com.ruoyi.production.pojo.ProductMaterialConfig;
+import com.ruoyi.production.service.ProductMaterialConfigService;
 import com.ruoyi.production.service.ProductMaterialService;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * <br>
@@ -34,6 +31,9 @@
     @Autowired
     private ProductMaterialService productMaterialService;
 
+    @Autowired
+    private ProductMaterialConfigService productMaterialConfigService;
+
     @GetMapping("/loadData")
     @ApiOperation("鎷夊彇鐗╂枡缂栫爜鏁版嵁")
     @Log(title = "鎷夊彇鐗╂枡缂栫爜鏁版嵁", businessType = BusinessType.INSERT)
@@ -46,7 +46,7 @@
     @ApiOperation("鐗╂枡鏁版嵁")
     @Log(title = "鐗╂枡鏁版嵁", businessType = BusinessType.OTHER)
     public AjaxResult productMaterialList(String materialName) {
-        Map<String, List<ProductMaterial>> productMaterialMap = productMaterialService.ProductMaterialList(materialName);
+        List<ProductMaterialGroupDto> productMaterialMap = productMaterialService.ProductMaterialList(materialName);
         return AjaxResult.success(productMaterialMap);
     }
 
@@ -75,5 +75,43 @@
     }
 
 
+    @GetMapping("/materialTypeList")
+    @ApiOperation("鐗╂枡绫诲瀷鏁版嵁闆嗗悎")
+    @Log(title = "鐗╂枡绫诲瀷鏁版嵁闆嗗悎", businessType = BusinessType.OTHER)
+    public AjaxResult materialTypeList() {
+        List<ProductMaterialConfig> list = productMaterialConfigService.materialTypeList();
+        return AjaxResult.success(list);
+    }
 
+    @GetMapping("/inventoryCategoryList")
+    @ApiOperation("'瀛樿揣绫诲埆鏁版嵁闆嗗悎")
+    @Log(title = "'瀛樿揣绫诲埆鏁版嵁闆嗗悎", businessType = BusinessType.OTHER)
+    public AjaxResult inventoryCategoryList() {
+        List<ProductMaterialConfig> list = productMaterialConfigService.inventoryCategoryList();
+        return AjaxResult.success(list);
+    }
+
+    @PostMapping("/config/add")
+    @ApiOperation("鏂板鐗╂枡閰嶇疆")
+    @Log(title = "鏂板鐗╂枡閰嶇疆", businessType = BusinessType.INSERT)
+    public AjaxResult addProductMaterialConfig(@RequestBody ProductMaterialConfigDto config) {
+        productMaterialConfigService.addProductMaterialConfig(config);
+        return AjaxResult.success();
+    }
+
+    @PutMapping("/config/update")
+    @ApiOperation("淇敼鐗╂枡閰嶇疆")
+    @Log(title = "淇敼鐗╂枡閰嶇疆", businessType = BusinessType.UPDATE)
+    public AjaxResult updateProductMaterialConfig(@RequestBody ProductMaterialConfigDto config) {
+        productMaterialConfigService.updateProductMaterialConfig(config);
+        return AjaxResult.success();
+    }
+
+    @DeleteMapping("/config/delete")
+    @ApiOperation("鍒犻櫎鐗╂枡閰嶇疆")
+    @Log(title = "鍒犻櫎鐗╂枡閰嶇疆", businessType = BusinessType.DELETE)
+    public AjaxResult deleteProductMaterialConfig(@RequestBody List<Integer> ids) {
+        productMaterialConfigService.deleteProductMaterialConfig(ids);
+        return AjaxResult.success();
+    }
 }
diff --git a/src/main/java/com/ruoyi/production/controller/ProductMaterialSkuController.java b/src/main/java/com/ruoyi/production/controller/ProductMaterialSkuController.java
index f9145d1..5d6c8ba 100644
--- a/src/main/java/com/ruoyi/production/controller/ProductMaterialSkuController.java
+++ b/src/main/java/com/ruoyi/production/controller/ProductMaterialSkuController.java
@@ -1,22 +1,20 @@
 package com.ruoyi.production.controller;
 
+import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.aspectj.lang.annotation.Log;
 import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
 import com.ruoyi.framework.web.domain.AjaxResult;
 import com.ruoyi.production.dto.ProductMaterialSkuDto;
 import com.ruoyi.production.pojo.ProductMaterialSku;
+import com.ruoyi.production.pojo.ProductMaterialSkuImportDto;
 import com.ruoyi.production.service.ProductMaterialSkuService;
+import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 
 /**
@@ -30,6 +28,7 @@
  */
 @RestController
 @RequestMapping("/productMaterialSku")
+@Api(tags = "鐗╂枡瑙勬牸绠$悊鎺ュ彛")
 public class ProductMaterialSkuController {
 
     @Autowired
@@ -66,4 +65,21 @@
         productMaterialSkuService.deleteProductMaterialSku(ids);
         return AjaxResult.success();
     }
+
+    @PostMapping("/downloadTemplate")
+    @Log(title = "涓嬭浇鐗╂枡瑙勬牸瀵煎叆妯℃澘", businessType = BusinessType.EXPORT)
+    @ApiOperation("涓嬭浇鐗╂枡瑙勬牸瀵煎叆妯℃澘")
+    public void importTemplate(HttpServletResponse response) {
+        ExcelUtil<ProductMaterialSkuImportDto> excelUtil = new ExcelUtil<>(ProductMaterialSkuImportDto.class);
+        excelUtil.importTemplateExcel(response, "涓嬭浇鐗╂枡瑙勬牸瀵煎叆妯℃澘");
+    }
+
+    @PostMapping("/import")
+    @ApiOperation("鐗╂枡瑙勬牸鏁版嵁瀵煎叆")
+    @Log(title = "鐗╂枡瑙勬牸鏁版嵁瀵煎叆", businessType = BusinessType.IMPORT)
+    public AjaxResult importProdData(@RequestParam("file") MultipartFile file, @RequestParam("materialId") Long materialId) {
+        productMaterialSkuService.importProdData(file, materialId);
+        return AjaxResult.success("瀵煎叆鎴愬姛");
+    }
+
 }
diff --git a/src/main/java/com/ruoyi/production/dto/ProductMaterialConfigDto.java b/src/main/java/com/ruoyi/production/dto/ProductMaterialConfigDto.java
new file mode 100644
index 0000000..947997e
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/dto/ProductMaterialConfigDto.java
@@ -0,0 +1,24 @@
+package com.ruoyi.production.dto;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ruoyi.production.pojo.ProductMaterialConfig;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * <br>
+ * 鐗╂枡淇℃伅琛ㄩ厤缃〃Dto
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/12 14:07
+ */
+@Data
+public class ProductMaterialConfigDto extends ProductMaterialConfig {
+
+    @ApiModelProperty("閰嶇疆绫诲瀷")
+    @TableField(exist = false)
+    private Integer type;
+
+}
diff --git a/src/main/java/com/ruoyi/production/dto/ProductMaterialGroupDto.java b/src/main/java/com/ruoyi/production/dto/ProductMaterialGroupDto.java
new file mode 100644
index 0000000..8f2e98f
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/dto/ProductMaterialGroupDto.java
@@ -0,0 +1,30 @@
+package com.ruoyi.production.dto;
+
+import com.ruoyi.production.pojo.ProductMaterial;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * <br>
+ * 鐗╂枡閰嶇疆鍒嗙粍 DTO
+ * </br>
+ *
+ * @author deslrey
+ * @since 2026/03/12 13:43
+ */
+@Data
+@ApiModel(value = "ProductMaterialGroupDto", description = "鐗╂枡閰嶇疆鍒嗙粍鏁版嵁")
+public class ProductMaterialGroupDto {
+
+    @ApiModelProperty("閰嶇疆ID")
+    private Integer configId;
+
+    @ApiModelProperty("閰嶇疆鍚嶇О")
+    private String configName;
+
+    @ApiModelProperty("鐗╂枡鍒楄〃")
+    private List<ProductMaterial> materialList;
+}
diff --git a/src/main/java/com/ruoyi/production/enums/MaterialConfigTypeEnum.java b/src/main/java/com/ruoyi/production/enums/MaterialConfigTypeEnum.java
index 7b8f0d9..bed2e86 100644
--- a/src/main/java/com/ruoyi/production/enums/MaterialConfigTypeEnum.java
+++ b/src/main/java/com/ruoyi/production/enums/MaterialConfigTypeEnum.java
@@ -13,13 +13,50 @@
 
     /**
      * 鐗╂枡绫诲瀷
-     * 瀵瑰簲鏁版嵁搴� config_type = MATERIAL_TYPE
      */
-    MATERIAL_TYPE,
+    MATERIAL_TYPE(1, "鐗╂枡绫诲瀷"),
 
     /**
      * 瀛樿揣绫诲埆
-     * 瀵瑰簲鏁版嵁搴� config_type = INVENTORY_CAT
      */
-    INVENTORY_CAT
+    INVENTORY_CAT(2, "瀛樿揣绫诲埆");
+
+    private final Integer type;
+    private final String desc;
+
+    MaterialConfigTypeEnum(Integer type, String desc) {
+        this.type = type;
+        this.desc = desc;
+    }
+
+    public Integer getType() {
+        return type;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    /**
+     * 鏍规嵁 type 鑾峰彇鏋氫妇
+     */
+    public static MaterialConfigTypeEnum getByType(Integer type) {
+        for (MaterialConfigTypeEnum value : values()) {
+            if (value.type.equals(type)) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 鏍规嵁 type 鑾峰彇鏁版嵁搴撳瓨鍌ㄥ��
+     */
+    public static String getConfigType(Integer type) {
+        MaterialConfigTypeEnum e = getByType(type);
+        if (e == null) {
+            throw new IllegalArgumentException("閰嶇疆绫诲瀷閿欒");
+        }
+        return e.name();
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/production/pojo/ProductMaterialSkuImportDto.java b/src/main/java/com/ruoyi/production/pojo/ProductMaterialSkuImportDto.java
new file mode 100644
index 0000000..06ed8b8
--- /dev/null
+++ b/src/main/java/com/ruoyi/production/pojo/ProductMaterialSkuImportDto.java
@@ -0,0 +1,35 @@
+package com.ruoyi.production.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.framework.aspectj.lang.annotation.Excel;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * <br>
+ * 鐗╂枡瑙勬牸瀵煎叆
+ * </br>
+ *
+ * @author deslrey
+ * @version 1.0
+ * @since 2026/03/12 13:08
+ */
+@Data
+@ApiModel(value = "ProductMaterialSkuImportDto", description = "鐗╂枡瑙勬牸琛ㄥ鍏�")
+public class ProductMaterialSkuImportDto {
+
+    @ApiModelProperty("瑙勬牸鍨嬪彿")
+    @Excel(name = "瑙勬牸鍨嬪彿")
+    private String specification;
+
+    @ApiModelProperty("渚涘簲鏂瑰紡锛堣嚜鍒讹紝澶栬喘锛�")
+    @Excel(name = "渚涘簲鏂瑰紡")
+    private String supplyType;
+
+
+}
diff --git a/src/main/java/com/ruoyi/production/service/ProductMaterialConfigService.java b/src/main/java/com/ruoyi/production/service/ProductMaterialConfigService.java
index e31fcf5..342af3e 100644
--- a/src/main/java/com/ruoyi/production/service/ProductMaterialConfigService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductMaterialConfigService.java
@@ -1,7 +1,10 @@
 package com.ruoyi.production.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.dto.ProductMaterialConfigDto;
 import com.ruoyi.production.pojo.ProductMaterialConfig;
+
+import java.util.List;
 
 /**
  * <br>
@@ -13,4 +16,13 @@
  * @since 2026/03/11 16:58
  */
 public interface ProductMaterialConfigService extends IService<ProductMaterialConfig> {
+    List<ProductMaterialConfig> materialTypeList();
+
+    List<ProductMaterialConfig> inventoryCategoryList();
+
+    void addProductMaterialConfig(ProductMaterialConfigDto config);
+
+    void updateProductMaterialConfig(ProductMaterialConfigDto config);
+
+    void deleteProductMaterialConfig(List<Integer> ids);
 }
diff --git a/src/main/java/com/ruoyi/production/service/ProductMaterialService.java b/src/main/java/com/ruoyi/production/service/ProductMaterialService.java
index 4d24475..9dfc867 100644
--- a/src/main/java/com/ruoyi/production/service/ProductMaterialService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductMaterialService.java
@@ -1,10 +1,10 @@
 package com.ruoyi.production.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.production.dto.ProductMaterialGroupDto;
 import com.ruoyi.production.pojo.ProductMaterial;
 
 import java.util.List;
-import java.util.Map;
 
 /**
  * <br>
@@ -21,7 +21,7 @@
 
     void syncProductMaterialJob();
 
-    Map<String, List<ProductMaterial>> ProductMaterialList(String materialName);
+    List<ProductMaterialGroupDto> ProductMaterialList(String materialName);
 
     void addProductMaterial(ProductMaterial productMaterial);
 
diff --git a/src/main/java/com/ruoyi/production/service/ProductMaterialSkuService.java b/src/main/java/com/ruoyi/production/service/ProductMaterialSkuService.java
index b24a444..1665678 100644
--- a/src/main/java/com/ruoyi/production/service/ProductMaterialSkuService.java
+++ b/src/main/java/com/ruoyi/production/service/ProductMaterialSkuService.java
@@ -3,6 +3,7 @@
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ruoyi.production.dto.ProductMaterialSkuDto;
 import com.ruoyi.production.pojo.ProductMaterialSku;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -23,4 +24,6 @@
     void updateProductMaterialSku(ProductMaterialSku productMaterialSku);
 
     void deleteProductMaterialSku(List<Long> ids);
+
+    void importProdData(MultipartFile file, Long materialId);
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductMaterialConfigServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductMaterialConfigServiceImpl.java
index 7136f8a..f61f0dc 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductMaterialConfigServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductMaterialConfigServiceImpl.java
@@ -1,11 +1,19 @@
 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.production.dto.ProductMaterialConfigDto;
+import com.ruoyi.production.enums.MaterialConfigTypeEnum;
 import com.ruoyi.production.mapper.ProductMaterialConfigMapper;
 import com.ruoyi.production.pojo.ProductMaterialConfig;
 import com.ruoyi.production.service.ProductMaterialConfigService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
 
 /**
  * <br>
@@ -20,5 +28,93 @@
 @Service
 public class ProductMaterialConfigServiceImpl extends ServiceImpl<ProductMaterialConfigMapper, ProductMaterialConfig> implements ProductMaterialConfigService {
 
+    @Override
+    public List<ProductMaterialConfig> materialTypeList() {
+        return getByType(MaterialConfigTypeEnum.MATERIAL_TYPE);
+    }
 
+    @Override
+    public List<ProductMaterialConfig> inventoryCategoryList() {
+        return getByType(MaterialConfigTypeEnum.INVENTORY_CAT);
+    }
+
+    private List<ProductMaterialConfig> getByType(MaterialConfigTypeEnum type) {
+        return list(new LambdaQueryWrapper<ProductMaterialConfig>().eq(ProductMaterialConfig::getConfigType, type.name()));
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void addProductMaterialConfig(ProductMaterialConfigDto config) {
+        config.setConfigType(MaterialConfigTypeEnum.getConfigType(config.getType()));
+        validateConfig(config, false);
+        if (existsConfig(config.getConfigType(), config.getConfigName(), null)) {
+            throw new ServiceException("閰嶇疆鍚嶇О宸插瓨鍦�");
+        }
+        if (!this.save(config)) {
+            throw new ServiceException("鏂板閰嶇疆澶辫触");
+        }
+        log.info("鏂板鐗╂枡閰嶇疆鎴愬姛 type={}, name={}", config.getConfigType(), config.getConfigName());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void updateProductMaterialConfig(ProductMaterialConfigDto config) {
+        config.setConfigType(MaterialConfigTypeEnum.getConfigType(config.getType()));
+        validateConfig(config, true);
+        ProductMaterialConfig exist = this.getById(config.getId());
+        if (exist == null) {
+            throw new ServiceException("閰嶇疆涓嶅瓨鍦�");
+        }
+        if (existsConfig(config.getConfigType(), config.getConfigName(), config.getId())) {
+            throw new ServiceException("閰嶇疆鍚嶇О宸插瓨鍦�");
+        }
+        if (!this.updateById(config)) {
+            throw new ServiceException("淇敼閰嶇疆澶辫触");
+        }
+        log.info("淇敼鐗╂枡閰嶇疆鎴愬姛 id={}", config.getId());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteProductMaterialConfig(List<Integer> ids) {
+        if (ids == null || ids.isEmpty()) {
+            throw new ServiceException("璇烽�夋嫨鑷冲皯涓�鏉℃暟鎹�");
+        }
+        if (!this.removeByIds(ids)) {
+            throw new ServiceException("鍒犻櫎閰嶇疆澶辫触");
+        }
+        log.info("鍒犻櫎鐗╂枡閰嶇疆鎴愬姛 ids={}", ids);
+    }
+
+    private void validateConfig(ProductMaterialConfig config, boolean requireId) {
+        if (config == null) {
+            throw new ServiceException("鍙傛暟涓嶈兘涓虹┖");
+        }
+        if (requireId && config.getId() == null) {
+            throw new ServiceException("涓婚敭ID涓嶈兘涓虹┖");
+        }
+        if (StringUtils.isEmpty(config.getConfigType())) {
+            throw new ServiceException("閰嶇疆绫诲瀷涓嶈兘涓虹┖");
+        }
+        try {
+            MaterialConfigTypeEnum.valueOf(config.getConfigType());
+        } catch (IllegalArgumentException e) {
+            throw new ServiceException("閰嶇疆绫诲瀷涓嶅悎娉�");
+        }
+        if (StringUtils.isEmpty(config.getConfigName())) {
+            throw new ServiceException("閰嶇疆鍚嶇О涓嶈兘涓虹┖");
+        }
+    }
+
+    private boolean existsConfig(String configType, String configName, Integer excludeId) {
+        if (StringUtils.isEmpty(configName) || StringUtils.isEmpty(configType)) {
+            return false;
+        }
+        LambdaQueryWrapper<ProductMaterialConfig> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(ProductMaterialConfig::getConfigType, configType).eq(ProductMaterialConfig::getConfigName, configName);
+        if (excludeId != null) {
+            wrapper.ne(ProductMaterialConfig::getId, excludeId);
+        }
+        return this.count(wrapper) > 0;
+    }
 }
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductMaterialServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductMaterialServiceImpl.java
index b1dd5b4..76a52d3 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductMaterialServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductMaterialServiceImpl.java
@@ -9,6 +9,7 @@
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.http.HttpUtils;
 import com.ruoyi.framework.config.AliDingConfig;
+import com.ruoyi.production.dto.ProductMaterialGroupDto;
 import com.ruoyi.production.enums.MaterialConfigTypeEnum;
 import com.ruoyi.production.mapper.ProductMaterialMapper;
 import com.ruoyi.production.pojo.ProductMaterial;
@@ -337,13 +338,12 @@
     }
 
     @Override
-    public Map<String, List<ProductMaterial>> ProductMaterialList(String materialName) {
+    public List<ProductMaterialGroupDto> ProductMaterialList(String materialName) {
 
-        List<ProductMaterialConfig> materialConfigList =
-                productMaterialConfigService.list(new LambdaQueryWrapper<ProductMaterialConfig>()
-                        .eq(ProductMaterialConfig::getConfigType, MaterialConfigTypeEnum.MATERIAL_TYPE.name()));
+        List<ProductMaterialConfig> materialConfigList = productMaterialConfigService.list(new LambdaQueryWrapper<ProductMaterialConfig>()
+                .eq(ProductMaterialConfig::getConfigType, MaterialConfigTypeEnum.MATERIAL_TYPE.name()));
 
-        Map<String, List<ProductMaterial>> productMaterialMap = new HashMap<>();
+        List<ProductMaterialGroupDto> productMaterialMap = new ArrayList<>();
         if (materialConfigList == null || materialConfigList.isEmpty()) {
             return productMaterialMap;
         }
@@ -352,14 +352,16 @@
             wrapper.eq(ProductMaterial::getMaterialTypeId, materialConfig.getId())
                     .select(ProductMaterial::getId, ProductMaterial::getMaterialName)
                     .like(materialName != null && !materialName.isEmpty(), ProductMaterial::getMaterialName, materialName);
-
             List<ProductMaterial> productMaterialList = list(wrapper);
 
             if (productMaterialList != null && !productMaterialList.isEmpty()) {
-                productMaterialMap.put(materialConfig.getConfigName(), productMaterialList);
+                ProductMaterialGroupDto dto = new ProductMaterialGroupDto();
+                dto.setConfigId(materialConfig.getId());
+                dto.setConfigName(materialConfig.getConfigName());
+                dto.setMaterialList(productMaterialList);
+                productMaterialMap.add(dto);
             }
         }
-
         return productMaterialMap;
     }
 
diff --git a/src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java b/src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java
index 289b3ad..b319f53 100644
--- a/src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java
+++ b/src/main/java/com/ruoyi/production/service/impl/ProductMaterialSkuServiceImpl.java
@@ -4,20 +4,28 @@
 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>
@@ -163,4 +171,101 @@
 
         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