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(); } } 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("å¯¼å ¥æå"); } } 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; } 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; } 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(); } } 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; } 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); } 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); 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); } 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; } } 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; } 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è§£æå¤±è´¥", 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.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()); } }