fix:物料批次导入模板及导入
This commit is contained in:
@@ -62,4 +62,11 @@ public interface SupplierService {
|
||||
*/
|
||||
PageResult<SupplierDO> getSupplierPage(SupplierPageReqVO pageReqVO);
|
||||
|
||||
/**
|
||||
* 获得供应商列表
|
||||
*
|
||||
* @param supplierNames 供应商名称数组
|
||||
* @return 供应商列表
|
||||
*/
|
||||
List<SupplierDO> getSuppliersByNames(List<String> supplierNames);
|
||||
}
|
||||
@@ -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<SupplierDO> getSuppliersByNames(List<String> supplierNames) {
|
||||
|
||||
return supplierMapper.selectList(Wrappers.lambdaQuery(SupplierDO.class)
|
||||
.in(SupplierDO::getName, supplierNames));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<MaterialBatchImportExcelVO> 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<MaterialBatchImportRespVO> importMaterialBatch(@RequestParam("file") MultipartFile file) throws IOException {
|
||||
List<MaterialBatchImportExcelVO> importList = ExcelUtils.read(file, MaterialBatchImportExcelVO.class, 0);
|
||||
MaterialBatchImportRespVO respVO = materialBatchService.importMaterialBatchList(importList);
|
||||
return success(respVO);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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<String> successBatchNos;
|
||||
|
||||
@Schema(description = "导入失败的批次集合,key 为行号或标识,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Map<String, String> failureBatches;
|
||||
|
||||
@Schema(description = "导入成功的记录数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer successCount;
|
||||
|
||||
@Schema(description = "导入失败的记录数", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Integer failureCount;
|
||||
}
|
||||
@@ -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<MaterialBatchImportExcelVO> importList);
|
||||
}
|
||||
@@ -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<MaterialBatchImportExcelVO> importList) {
|
||||
if (CollUtil.isEmpty(importList)) throw new ServiceException(1_032_160_000, "导入数据不能为空");
|
||||
log.info("导入数据:{}", importList);
|
||||
List<String> successBatchNos = new ArrayList<>();
|
||||
Map<String, String> 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<String> pdtCodes = importList.stream().map(MaterialBatchImportExcelVO::getProductCode).collect(Collectors.toSet());
|
||||
List<MaterialProductDO> products = materialProductService.getProductListByPdtCodes(new ArrayList<>(pdtCodes));
|
||||
if (CollUtil.isEmpty(products)) throw new ServiceException(1_032_160_000, "未找到对应的物料");
|
||||
Map<String, MaterialProductDO> productDOMapByCode = products.stream().collect(Collectors.toMap(MaterialProductDO::getCode, Function.identity()));
|
||||
if (pdtCodes.size() != products.size()) {
|
||||
List<String> 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<String> supplierNames = importList.stream().map(MaterialBatchImportExcelVO::getSupplier).filter(Objects::nonNull).collect(Collectors.toSet());
|
||||
if (CollUtil.isNotEmpty(supplierNames)) {
|
||||
List<SupplierDO> suppliers = supplierService.getSuppliersByNames(new ArrayList<>(supplierNames));
|
||||
if (CollUtil.isEmpty(suppliers)) throw new ServiceException(1_032_160_000, "未找到对应的供应商");
|
||||
Map<String, SupplierDO> supplierDOMapByName = suppliers.stream().collect(Collectors.toMap(SupplierDO::getName, Function.identity()));
|
||||
if (supplierNames.size() != suppliers.size()) {
|
||||
List<String> 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<MaterialBatchDO> batchOrGongDOS, Map<Long, MaterialLifecycleDetailDO> lifecycleDetailDOMapByBatOrGongId) {
|
||||
for (MaterialBatchDO batOrGong : batchOrGongDOS) {
|
||||
MaterialLifecycleDetailDO detailDO = lifecycleDetailDOMapByBatOrGongId.get(batOrGong.getId());
|
||||
|
||||
@@ -148,4 +148,12 @@ public interface MaterialProductService {
|
||||
* @return 是否是审核的分类
|
||||
*/
|
||||
Boolean checkIsVerifyCategoryByPdtId(Long productId);
|
||||
|
||||
/**
|
||||
* 根据pdtCodes获取大类数据
|
||||
*
|
||||
* @param pdtCodes pdtCodes
|
||||
* @return 物料数据
|
||||
*/
|
||||
List<MaterialProductDO> getProductListByPdtCodes(List<String> pdtCodes);
|
||||
}
|
||||
@@ -478,4 +478,11 @@ public class MaterialProductServiceImpl implements MaterialProductService {
|
||||
return "1".equals(verifyCalibrateFlag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MaterialProductDO> getProductListByPdtCodes(List<String> pdtCodes) {
|
||||
|
||||
return materialProductMapper.selectList(Wrappers.lambdaQuery(MaterialProductDO.class)
|
||||
.in(MaterialProductDO::getCode, pdtCodes));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user