From c2aa950ad02fb063deeb1903d8f26f2898678329 Mon Sep 17 00:00:00 2001 From: shusir <497819738@qq.com> Date: Thu, 12 Mar 2026 18:06:14 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E7=89=A9=E6=96=99=E6=89=B9=E6=AC=A1?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E6=A8=A1=E6=9D=BF=E5=8F=8A=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../supplier/service/SupplierService.java | 7 ++ .../supplier/service/SupplierServiceImpl.java | 8 +++ .../admin/MaterialBatchController.java | 56 ++++++++++++++++ .../importer/MaterialBatchImportExcelVO.java | 50 ++++++++++++++ .../vo/resp/MaterialBatchImportRespVO.java | 24 +++++++ .../service/MaterialBatchService.java | 10 +++ .../service/MaterialBatchServiceImpl.java | 65 +++++++++++++++++-- .../service/MaterialProductService.java | 8 +++ .../service/MaterialProductServiceImpl.java | 7 ++ 9 files changed, 231 insertions(+), 4 deletions(-) create mode 100644 zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/importer/MaterialBatchImportExcelVO.java create mode 100644 zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/resp/MaterialBatchImportRespVO.java diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/office/supplier/service/SupplierService.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/office/supplier/service/SupplierService.java index b9592f0e..d6090c95 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/office/supplier/service/SupplierService.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/office/supplier/service/SupplierService.java @@ -62,4 +62,11 @@ public interface SupplierService { */ PageResult getSupplierPage(SupplierPageReqVO pageReqVO); + /** + * 获得供应商列表 + * + * @param supplierNames 供应商名称数组 + * @return 供应商列表 + */ + List getSuppliersByNames(List supplierNames); } \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/office/supplier/service/SupplierServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/office/supplier/service/SupplierServiceImpl.java index f188ef79..1168fd7a 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/office/supplier/service/SupplierServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/office/supplier/service/SupplierServiceImpl.java @@ -1,6 +1,7 @@ package com.zt.plat.module.qms.office.supplier.service; import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.zt.plat.module.qms.office.supplier.controller.vo.SupplierExtendRespVO; import com.zt.plat.module.qms.office.supplier.controller.vo.SupplierPageReqVO; import com.zt.plat.module.qms.office.supplier.controller.vo.SupplierRespVO; @@ -90,4 +91,11 @@ public class SupplierServiceImpl implements SupplierService { return supplierMapper.selectPage(pageReqVO); } + @Override + public List getSuppliersByNames(List supplierNames) { + + return supplierMapper.selectList(Wrappers.lambdaQuery(SupplierDO.class) + .in(SupplierDO::getName, supplierNames)); + } + } \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/admin/MaterialBatchController.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/admin/MaterialBatchController.java index 2e4b5730..582acff3 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/admin/MaterialBatchController.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/admin/MaterialBatchController.java @@ -1,9 +1,17 @@ package com.zt.plat.module.qms.resource.material.controller.admin; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.converters.longconverter.LongStringConverter; +import com.alibaba.excel.write.metadata.WriteSheet; +import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import com.zt.plat.framework.common.util.http.HttpUtils; import com.zt.plat.framework.datapermission.core.annotation.DeptDataPermissionIgnore; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchPageReqVO; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchRespVO; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchSaveReqVO; +import com.zt.plat.module.qms.resource.material.controller.vo.importer.MaterialBatchImportExcelVO; +import com.zt.plat.module.qms.resource.material.controller.vo.resp.MaterialBatchImportRespVO; import com.zt.plat.module.qms.resource.material.dal.dataobject.MaterialBatchDO; import com.zt.plat.module.qms.resource.material.service.MaterialBatchService; import com.zt.plat.module.qms.resource.material.valid.AddGroup; @@ -20,6 +28,10 @@ import io.swagger.v3.oas.annotations.Operation; import jakarta.validation.*; import jakarta.servlet.http.*; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; import java.util.*; import java.io.IOException; @@ -33,6 +45,8 @@ import static com.zt.plat.framework.common.pojo.CommonResult.success; import com.zt.plat.framework.excel.core.util.ExcelUtils; import com.zt.plat.framework.apilog.core.annotation.ApiAccessLog; +import org.springframework.web.multipart.MultipartFile; + import static com.zt.plat.framework.apilog.core.enums.OperateTypeEnum.*; @Tag(name = "管理后台 - 物料批次") @@ -132,4 +146,46 @@ public class MaterialBatchController implements BusinessControllerMarker { return success(BeanUtils.toBean(list, MaterialBatchRespVO.class)); } + @GetMapping("/get-import-template") + @Operation(summary = "获得物料批次导入模板") + public void importTemplate(HttpServletResponse response) throws IOException { + List samples = Arrays.asList( + MaterialBatchImportExcelVO.builder() + .productName("无水硼砂") + .productCode("W11174909") + .productModelNo("95%") + .supplier("供应商 1") + .manufacturerDate(LocalDate.parse("2026-03-15")) + .dueDate(LocalDate.parse("2026-08-11")) + .inboundQuantity(BigDecimal.valueOf(100)) + .location("1 号货架") + .remark("模板数据,导入时请删除!") + .build(), + MaterialBatchImportExcelVO.builder() + .productName("氧化钙") + .productCode("W10102372") + .productModelNo("AR500g/瓶") + .supplier("供应商 2") + .manufacturerDate(LocalDate.parse("2026-04-16")) + .dueDate(LocalDate.parse("2026-09-18")) + .inboundQuantity(BigDecimal.valueOf(200)) + .location("2 号货架") + .remark("模板数据,导入时请删除!") + .build() + ); + + ExcelUtils.write(response, "物料批次导入模板.xls", "物料批次导入", + MaterialBatchImportExcelVO.class, samples); + } + + + @PostMapping("/import") + @Operation(summary = "导入物料批次") + @Parameter(name = "file", description = "Excel 文件", required = true) + public CommonResult importMaterialBatch(@RequestParam("file") MultipartFile file) throws IOException { + List importList = ExcelUtils.read(file, MaterialBatchImportExcelVO.class, 0); + MaterialBatchImportRespVO respVO = materialBatchService.importMaterialBatchList(importList); + return success(respVO); + } + } \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/importer/MaterialBatchImportExcelVO.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/importer/MaterialBatchImportExcelVO.java new file mode 100644 index 00000000..1bf00be5 --- /dev/null +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/importer/MaterialBatchImportExcelVO.java @@ -0,0 +1,50 @@ +package com.zt.plat.module.qms.resource.material.controller.vo.importer; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchRespVO; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - 物料批次导入 Request VO") +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = false) +public class MaterialBatchImportExcelVO { + + @ExcelProperty("物料名称") + private String productName; + + @ExcelProperty("物料编码") + private String productCode; + + @ExcelProperty("物料型号") + private String productModelNo; + + @ExcelProperty("供应商") + private String supplier; + + @ExcelProperty("生产日期") + private LocalDate manufacturerDate; + + @ExcelProperty("到期日期") + private LocalDate dueDate; + + @ExcelProperty("数量") + private BigDecimal inboundQuantity; + + @ExcelProperty("存放位置描述") + private String location; + + @ExcelProperty("备注") + private String remark; + +} \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/resp/MaterialBatchImportRespVO.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/resp/MaterialBatchImportRespVO.java new file mode 100644 index 00000000..8def92ea --- /dev/null +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/controller/vo/resp/MaterialBatchImportRespVO.java @@ -0,0 +1,24 @@ +package com.zt.plat.module.qms.resource.material.controller.vo.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Schema(description = "管理后台 - 物料批次导入 Response VO") +@Data +public class MaterialBatchImportRespVO { + + @Schema(description = "导入成功的批次编号列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List successBatchNos; + + @Schema(description = "导入失败的批次集合,key 为行号或标识,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) + private Map failureBatches; + + @Schema(description = "导入成功的记录数", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer successCount; + + @Schema(description = "导入失败的记录数", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer failureCount; +} diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchService.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchService.java index a6c5febc..ce8e5ffb 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchService.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchService.java @@ -6,6 +6,8 @@ import com.zt.plat.module.qms.enums.LockType; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchPageReqVO; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchRespVO; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchSaveReqVO; +import com.zt.plat.module.qms.resource.material.controller.vo.importer.MaterialBatchImportExcelVO; +import com.zt.plat.module.qms.resource.material.controller.vo.resp.MaterialBatchImportRespVO; import com.zt.plat.module.qms.resource.material.dal.dataobject.MaterialBatchDO; import com.zt.plat.module.qms.resource.material.dal.dataobject.MaterialLifecycleDetailDO; import jakarta.validation.*; @@ -189,4 +191,12 @@ public interface MaterialBatchService { * @param id 流程id */ void createVerifyBatchAssignsByLfcId(Long id); + + /** + * 导入物料批次列表 + * + * @param importList 导入数据列表 + * @return 导入结果 + */ + MaterialBatchImportRespVO importMaterialBatchList(List importList); } \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchServiceImpl.java index 8a846903..eee28320 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialBatchServiceImpl.java @@ -17,12 +17,16 @@ import com.zt.plat.module.qms.core.code.SequenceUtil; import com.zt.plat.module.qms.core.constant.DataTypeConstant; import com.zt.plat.module.qms.enums.AdjustType; import com.zt.plat.module.qms.enums.LockType; +import com.zt.plat.module.qms.office.supplier.dal.dataobject.SupplierDO; +import com.zt.plat.module.qms.office.supplier.service.SupplierService; import com.zt.plat.module.qms.resource.material.constant.MaterialConstants; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchPageReqVO; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchRespVO; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialBatchSaveReqVO; import com.zt.plat.module.qms.resource.material.controller.vo.MaterialProductRespVO; +import com.zt.plat.module.qms.resource.material.controller.vo.importer.MaterialBatchImportExcelVO; import com.zt.plat.module.qms.resource.material.controller.vo.query.MaterialProductQueryVO; +import com.zt.plat.module.qms.resource.material.controller.vo.resp.MaterialBatchImportRespVO; import com.zt.plat.module.qms.resource.material.dal.dataobject.MaterialBatchDO; import com.zt.plat.module.qms.resource.material.dal.dataobject.MaterialLifecycleDO; import com.zt.plat.module.qms.resource.material.dal.dataobject.MaterialLifecycleDetailDO; @@ -42,10 +46,7 @@ import org.springframework.validation.annotation.Validated; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -74,6 +75,8 @@ public class MaterialBatchServiceImpl implements MaterialBatchService { private MaterialLifecycleService materialLifecycleService; @Autowired private BpmProcessInstanceApi bpmProcessInstanceApi; + @Autowired + private SupplierService supplierService; @Override public MaterialBatchRespVO createMaterialBatch(MaterialBatchSaveReqVO createReqVO) { @@ -519,6 +522,60 @@ public class MaterialBatchServiceImpl implements MaterialBatchService { materialBatchMapper.insertBatch(gongs); } + @Override + public MaterialBatchImportRespVO importMaterialBatchList(List importList) { + if (CollUtil.isEmpty(importList)) throw new ServiceException(1_032_160_000, "导入数据不能为空"); + log.info("导入数据:{}", importList); + List successBatchNos = new ArrayList<>(); + Map failureBatches = new LinkedHashMap<>(); + // 检验 + for (MaterialBatchImportExcelVO batch : importList) { + if (StrUtil.isEmpty(batch.getProductCode())) throw new ServiceException(1_032_160_000, "物料编码不能为空"); + if (batch.getInboundQuantity() == null || batch.getInboundQuantity().compareTo(BigDecimal.ZERO) < 0) + throw new ServiceException(1_032_160_000, "批次数量不能小于0"); + } + // 获取大类id 每个物料都得校验是否存在 + Set pdtCodes = importList.stream().map(MaterialBatchImportExcelVO::getProductCode).collect(Collectors.toSet()); + List products = materialProductService.getProductListByPdtCodes(new ArrayList<>(pdtCodes)); + if (CollUtil.isEmpty(products)) throw new ServiceException(1_032_160_000, "未找到对应的物料"); + Map productDOMapByCode = products.stream().collect(Collectors.toMap(MaterialProductDO::getCode, Function.identity())); + if (pdtCodes.size() != products.size()) { + List notFoundCodes = new ArrayList<>(); + for (String pdtCode : pdtCodes) { + if (!productDOMapByCode.containsKey(pdtCode)) { + notFoundCodes.add(pdtCode); + } + } + if (CollUtil.isNotEmpty(notFoundCodes)) { + throw new ServiceException(1_032_160_000, "未找到以下物料:" + String.join(", ", notFoundCodes)); + } + } + // 获取供应商 + Set supplierNames = importList.stream().map(MaterialBatchImportExcelVO::getSupplier).filter(Objects::nonNull).collect(Collectors.toSet()); + if (CollUtil.isNotEmpty(supplierNames)) { + List suppliers = supplierService.getSuppliersByNames(new ArrayList<>(supplierNames)); + if (CollUtil.isEmpty(suppliers)) throw new ServiceException(1_032_160_000, "未找到对应的供应商"); + Map supplierDOMapByName = suppliers.stream().collect(Collectors.toMap(SupplierDO::getName, Function.identity())); + if (supplierNames.size() != suppliers.size()) { + List notFoundNames = new ArrayList<>(); + for (String supplierName : supplierNames) { + if (!supplierDOMapByName.containsKey(supplierName)) { + notFoundNames.add(supplierName); + } + } + if (CollUtil.isNotEmpty(notFoundNames)) { + throw new ServiceException(1_032_160_000, "未找到以下供应商:" + String.join(", ", notFoundNames)); + } + } + } + return new MaterialBatchImportRespVO() + .setSuccessBatchNos(successBatchNos) + .setFailureBatches(failureBatches) + .setSuccessCount(successBatchNos.size()) + .setFailureCount(failureBatches.size()); + } + + private void lockBatchOrGongReturnExchangeCount(LockType lockType, List batchOrGongDOS, Map lifecycleDetailDOMapByBatOrGongId) { for (MaterialBatchDO batOrGong : batchOrGongDOS) { MaterialLifecycleDetailDO detailDO = lifecycleDetailDOMapByBatOrGongId.get(batOrGong.getId()); diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialProductService.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialProductService.java index 45d9222a..65999bc7 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialProductService.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialProductService.java @@ -148,4 +148,12 @@ public interface MaterialProductService { * @return 是否是审核的分类 */ Boolean checkIsVerifyCategoryByPdtId(Long productId); + + /** + * 根据pdtCodes获取大类数据 + * + * @param pdtCodes pdtCodes + * @return 物料数据 + */ + List getProductListByPdtCodes(List pdtCodes); } \ No newline at end of file diff --git a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialProductServiceImpl.java b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialProductServiceImpl.java index f79571bc..8e80d3f3 100644 --- a/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialProductServiceImpl.java +++ b/zt-module-qms/zt-module-qms-server/src/main/java/com/zt/plat/module/qms/resource/material/service/MaterialProductServiceImpl.java @@ -478,4 +478,11 @@ public class MaterialProductServiceImpl implements MaterialProductService { return "1".equals(verifyCalibrateFlag); } + @Override + public List getProductListByPdtCodes(List pdtCodes) { + + return materialProductMapper.selectList(Wrappers.lambdaQuery(MaterialProductDO.class) + .in(MaterialProductDO::getCode, pdtCodes)); + } + } \ No newline at end of file