From e6a12aaeb28d97b12ae3ec0629bd4a0014f55665 Mon Sep 17 00:00:00 2001 From: zc Date: Sun, 12 Apr 2026 18:28:02 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../material/mapper/MaterialInfoMapper.java | 4 + .../material/model/entity/MaterialInfoDO.java | 8 +- .../material/model/req/BatchImportReq.java | 24 +++ .../material/model/req/BatchImportRowReq.java | 33 ++++ .../model/req/MaterialImportRowReq.java | 4 +- .../material/model/req/MaterialInfoReq.java | 17 +- .../material/model/resp/MaterialInfoResp.java | 17 +- .../material/service/MaterialInfoService.java | 25 +++ .../service/impl/MaterialInfoServiceImpl.java | 104 +++++++++- .../model/req/MaterialTypeImportReq.java | 32 ++++ .../model/req/MaterialTypeImportRowReq.java | 40 ++++ .../resp/MaterialTypeImportParseResp.java | 43 +++++ .../model/resp/MaterialTypeImportResp.java | 34 ++++ .../service/MaterialTypeService.java | 12 ++ .../service/impl/MaterialTypeServiceImpl.java | 181 +++++++++++++++++- .../weighManage/model/resp/WorkOrderResp.java | 6 + .../service/impl/WorkOrderServiceImpl.java | 1 + .../resources/mapper/MeterialInfoMapper.xml | 33 ++++ .../materialType/MaterialTypeController.java | 36 ++++ .../meterial/MaterialInfoController.java | 25 +++ .../weighManage/ah/AHDZCConnect.java | 3 +- .../wms/admin/controller/ys/NetCommon.java | 6 +- .../admin/controller/ys/ysNetController.java | 2 +- .../resources/templates/import/batch.xlsx | Bin 0 -> 9048 bytes .../templates/import/materialType.xlsx | Bin 0 -> 9118 bytes 25 files changed, 661 insertions(+), 29 deletions(-) create mode 100644 wms-module-system/src/main/java/top/wms/admin/material/model/req/BatchImportReq.java create mode 100644 wms-module-system/src/main/java/top/wms/admin/material/model/req/BatchImportRowReq.java create mode 100644 wms-module-system/src/main/java/top/wms/admin/materialType/model/req/MaterialTypeImportReq.java create mode 100644 wms-module-system/src/main/java/top/wms/admin/materialType/model/req/MaterialTypeImportRowReq.java create mode 100644 wms-module-system/src/main/java/top/wms/admin/materialType/model/resp/MaterialTypeImportParseResp.java create mode 100644 wms-module-system/src/main/java/top/wms/admin/materialType/model/resp/MaterialTypeImportResp.java create mode 100644 wms-webapi/src/main/resources/templates/import/batch.xlsx create mode 100644 wms-webapi/src/main/resources/templates/import/materialType.xlsx diff --git a/wms-module-system/src/main/java/top/wms/admin/material/mapper/MaterialInfoMapper.java b/wms-module-system/src/main/java/top/wms/admin/material/mapper/MaterialInfoMapper.java index f58e75a..b79c6a5 100644 --- a/wms-module-system/src/main/java/top/wms/admin/material/mapper/MaterialInfoMapper.java +++ b/wms-module-system/src/main/java/top/wms/admin/material/mapper/MaterialInfoMapper.java @@ -28,4 +28,8 @@ public interface MaterialInfoMapper extends BaseMapper { @Param(Constants.WRAPPER) QueryWrapper queryWrapper); List selectMaterialInfoExport(@Param(Constants.WRAPPER) QueryWrapper queryWrapper); + + void updateBatchNull(); + + int updateBatchByCode(List materialInfoDOS); } diff --git a/wms-module-system/src/main/java/top/wms/admin/material/model/entity/MaterialInfoDO.java b/wms-module-system/src/main/java/top/wms/admin/material/model/entity/MaterialInfoDO.java index 88457f2..1ae1aa9 100644 --- a/wms-module-system/src/main/java/top/wms/admin/material/model/entity/MaterialInfoDO.java +++ b/wms-module-system/src/main/java/top/wms/admin/material/model/entity/MaterialInfoDO.java @@ -48,7 +48,7 @@ public class MaterialInfoDO extends BaseDO { private String photoUrl; /** - * 物料类型ID + * 物料品类ID */ private Long materialTypeId; @@ -66,4 +66,10 @@ public class MaterialInfoDO extends BaseDO { * 颜色 */ private String color; + + /** + * 批次 + */ + private String batch; + } diff --git a/wms-module-system/src/main/java/top/wms/admin/material/model/req/BatchImportReq.java b/wms-module-system/src/main/java/top/wms/admin/material/model/req/BatchImportReq.java new file mode 100644 index 0000000..81f6d25 --- /dev/null +++ b/wms-module-system/src/main/java/top/wms/admin/material/model/req/BatchImportReq.java @@ -0,0 +1,24 @@ +package top.wms.admin.material.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@Schema(description = "批次导入参数") +public class BatchImportReq implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 导入会话KEY + */ + @Schema(description = "导入会话KEY", example = "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed") + @NotBlank(message = "导入已过期,请重新上传") + private String importKey; + +} diff --git a/wms-module-system/src/main/java/top/wms/admin/material/model/req/BatchImportRowReq.java b/wms-module-system/src/main/java/top/wms/admin/material/model/req/BatchImportRowReq.java new file mode 100644 index 0000000..d8742f2 --- /dev/null +++ b/wms-module-system/src/main/java/top/wms/admin/material/model/req/BatchImportRowReq.java @@ -0,0 +1,33 @@ +package top.wms.admin.material.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@Schema(description = "物料信息导入行数据") +public class BatchImportRowReq implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + /** + * 物料名称 + */ + @Schema(description = "物料编码") + @NotBlank(message = "物料编码不能为空") + @Length(max = 255, message = "物料编码长度不能超过 {max} 个字符") + private String encoding; + + /** + * 批次 + */ + @Schema(description = "批次") + @NotBlank(message = "批次不能为空") + @Length(max = 255, message = "批次长度不能超过 {max} 个字符") + private String batch; + +} diff --git a/wms-module-system/src/main/java/top/wms/admin/material/model/req/MaterialImportRowReq.java b/wms-module-system/src/main/java/top/wms/admin/material/model/req/MaterialImportRowReq.java index 393f356..1788c7f 100644 --- a/wms-module-system/src/main/java/top/wms/admin/material/model/req/MaterialImportRowReq.java +++ b/wms-module-system/src/main/java/top/wms/admin/material/model/req/MaterialImportRowReq.java @@ -52,9 +52,9 @@ public class MaterialImportRowReq implements Serializable { private Double materialSpec; /** - * 物料类型名称 + * 物料品类名称 */ - @Schema(description = "物料类型名称") + @Schema(description = "物料品类名称") private String typeName; /** diff --git a/wms-module-system/src/main/java/top/wms/admin/material/model/req/MaterialInfoReq.java b/wms-module-system/src/main/java/top/wms/admin/material/model/req/MaterialInfoReq.java index 986957c..1dee185 100644 --- a/wms-module-system/src/main/java/top/wms/admin/material/model/req/MaterialInfoReq.java +++ b/wms-module-system/src/main/java/top/wms/admin/material/model/req/MaterialInfoReq.java @@ -48,8 +48,8 @@ public class MaterialInfoReq implements Serializable { private Double unitWeight; /* - * 物料直径 - * */ + * 物料直径 + * */ @Schema(description = "物料直径") private Double materialSpec; @@ -61,10 +61,10 @@ public class MaterialInfoReq implements Serializable { private String photoUrl; /** - * 物料类型ID + * 物料品类ID */ - @Schema(description = "物料类型ID") - @NotNull(message = "物料类型ID不能为空") + @Schema(description = "物料品类ID") + @NotNull(message = "物料品类ID不能为空") private Long materialTypeId; /** @@ -85,4 +85,11 @@ public class MaterialInfoReq implements Serializable { */ @Schema(description = "颜色") private String color; + + /** + * 批次 + */ + @Schema(description = "批次") + private String batch; + } diff --git a/wms-module-system/src/main/java/top/wms/admin/material/model/resp/MaterialInfoResp.java b/wms-module-system/src/main/java/top/wms/admin/material/model/resp/MaterialInfoResp.java index c51a196..0079e4d 100644 --- a/wms-module-system/src/main/java/top/wms/admin/material/model/resp/MaterialInfoResp.java +++ b/wms-module-system/src/main/java/top/wms/admin/material/model/resp/MaterialInfoResp.java @@ -58,10 +58,10 @@ public class MaterialInfoResp extends BaseDetailResp { private String photoUrl; /** - * 物料类型名称 + * 物料品类名称 */ - @Schema(description = "物料类型名称") - @ExcelProperty(value = "物料类型") + @Schema(description = "物料品类名称") + @ExcelProperty(value = "物料品类") private String typeName; /** @@ -72,9 +72,9 @@ public class MaterialInfoResp extends BaseDetailResp { private String materialProcess; /** - * 物料类型ID + * 物料品类ID */ - @Schema(description = "物料类型ID") + @Schema(description = "物料品类ID") @ExcelIgnore private Long materialTypeId; @@ -106,4 +106,11 @@ public class MaterialInfoResp extends BaseDetailResp { @ExcelProperty(value = "颜色", order = 6) private String color; + /** + * 批次 + */ + @Schema(description = "批次") + @ExcelProperty(value = "批次", order = 7) + private String batch; + } diff --git a/wms-module-system/src/main/java/top/wms/admin/material/service/MaterialInfoService.java b/wms-module-system/src/main/java/top/wms/admin/material/service/MaterialInfoService.java index ad1d075..17bc750 100644 --- a/wms-module-system/src/main/java/top/wms/admin/material/service/MaterialInfoService.java +++ b/wms-module-system/src/main/java/top/wms/admin/material/service/MaterialInfoService.java @@ -4,6 +4,7 @@ import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; import top.continew.starter.extension.crud.service.BaseService; import top.wms.admin.material.model.query.MaterialInfoQuery; +import top.wms.admin.material.model.req.BatchImportReq; import top.wms.admin.material.model.req.MaterialInfoImportReq; import top.wms.admin.material.model.req.MaterialInfoReq; import top.wms.admin.material.model.resp.MaterialImportParseResp; @@ -69,4 +70,28 @@ public interface MaterialInfoService extends BaseService existCode = listExistByField(importMaterialList, MaterialImportRowReq::getEncoding, MaterialInfoDO::getEncoding); CheckUtils.throwIf(isExitImportMaterial(req, importMaterialList, existName, existCode), "数据不符合导入策略,已退出导入"); - //查询物料类型 + //查询物料品类 List collect = importMaterialList.stream().map(MaterialImportRowReq::getTypeName).distinct().toList(); Map materialTypeMap = new HashMap<>(); if (CollUtil.isNotEmpty(collect)) { @@ -290,6 +290,16 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl ValidationUtil.validate(row).isEmpty()).toList(); } + /** + * 过滤无效的导入用户数据(批量导入不严格校验数据) + * + * @param importRowList 导入数据 + */ + private List filterImportData2(List importRowList) { + // 校验过滤 + return importRowList.stream().filter(row -> ValidationUtil.validate(row).isEmpty()).toList(); + } + /** * 按指定数据集获取数据库已存在内容 * @@ -472,4 +482,84 @@ public class MaterialInfoServiceImpl extends BaseServiceImpl importRowList; + // 读取表格数据 + try { + importRowList = EasyExcel.read(file.getInputStream()) + .head(BatchImportRowReq.class) + .sheet() + .headRowNumber(1) + .doReadSync(); + } catch (Exception e) { + log.error("物料信息导入数据文件解析异常:", e); + throw new BusinessException("数据文件解析异常"); + } + // 总计行数 + materialImportResp.setTotalRows(importRowList.size()); + CheckUtils.throwIfEmpty(importRowList, "数据文件格式错误"); + // 有效行数:过滤无效(同名物料)数据 + List validRowList = this.filterImportData2(importRowList); + materialImportResp.setValidRows(validRowList.size()); + CheckUtils.throwIfEmpty(validRowList, "数据文件格式错误"); + + // 设置导入会话并缓存数据,有效期10分钟 + String importKey = UUID.fastUUID().toString(true); + RedisUtils.set(CacheConstants.DATA_IMPORT_KEY + importKey, JSONUtil.toJsonStr(validRowList), Duration + .ofMinutes(10)); + materialImportResp.setImportKey(importKey); + return materialImportResp; + } + + @Override + public MaterialInfoImportResp importBatchMaterial(BatchImportReq req) { + // 校验导入会话是否过期 + List batchImportRowReqs; + try { + String data = RedisUtils.get(CacheConstants.DATA_IMPORT_KEY + req.getImportKey()); + batchImportRowReqs = JSONUtil.toList(data, BatchImportRowReq.class); + CheckUtils.throwIf(CollUtil.isEmpty(batchImportRowReqs), "导入已过期,请重新上传"); + } catch (Exception e) { + log.error("导入异常:", e); + throw new BusinessException("导入已过期,请重新上传"); + } + + // 转换为MaterialInfoDO列表 + List materialInfoDOS = batchImportRowReqs.stream() + .map(row -> { + MaterialInfoDO materialInfoDO = new MaterialInfoDO(); + materialInfoDO.setEncoding(row.getEncoding()); + materialInfoDO.setBatch(row.getBatch()); + materialInfoDO.setUpdateUser(UserContextHolder.getUserId()); + return materialInfoDO; + }) + .toList(); + + // 批量操作数据库集合 + try { + InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().blockAttack(true).build()); + baseMapper.updateBatchNull(); + } finally { + InterceptorIgnoreHelper.clearIgnoreStrategy(); + } + int totalUpdateCount = baseMapper.updateBatchByCode(materialInfoDOS); + RedisUtils.delete(CacheConstants.DATA_IMPORT_KEY + req.getImportKey()); + return new MaterialInfoImportResp(materialInfoDOS.size(), 0, totalUpdateCount); + } + +} \ No newline at end of file diff --git a/wms-module-system/src/main/java/top/wms/admin/materialType/model/req/MaterialTypeImportReq.java b/wms-module-system/src/main/java/top/wms/admin/materialType/model/req/MaterialTypeImportReq.java new file mode 100644 index 0000000..1b2a0b3 --- /dev/null +++ b/wms-module-system/src/main/java/top/wms/admin/materialType/model/req/MaterialTypeImportReq.java @@ -0,0 +1,32 @@ +package top.wms.admin.materialType.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import top.wms.admin.system.enums.ImportPolicyEnum; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@Schema(description = "物料品类导入参数") +public class MaterialTypeImportReq implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 导入会话KEY + */ + @Schema(description = "导入会话KEY", example = "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed") + @NotBlank(message = "导入已过期,请重新上传") + private String importKey; + + /** + * 品类名称重复策略 + */ + @Schema(description = "品类名称重复策略", example = "1") + @NotNull(message = "品类名称重复策略不能为空") + private ImportPolicyEnum duplicateTypeName; +} \ No newline at end of file diff --git a/wms-module-system/src/main/java/top/wms/admin/materialType/model/req/MaterialTypeImportRowReq.java b/wms-module-system/src/main/java/top/wms/admin/materialType/model/req/MaterialTypeImportRowReq.java new file mode 100644 index 0000000..ac1f7e1 --- /dev/null +++ b/wms-module-system/src/main/java/top/wms/admin/materialType/model/req/MaterialTypeImportRowReq.java @@ -0,0 +1,40 @@ +package top.wms.admin.materialType.model.req; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.io.Serial; +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +@Schema(description = "物料品类导入行数据") +public class MaterialTypeImportRowReq implements Serializable { + @Serial + private static final long serialVersionUID = 1L; + + /** + * 品类名称 + */ + @Schema(description = "品类名称") + @NotBlank(message = "品类名称不能为空") + @Length(max = 255, message = "品类名称长度不能超过 {max} 个字符") + private String typeName; + + /** + * 品类下行浮动范围(%) + */ + @Schema(description = "品类下行浮动范围(%)") + @NotNull(message = "品类下行浮动范围不能为空") + private BigDecimal downFloatRatio; + + /** + * 品类上行浮动范围(%) + */ + @Schema(description = "品类上行浮动范围(%)") + @NotNull(message = "品类上行浮动范围不能为空") + private BigDecimal upFloatRatio; +} \ No newline at end of file diff --git a/wms-module-system/src/main/java/top/wms/admin/materialType/model/resp/MaterialTypeImportParseResp.java b/wms-module-system/src/main/java/top/wms/admin/materialType/model/resp/MaterialTypeImportParseResp.java new file mode 100644 index 0000000..74d3fc1 --- /dev/null +++ b/wms-module-system/src/main/java/top/wms/admin/materialType/model/resp/MaterialTypeImportParseResp.java @@ -0,0 +1,43 @@ +package top.wms.admin.materialType.model.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serial; +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "物料品类导入解析结果") +public class MaterialTypeImportParseResp implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 导入会话 Key + */ + @Schema(description = "导入会话Key", example = "1b9d6bcd-bbfd-4b2d-9b5d-ab8dfbbd4bed") + private String importKey; + + /** + * 总计行数 + */ + @Schema(description = "总计行数", example = "100") + private Integer totalRows; + + /** + * 有效行数 + */ + @Schema(description = "有效行数", example = "100") + private Integer validRows; + + /** + * 重复品类名称行数 + */ + @Schema(description = "重复品类名称行数", example = "100") + private Integer duplicateNameRows; +} \ No newline at end of file diff --git a/wms-module-system/src/main/java/top/wms/admin/materialType/model/resp/MaterialTypeImportResp.java b/wms-module-system/src/main/java/top/wms/admin/materialType/model/resp/MaterialTypeImportResp.java new file mode 100644 index 0000000..848c051 --- /dev/null +++ b/wms-module-system/src/main/java/top/wms/admin/materialType/model/resp/MaterialTypeImportResp.java @@ -0,0 +1,34 @@ +package top.wms.admin.materialType.model.resp; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@Schema(description = "物料品类导入结果") +@AllArgsConstructor +@NoArgsConstructor +public class MaterialTypeImportResp implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 总计行数 + */ + @Schema(description = "总计行数", example = "100") + private Integer totalRows; + + /** + * 新增行数 + */ + @Schema(description = "新增行数", example = "100") + private Integer insertRows; + + /** + * 修改行数 + */ + @Schema(description = "修改行数", example = "100") + private Integer updateRows; +} \ No newline at end of file diff --git a/wms-module-system/src/main/java/top/wms/admin/materialType/service/MaterialTypeService.java b/wms-module-system/src/main/java/top/wms/admin/materialType/service/MaterialTypeService.java index 3bbfde6..fa5d37d 100644 --- a/wms-module-system/src/main/java/top/wms/admin/materialType/service/MaterialTypeService.java +++ b/wms-module-system/src/main/java/top/wms/admin/materialType/service/MaterialTypeService.java @@ -1,11 +1,17 @@ package top.wms.admin.materialType.service; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.web.multipart.MultipartFile; import top.continew.starter.extension.crud.model.resp.LabelValueResp; import top.continew.starter.extension.crud.service.BaseService; import top.wms.admin.materialType.model.query.MaterialTypeQuery; +import top.wms.admin.materialType.model.req.MaterialTypeImportReq; import top.wms.admin.materialType.model.req.MaterialTypeReq; +import top.wms.admin.materialType.model.resp.MaterialTypeImportParseResp; +import top.wms.admin.materialType.model.resp.MaterialTypeImportResp; import top.wms.admin.materialType.model.resp.MaterialTypeResp; +import java.io.IOException; import java.util.List; /** @@ -17,4 +23,10 @@ import java.util.List; public interface MaterialTypeService extends BaseService { List getSelectList(); + + void downloadImportTemplate(HttpServletResponse response) throws IOException; + + MaterialTypeImportParseResp parseImport(MultipartFile file); + + MaterialTypeImportResp importMaterial(MaterialTypeImportReq req); } \ No newline at end of file diff --git a/wms-module-system/src/main/java/top/wms/admin/materialType/service/impl/MaterialTypeServiceImpl.java b/wms-module-system/src/main/java/top/wms/admin/materialType/service/impl/MaterialTypeServiceImpl.java index 61dacfc..c6f5e5f 100644 --- a/wms-module-system/src/main/java/top/wms/admin/materialType/service/impl/MaterialTypeServiceImpl.java +++ b/wms-module-system/src/main/java/top/wms/admin/materialType/service/impl/MaterialTypeServiceImpl.java @@ -1,21 +1,49 @@ package top.wms.admin.materialType.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.io.resource.ResourceUtil; +import cn.hutool.core.lang.UUID; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.extra.validation.ValidationUtil; +import cn.hutool.http.ContentType; +import cn.hutool.json.JSONUtil; +import com.alibaba.excel.EasyExcel; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; - +import lombok.extern.slf4j.Slf4j; +import net.dreamlu.mica.core.result.R; import org.springframework.stereotype.Service; - +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import top.continew.starter.cache.redisson.util.RedisUtils; +import top.continew.starter.core.exception.BusinessException; +import top.continew.starter.core.validation.CheckUtils; import top.continew.starter.extension.crud.model.resp.LabelValueResp; import top.continew.starter.extension.crud.service.BaseServiceImpl; +import top.continew.starter.web.util.FileUploadUtils; +import top.wms.admin.common.constant.CacheConstants; +import top.wms.admin.common.context.UserContextHolder; import top.wms.admin.materialType.mapper.MaterialTypeMapper; import top.wms.admin.materialType.mapstruct.MaterialTypeConvert; import top.wms.admin.materialType.model.entity.MaterialTypeDO; import top.wms.admin.materialType.model.query.MaterialTypeQuery; +import top.wms.admin.materialType.model.req.MaterialTypeImportReq; +import top.wms.admin.materialType.model.req.MaterialTypeImportRowReq; import top.wms.admin.materialType.model.req.MaterialTypeReq; +import top.wms.admin.materialType.model.resp.MaterialTypeImportParseResp; +import top.wms.admin.materialType.model.resp.MaterialTypeImportResp; import top.wms.admin.materialType.model.resp.MaterialTypeResp; import top.wms.admin.materialType.service.MaterialTypeService; -import java.util.List; +import java.io.IOException; +import java.time.Duration; +import java.util.*; +import java.util.function.Function; + +import static top.wms.admin.system.enums.ImportPolicyEnum.*; /** * 物料品类业务实现 @@ -25,6 +53,7 @@ import java.util.List; */ @Service @RequiredArgsConstructor +@Slf4j public class MaterialTypeServiceImpl extends BaseServiceImpl implements MaterialTypeService { private final MaterialTypeConvert materialTypeConvert; @@ -34,4 +63,150 @@ public class MaterialTypeServiceImpl extends BaseServiceImpl materialTypeDOS = baseMapper.selectList(new QueryWrapper<>()); return materialTypeConvert.labelValueList(materialTypeDOS); } + + @Override + public void downloadImportTemplate(HttpServletResponse response) throws IOException { + try { + FileUploadUtils.download(response, ResourceUtil + .getStream("templates/import/materialType.xlsx"), "物料品类导入模板.xlsx"); + } catch (Exception e) { + log.error("下载物料品类导入模板失败:", e); + response.setCharacterEncoding(CharsetUtil.UTF_8); + response.setContentType(ContentType.JSON.toString()); + response.getWriter().write(JSONUtil.toJsonStr(R.fail("下载批次导入模板失败"))); + } + } + + @Override + public MaterialTypeImportParseResp parseImport(MultipartFile file) { + MaterialTypeImportParseResp materialTypeImportResp = new MaterialTypeImportParseResp(); + List importRowList; + try { + importRowList = EasyExcel.read(file.getInputStream()) + .head(MaterialTypeImportRowReq.class) + .sheet() + .headRowNumber(1) + .doReadSync(); + } catch (Exception e) { + log.error("物料品类导入数据文件解析异常:", e); + throw new BusinessException("数据文件解析异常"); + } + materialTypeImportResp.setTotalRows(importRowList.size()); + CheckUtils.throwIfEmpty(importRowList, "数据文件格式错误"); + List validRowList = this.filterImportData(importRowList); + materialTypeImportResp.setValidRows(validRowList.size()); + CheckUtils.throwIfEmpty(validRowList, "数据文件格式错误"); + + Set seenTypeName = new HashSet<>(); + boolean hasDuplicateTypeName = validRowList.stream() + .map(MaterialTypeImportRowReq::getTypeName) + .anyMatch(typeName -> typeName != null && !seenTypeName.add(typeName)); + CheckUtils.throwIf(hasDuplicateTypeName, "存在重复品类名称,请检测数据"); + + materialTypeImportResp.setDuplicateNameRows(countExistByField(validRowList, MaterialTypeImportRowReq::getTypeName, MaterialTypeDO::getTypeName, false)); + + String importKey = UUID.fastUUID().toString(true); + RedisUtils.set(CacheConstants.DATA_IMPORT_KEY + importKey, JSONUtil.toJsonStr(validRowList), Duration + .ofMinutes(10)); + materialTypeImportResp.setImportKey(importKey); + return materialTypeImportResp; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public MaterialTypeImportResp importMaterial(MaterialTypeImportReq req) { + List importMaterialTypeList; + try { + String data = RedisUtils.get(CacheConstants.DATA_IMPORT_KEY + req.getImportKey()); + importMaterialTypeList = JSONUtil.toList(data, MaterialTypeImportRowReq.class); + CheckUtils.throwIf(CollUtil.isEmpty(importMaterialTypeList), "导入已过期,请重新上传"); + } catch (Exception e) { + log.error("导入异常:", e); + throw new BusinessException("导入已过期,请重新上传"); + } + + List existTypeName = listExistByField(importMaterialTypeList, MaterialTypeImportRowReq::getTypeName, MaterialTypeDO::getTypeName); + CheckUtils.throwIf(isExitImportMaterialType(req, importMaterialTypeList, existTypeName), "数据不符合导入策略,已退出导入"); + + List insertList = new ArrayList<>(); + List updateList = new ArrayList<>(); + + for (MaterialTypeImportRowReq row : importMaterialTypeList) { + if (isSkipImportMaterialType(req, row, existTypeName)) { + continue; + } + MaterialTypeDO materialTypeDO = BeanUtil.toBeanIgnoreError(row, MaterialTypeDO.class); + + if (UPDATE.validate(req.getDuplicateTypeName(), row.getTypeName(), existTypeName)) { + materialTypeDO.setTypeName(row.getTypeName()); + materialTypeDO.setUpdateUser(UserContextHolder.getUserId()); + updateList.add(materialTypeDO); + } else { + insertList.add(materialTypeDO); + } + } + + doImportMaterialType(insertList, updateList); + RedisUtils.delete(CacheConstants.DATA_IMPORT_KEY + req.getImportKey()); + + int insertCount = insertList.size(); + int updateCount = updateList.size(); + int totalHandleCount = insertCount + updateCount; + return new MaterialTypeImportResp(totalHandleCount, insertCount, updateCount); + } + + private int countExistByField(List materialTypeRowList, + Function rowField, + com.baomidou.mybatisplus.core.toolkit.support.SFunction dbField, + boolean fieldEncrypt) { + List fieldValues = materialTypeRowList.stream().map(rowField).filter(Objects::nonNull).toList(); + if (fieldValues.isEmpty()) { + return 0; + } + return (int)this.count(Wrappers.lambdaQuery() + .in(dbField, fieldValues)); + } + + private List filterImportData(List importRowList) { + return importRowList.stream().filter(row -> ValidationUtil.validate(row).isEmpty()).toList(); + } + + private List listExistByField(List materialTypeRowList, + Function rowField, + com.baomidou.mybatisplus.core.toolkit.support.SFunction dbField) { + List fieldValues = materialTypeRowList.stream().map(rowField).filter(Objects::nonNull).toList(); + if (fieldValues.isEmpty()) { + return Collections.emptyList(); + } + List materialTypeDOList = baseMapper.selectList(Wrappers.lambdaQuery() + .in(dbField, fieldValues) + .select(dbField)); + return materialTypeDOList.stream().map(dbField).filter(Objects::nonNull).toList(); + } + + private boolean isExitImportMaterialType(MaterialTypeImportReq req, + List list, + List existTypeName) { + return list.stream() + .anyMatch(row -> EXIT.validate(req.getDuplicateTypeName(), row.getTypeName(), existTypeName)); + } + + private boolean isSkipImportMaterialType(MaterialTypeImportReq req, + MaterialTypeImportRowReq row, + List existTypeName) { + return SKIP.validate(req.getDuplicateTypeName(), row.getTypeName(), existTypeName); + } + + private void doImportMaterialType(List insertList, + List updateList) { + if (CollUtil.isNotEmpty(insertList)) { + baseMapper.insertBatch(insertList); + } + if (CollUtil.isNotEmpty(updateList)) { + for (MaterialTypeDO materialTypeDO : updateList) { + baseMapper.update(materialTypeDO, Wrappers.lambdaUpdate() + .eq(MaterialTypeDO::getTypeName, materialTypeDO.getTypeName())); + } + } + } } \ No newline at end of file diff --git a/wms-module-system/src/main/java/top/wms/admin/weighManage/model/resp/WorkOrderResp.java b/wms-module-system/src/main/java/top/wms/admin/weighManage/model/resp/WorkOrderResp.java index 905d586..18e6fbf 100644 --- a/wms-module-system/src/main/java/top/wms/admin/weighManage/model/resp/WorkOrderResp.java +++ b/wms-module-system/src/main/java/top/wms/admin/weighManage/model/resp/WorkOrderResp.java @@ -102,4 +102,10 @@ public class WorkOrderResp extends BaseDetailResp { @Schema(description = "任务工单详情信息列表") private List workOrderInfos; + /** + * 批次 + */ + @Schema(description = "批次") + private String batch; + } \ No newline at end of file diff --git a/wms-module-system/src/main/java/top/wms/admin/weighManage/service/impl/WorkOrderServiceImpl.java b/wms-module-system/src/main/java/top/wms/admin/weighManage/service/impl/WorkOrderServiceImpl.java index 0b0199c..137cc0d 100644 --- a/wms-module-system/src/main/java/top/wms/admin/weighManage/service/impl/WorkOrderServiceImpl.java +++ b/wms-module-system/src/main/java/top/wms/admin/weighManage/service/impl/WorkOrderServiceImpl.java @@ -78,6 +78,7 @@ public class WorkOrderServiceImpl extends BaseServiceImpl + + UPDATE sys_material_info SET batch = null + + + + UPDATE sys_material_info + + + batch = CASE + + + WHEN encoding = #{item.encoding} THEN #{item.batch} + + + ELSE batch + END, + update_user = CASE + + + WHEN encoding = #{item.encoding} THEN #{item.updateUser} + + + ELSE update_user + END, + update_time = NOW() + + + WHERE encoding IN + + #{item.encoding} + + +