From ff37f00ec28f7d24ead035a322c5cacf07d7fa13 Mon Sep 17 00:00:00 2001 From: 10001392 <1055202292@qq.com> Date: Fri, 17 Apr 2026 15:05:48 +0800 Subject: [PATCH] =?UTF-8?q?1438=20=E5=8F=91=E8=B4=A7=E7=AE=A1=E7=90=86-?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E4=BF=A1=E6=81=AF-=E8=80=81=E9=BC=A0?= =?UTF-8?q?=E5=9B=BE=E9=A1=B5=E9=9D=A2=E6=B7=BB=E5=8A=A0=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/ShipmentMaterialExcelExportDTO.java | 96 +++++ .../dto/ShipmentMaterialExcelImportDTO.java | 56 +++ ...hipmentMaterialExcelTemplateExportDTO.java | 41 ++ .../ShipmentMaterialZipImportProcessor.java | 129 ++++++ nflg-wms-shipment/pom.xml | 15 + .../shipment/config/PowerJobClientConfig.java | 27 ++ .../controller/MaterialController.java | 57 +++ .../ShipmentMaterialControllerService.java | 377 ++++++++++++++++++ 8 files changed, 798 insertions(+) create mode 100644 nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelExportDTO.java create mode 100644 nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelImportDTO.java create mode 100644 nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelTemplateExportDTO.java create mode 100644 nflg-wms-scheduled/src/main/java/com/nflg/wms/scheduled/processor/ShipmentMaterialZipImportProcessor.java create mode 100644 nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/config/PowerJobClientConfig.java create mode 100644 nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/service/ShipmentMaterialControllerService.java diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelExportDTO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelExportDTO.java new file mode 100644 index 00000000..40ba4e67 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelExportDTO.java @@ -0,0 +1,96 @@ +package com.nflg.wms.common.pojo.dto; + +import lombok.Data; +import lombok.experimental.Accessors; +import org.ttzero.excel.annotation.ExcelColumn; +import org.ttzero.excel.annotation.MediaColumn; + +import java.math.BigDecimal; + +@Data +@Accessors(chain = true) +public class ShipmentMaterialExcelExportDTO { + + /** + * 物料编号 + */ + @ExcelColumn("物料编号") + private String no; + + /** + * 物料描述 + */ + @ExcelColumn("物料描述") + private String describe; + + /** + * 英文描述 + */ + @ExcelColumn("英文描述") + private String describeEn; + + /** + * 图号 + */ + @ExcelColumn("图号") + private String drawingNo; + + /** + * 重量 + */ + @ExcelColumn("重量") + private BigDecimal weight; + + /** + * 长度 + */ + @ExcelColumn("长度") + private BigDecimal length; + + /** + * 宽度 + */ + @ExcelColumn("宽度") + private BigDecimal width; + + /** + * 高度 + */ + @ExcelColumn("高度") + private BigDecimal height; + + /** + * 图片URL + */ + @MediaColumn + private String image; + + /** + * 图片类型 + */ + private String imageType; +// +// /** +// * 创建人 +// */ +// @ExcelColumn("创建人") +// private String createBy; +// +// /** +// * 创建时间 +// */ +// @ExcelColumn("创建时间") +// private String createTime; +// +// /** +// * 最后更新人 +// */ +// @ExcelColumn("最后更新人") +// private String updateBy; +// +// /** +// * 最后更新时间 +// */ +// @ExcelColumn("最后更新时间") +// private String updateTime; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelImportDTO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelImportDTO.java new file mode 100644 index 00000000..d86d55e6 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelImportDTO.java @@ -0,0 +1,56 @@ +package com.nflg.wms.common.pojo.dto; + +import lombok.Data; +import org.ttzero.excel.annotation.ExcelColumn; + +@Data +public class ShipmentMaterialExcelImportDTO { + + /** + * 物料编号 + */ + @ExcelColumn("*物料编号") + private String no; + + /** + * 物料描述 + */ + @ExcelColumn("物料描述") + private String describe; + + /** + * 重量 + */ + @ExcelColumn("*重量") + private String weight; + + /** + * 长度 + */ + @ExcelColumn("*长度") + private String length; + + /** + * 宽度 + */ + @ExcelColumn("*宽度") + private String width; + + /** + * 高度 + */ + @ExcelColumn("*高度") + private String height; + + /** + * 图片URL + */ + @ExcelColumn("图片URL") + private String image; + + /** + * 错误信息 + */ + @ExcelColumn("错误信息") + private String error; +} diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelTemplateExportDTO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelTemplateExportDTO.java new file mode 100644 index 00000000..9b3d40c4 --- /dev/null +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/dto/ShipmentMaterialExcelTemplateExportDTO.java @@ -0,0 +1,41 @@ +package com.nflg.wms.common.pojo.dto; + +import lombok.Data; +import lombok.experimental.Accessors; +import org.ttzero.excel.annotation.ExcelColumn; + +@Data +@Accessors(chain = true) +public class ShipmentMaterialExcelTemplateExportDTO { + + /** + * 物料编号 + */ + @ExcelColumn("*物料编号") + private String no; + + /** + * 重量 + */ + @ExcelColumn("*重量") + private String weight; + + /** + * 长度 + */ + @ExcelColumn("*长度") + private String length; + + /** + * 宽度 + */ + @ExcelColumn("*宽度") + private String width; + + /** + * 高度 + */ + @ExcelColumn("*高度") + private String height; + +} diff --git a/nflg-wms-scheduled/src/main/java/com/nflg/wms/scheduled/processor/ShipmentMaterialZipImportProcessor.java b/nflg-wms-scheduled/src/main/java/com/nflg/wms/scheduled/processor/ShipmentMaterialZipImportProcessor.java new file mode 100644 index 00000000..a975c76d --- /dev/null +++ b/nflg-wms-scheduled/src/main/java/com/nflg/wms/scheduled/processor/ShipmentMaterialZipImportProcessor.java @@ -0,0 +1,129 @@ +package com.nflg.wms.scheduled.processor; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import com.nflg.wms.common.pojo.dto.BomMaterialDTO; +import com.nflg.wms.repository.entity.WmsShipmentMaterial; +import com.nflg.wms.repository.service.IWmsShipmentMaterialService; +import com.nflg.wms.starter.service.BomMaterialService; +import com.nflg.wms.starter.service.FileUploadService; +import jakarta.annotation.Resource; +import org.apache.commons.io.FilenameUtils; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import tech.powerjob.worker.core.processor.ProcessResult; +import tech.powerjob.worker.core.processor.TaskContext; +import tech.powerjob.worker.core.processor.sdk.BasicProcessor; +import tech.powerjob.worker.log.OmsLogger; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.math.BigDecimal; +import java.net.URL; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Objects; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +@Component(value = "shipmentMaterialZipImportProcessor") +public class ShipmentMaterialZipImportProcessor implements BasicProcessor { + + @Resource + private IWmsShipmentMaterialService shipmentMaterialService; + + @Resource + private BomMaterialService bomMaterialService; + + @Resource + private FileUploadService fileUploadService; + + @Override + public ProcessResult process(TaskContext context) throws Exception { + OmsLogger omsLogger = context.getOmsLogger(); + List params = StrUtil.split(context.getInstanceParams(), "|"); + String zipUrl = CollectionUtil.get(params, 0); + String userName = CollectionUtil.get(params, 1); + if (StrUtil.isBlank(zipUrl)) { + omsLogger.error("无效的zip地址"); + return new ProcessResult(false, "无效的zip地址"); + } + try (InputStream is = new URL(zipUrl).openStream(); ZipInputStream zis = new ZipInputStream(is)) { + ZipEntry entry; + while ((entry = zis.getNextEntry()) != null) { + String name = entry.getName(); + omsLogger.info("开始处理文件:{}", name); + if (!entry.isDirectory()) { + ByteArrayOutputStream osOut = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + while ((len = zis.read(buffer)) > 0) { + osOut.write(buffer, 0, len); + } + String materialNo = name.substring(0, name.lastIndexOf(".")); + omsLogger.info("物料编号:{}", materialNo); + BomMaterialDTO bomMaterialDTO = bomMaterialService.getMaterialInfo(materialNo); + if (Objects.isNull(bomMaterialDTO)) { + omsLogger.error("主数据中未查找到该物料:{}", materialNo); + } else { + String picUrl = ""; + try (ByteArrayInputStream isIn = new ByteArrayInputStream(osOut.toByteArray())) { + picUrl = fileUploadService.upload(buildFilePath(name), isIn, MediaType.IMAGE_JPEG_VALUE); + omsLogger.info("上传后的图片地址:{}", picUrl); + } catch (Exception ex) { + omsLogger.error("上传图片失败:{}", ex.getMessage()); + } + WmsShipmentMaterial old = shipmentMaterialService.lambdaQuery() + .eq(WmsShipmentMaterial::getNo, materialNo) + .orderByDesc(WmsShipmentMaterial::getId) + .last("LIMIT 1") + .one(); + if (Objects.isNull(old) || StrUtil.isNotBlank(old.getImage())) { + omsLogger.info("添加老鼠图"); + WmsShipmentMaterial material = new WmsShipmentMaterial() + .setNo(bomMaterialDTO.getMaterialNo()) + .setDescribe(bomMaterialDTO.getMaterialDesc()) + .setDrawingNo(bomMaterialDTO.getDrawingNo()) + .setImage(picUrl) + .setWeight(BigDecimal.ZERO) + .setLength(BigDecimal.ZERO) + .setWidth(BigDecimal.ZERO) + .setHeight(BigDecimal.ZERO) + .setCreateBy(userName) + .setCreateTime(LocalDateTime.now()); + if (shipmentMaterialService.save(material)) { + omsLogger.info("保存成功,id:" + material.getId()); + } else { + omsLogger.error("保存失败"); + } + } else { + omsLogger.info("更新老鼠图"); + old.setImage(picUrl); + old.setUpdateBy(userName); + old.setUpdateTime(LocalDateTime.now()); + if (shipmentMaterialService.updateById(old)) { + omsLogger.info("更新成功,id:" + old.getId()); + } else { + omsLogger.error("更新失败"); + } + } + } + } + omsLogger.info("处理完毕"); + omsLogger.info("-----------------------------------------"); + zis.closeEntry(); + } + } + return new ProcessResult(true, "处理完毕"); + } + + private String buildFilePath(String fileName) { + String fileType = "." + FilenameUtils.getExtension(fileName); + return StrUtil.format("admin/task/{}/{}/{}{}", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + , RandomUtil.randomString(4), IdUtil.fastUUID(), fileType); + } +} diff --git a/nflg-wms-shipment/pom.xml b/nflg-wms-shipment/pom.xml index 1e278ecd..21493979 100644 --- a/nflg-wms-shipment/pom.xml +++ b/nflg-wms-shipment/pom.xml @@ -135,6 +135,21 @@ org.redisson redisson-spring-boot-starter + + com.alibaba + easyexcel + 3.3.4 + + + tech.powerjob + powerjob-client + + + checker-qual + org.checkerframework + + + diff --git a/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/config/PowerJobClientConfig.java b/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/config/PowerJobClientConfig.java new file mode 100644 index 00000000..921cce63 --- /dev/null +++ b/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/config/PowerJobClientConfig.java @@ -0,0 +1,27 @@ +package com.nflg.wms.shipment.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Lazy; +import tech.powerjob.client.PowerJobClient; + +@Configuration +@Lazy +public class PowerJobClientConfig { + + @Value("${powerjob.worker.server-address}") + private String serverAddress; + + @Value("${powerjob.worker.app-name}") + private String appName; + + @Value("${powerjob.client.password}") + private String password; + + @Bean + @Lazy + public PowerJobClient initPowerJobClient() { + return new PowerJobClient(serverAddress, appName, password); + } +} diff --git a/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/controller/MaterialController.java b/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/controller/MaterialController.java index b270a4c0..03dcf13a 100644 --- a/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/controller/MaterialController.java +++ b/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/controller/MaterialController.java @@ -16,17 +16,23 @@ import com.nflg.wms.common.util.UserUtil; import com.nflg.wms.common.util.VUtil; import com.nflg.wms.repository.entity.WmsShipmentMaterial; import com.nflg.wms.repository.service.IWmsShipmentMaterialService; +import com.nflg.wms.shipment.service.ShipmentMaterialControllerService; import com.nflg.wms.starter.BaseController; import com.nflg.wms.starter.service.BomMaterialService; import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PostMapping; 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.multipart.MultipartFile; +import java.io.IOException; import java.time.LocalDateTime; import java.util.List; import java.util.Map; @@ -45,6 +51,9 @@ public class MaterialController extends BaseController { @Resource private BomMaterialService bomMaterialService; + @Resource + private ShipmentMaterialControllerService shipmentMaterialControllerService; + /** * 新增图纸 */ @@ -188,4 +197,52 @@ public class MaterialController extends BaseController { shipmentMaterialService.remove(new LambdaQueryWrapper().in(WmsShipmentMaterial::getNo, nos)); return ApiResult.success(); } + + /** + * 导出选择的数据 + * @param ids id列表,为空时导出模板 + */ + @PostMapping("exportSelect") + public void exportSelect(HttpServletResponse response, @RequestBody(required = false) List ids) throws Exception { + shipmentMaterialControllerService.exportSelect(response, ids); + } + + /** + * 导出搜索结果 + * @param request 搜索参数 + */ + @PostMapping("exportSearch") + public void exportSearch(HttpServletResponse response, @Valid @RequestBody ShipmentMaterialSearchQO request) throws Exception { + shipmentMaterialControllerService.exportSearch(response, request); + } + + /** + * 导入 + * @param file 文件 + */ + @Transactional + @PostMapping("import") + public ApiResult importFromExcel(@RequestParam(value = "file") MultipartFile file) throws IOException { + return shipmentMaterialControllerService.importFromExcel(file); + } + + /** + * 批量上传物料图片 + * @param files 文件列表 + */ + @Transactional + @PostMapping("uploadPics") + public ApiResult uploadPics(@Valid @RequestParam("files") @NotEmpty List files) throws Exception { + return shipmentMaterialControllerService.uploadPics(files); + } + + /** + * 上传物料图片zip压缩包 + * @param file zip压缩包 + */ + @Transactional + @PostMapping("uploadZip") + public ApiResult uploadZip(@Valid @RequestParam("file") @NotNull MultipartFile file) throws Exception { + return shipmentMaterialControllerService.uploadZip(file); + } } diff --git a/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/service/ShipmentMaterialControllerService.java b/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/service/ShipmentMaterialControllerService.java new file mode 100644 index 00000000..f7b76595 --- /dev/null +++ b/nflg-wms-shipment/src/main/java/com/nflg/wms/shipment/service/ShipmentMaterialControllerService.java @@ -0,0 +1,377 @@ +package com.nflg.wms.shipment.service; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.core.util.StrUtil; +import com.nflg.wms.common.pojo.ApiResult; +import com.nflg.wms.common.pojo.dto.*; +import com.nflg.wms.common.pojo.qo.ShipmentMaterialSearchQO; +import com.nflg.wms.common.util.DateTimeUtil; +import com.nflg.wms.common.util.EecExcelUtil; +import com.nflg.wms.common.util.UserUtil; +import com.nflg.wms.common.util.VUtil; +import com.nflg.wms.repository.entity.WmsShipmentMaterial; +import com.nflg.wms.repository.service.IWmsShipmentMaterialService; +import com.nflg.wms.starter.service.BomMaterialService; +import com.nflg.wms.starter.service.FileUploadService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import org.ttzero.excel.entity.ListSheet; +import org.ttzero.excel.entity.Workbook; +import tech.powerjob.client.PowerJobClient; +import tech.powerjob.common.request.query.JobInfoQuery; +import tech.powerjob.common.response.JobInfoDTO; +import tech.powerjob.common.response.ResultDTO; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigDecimal; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +@Component +public class ShipmentMaterialControllerService { + + @Resource + private IWmsShipmentMaterialService shipmentMaterialService; + + @Resource + private BomMaterialService bomMaterialService; + + @Resource + private FileUploadService fileUploadService; + + @Resource + private PowerJobClient powerJobClient; + + /** + * 导出选择的数据 + * @param response HTTP响应 + * @param ids id列表,为空时导出模板 + */ + public void exportSelect(HttpServletResponse response, List ids) throws IOException { + if (CollectionUtil.isEmpty(ids)) { + exportTemplate(response); + } else { + List materials = shipmentMaterialService.listByIds(ids); + List datas = materials.stream() + .map(model -> Convert.convert(ShipmentMaterialExcelExportDTO.class, model)) + .collect(Collectors.toList()); + // 设置图片类型 + datas.forEach(dto -> { + if (StrUtil.isNotBlank(dto.getImage())) { + String image = dto.getImage(); + int lastDotIndex = image.lastIndexOf("."); + if (lastDotIndex > 0 && lastDotIndex < image.length() - 1) { + dto.setImageType(image.substring(lastDotIndex + 1)); + } + } + }); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode("老鼠图导出.xlsx", StandardCharsets.UTF_8)); + if (CollectionUtil.isEmpty(datas)) { + exportTemplate(response); + } else { + new Workbook() + .addSheet(new ListSheet<>(datas).setRowHeight(100)) + .writeTo(response.getOutputStream()); + } + } + } + + /** + * 导出模板 + */ + private void exportTemplate(HttpServletResponse response) throws IOException { + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode("老鼠图导入模板.xlsx", StandardCharsets.UTF_8)); + List datas = new ArrayList<>(); + datas.add(new ShipmentMaterialExcelTemplateExportDTO() + .setNo("") + .setWeight("") + .setLength("") + .setWidth("") + .setHeight("")); + new Workbook() + .addSheet(new ListSheet<>(datas)) + .writeTo(response.getOutputStream()); + } + + /** + * 导出搜索结果 + */ + public void exportSearch(HttpServletResponse response, @Valid ShipmentMaterialSearchQO request) throws IOException { + List list = shipmentMaterialService.lambdaQuery() + .like(StrUtil.isNotBlank(request.getNo()), WmsShipmentMaterial::getNo, request.getNo()) + .like(StrUtil.isNotBlank(request.getDescribe()), WmsShipmentMaterial::getDescribe, request.getDescribe()) + .like(StrUtil.isNotBlank(request.getDrawingNo()), WmsShipmentMaterial::getDrawingNo, request.getDrawingNo()) + .orderByDesc(WmsShipmentMaterial::getId) + .list(); + List datas = list.stream() + .map(model -> Convert.convert(ShipmentMaterialExcelExportDTO.class, model)) + .collect(Collectors.toList()); + // 设置图片类型 + datas.forEach(dto -> { + if (StrUtil.isNotBlank(dto.getImage())) { + String image = dto.getImage(); + int lastDotIndex = image.lastIndexOf("."); + if (lastDotIndex > 0 && lastDotIndex < image.length() - 1) { + dto.setImageType(image.substring(lastDotIndex + 1)); + } + } + }); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode("老鼠图导出.xlsx", StandardCharsets.UTF_8)); + new Workbook() + .addSheet(new ListSheet<>(datas).setRowHeight(100)) + .writeTo(response.getOutputStream()); + } + + /** + * 从Excel导入 + */ + @Transactional + public ApiResult importFromExcel(MultipartFile file) throws IOException { + List data = EecExcelUtil.getExcelContext(file.getInputStream(), ShipmentMaterialExcelImportDTO.class); + VUtil.trueThrowBusinessError(CollectionUtil.isEmpty(data)).throwMessage("导入文件内容为空"); + if (checkAndImport(data)) { + return ApiResult.success(); + } else { + try (ByteArrayOutputStream osOut = new ByteArrayOutputStream()) { + new Workbook() + .addSheet(new ListSheet<>(data)) + .writeTo(osOut); + try (ByteArrayInputStream isIn = new ByteArrayInputStream(osOut.toByteArray())) { + String errorFileUrl = fileUploadService.upload("temp/" + DateTimeUtil.format(LocalDate.now(), "yyyyMMdd") + "/" + IdUtil.fastUUID() + ".xlsx", isIn, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + return ApiResult.error("导入文件失败,错误文件:" + errorFileUrl); + } + } catch (Exception e) { + return ApiResult.error("保存文件出错"); + } + } + } + + /** + * 校验并导入数据 + */ + @Transactional + public boolean checkAndImport(List data) { + List forAdd = new ArrayList<>(); + List forUpdate = new ArrayList<>(); + + // 获取已存在的物料 + List materialNos = data.stream() + .map(ShipmentMaterialExcelImportDTO::getNo) + .filter(StrUtil::isNotBlank) + .distinct() + .collect(Collectors.toList()); + + List dbMaterials = CollectionUtil.isNotEmpty(materialNos) + ? shipmentMaterialService.lambdaQuery() + .in(WmsShipmentMaterial::getNo, materialNos) + .list() + : new ArrayList<>(); + + // 从BOM系统获取物料信息 + List bomMaterials = bomMaterialService.getList( + data.stream().map(ShipmentMaterialExcelImportDTO::getNo).collect(Collectors.toSet()) + ); + + for (ShipmentMaterialExcelImportDTO dto : data) { + StringBuilder sb = new StringBuilder(); + WmsShipmentMaterial material = new WmsShipmentMaterial(); + + // 校验物料编号 + if (StrUtil.isBlank(dto.getNo())) { + sb.append("物料编号不能为空;"); + } else { + BomMaterialDTO bomMaterial = bomMaterials.stream() + .filter(m -> StrUtil.equals(dto.getNo(), m.getMaterialNo())) + .findFirst() + .orElse(null); + + if (Objects.isNull(bomMaterial)) { + sb.append("物料编号无效;"); + } else { + WmsShipmentMaterial existingMaterial = dbMaterials.stream() + .filter(m -> StrUtil.equals(m.getNo(), dto.getNo())) + .findFirst() + .orElse(null); + + if (Objects.nonNull(existingMaterial)) { + material.setId(existingMaterial.getId()); + material.setUpdateBy(UserUtil.getUserName()); + material.setUpdateTime(LocalDateTime.now()); + forUpdate.add(material); + } else { + material.setCreateBy(UserUtil.getUserName()); + material.setCreateTime(LocalDateTime.now()); + forAdd.add(material); + } + + material.setNo(dto.getNo()); + material.setDescribe(bomMaterial.getMaterialDesc()); + material.setDescribeEn(bomMaterial.getMaterialDescEn()); + material.setDrawingNo(bomMaterial.getDrawingNo()); + } + } + + // 校验重量 + if (StrUtil.isNotBlank(dto.getWeight())) { + if (!NumberUtils.isCreatable(dto.getWeight())) { + sb.append("重量无效;"); + } else { + material.setWeight(new BigDecimal(dto.getWeight())); + } + } + + // 校验长度 + if (StrUtil.isNotBlank(dto.getLength())) { + if (!NumberUtils.isCreatable(dto.getLength())) { + sb.append("长度无效;"); + } else { + material.setLength(new BigDecimal(dto.getLength())); + } + } + + // 校验宽度 + if (StrUtil.isNotBlank(dto.getWidth())) { + if (!NumberUtils.isCreatable(dto.getWidth())) { + sb.append("宽度无效;"); + } else { + material.setWidth(new BigDecimal(dto.getWidth())); + } + } + + // 校验高度 + if (StrUtil.isNotBlank(dto.getHeight())) { + if (!NumberUtils.isCreatable(dto.getHeight())) { + sb.append("高度无效;"); + } else { + material.setHeight(new BigDecimal(dto.getHeight())); + } + } + + material.setImage(dto.getImage()); + dto.setError(sb.toString()); + } + + // 如果没有错误,执行保存 + if (data.stream().noneMatch(it -> StrUtil.isNotBlank(it.getError()))) { + if (CollectionUtil.isNotEmpty(forAdd)) { + shipmentMaterialService.saveBatch(forAdd, 1000); + } + if (CollectionUtil.isNotEmpty(forUpdate)) { + shipmentMaterialService.updateBatchById(forUpdate, 1000); + } + return true; + } + return false; + } + + /** + * 批量上传老鼠图 + */ + @Transactional + public ApiResult uploadPics(List files) throws Exception { + List pics = new ArrayList<>(); + List materials = new ArrayList<>(); + + for (MultipartFile file : files) { + String name = file.getOriginalFilename(); + VUtil.trueThrowBusinessError(StrUtil.isBlank(name)).throwMessage("文件名不能为空"); + + String materialNo = name.substring(0, name.lastIndexOf(".")); + BomMaterialDTO bomMaterialDTO = bomMaterialService.getMaterialInfo(materialNo); + + if (Objects.isNull(bomMaterialDTO)) { + pics.add(name); + } else { + String url = fileUploadService.upload(buildFilePath(name), file); + WmsShipmentMaterial existingMaterial = shipmentMaterialService.lambdaQuery() + .eq(WmsShipmentMaterial::getNo, materialNo) + .one(); + + if (Objects.isNull(existingMaterial) || StrUtil.isNotBlank(existingMaterial.getImage())) { + WmsShipmentMaterial material = new WmsShipmentMaterial() + .setNo(bomMaterialDTO.getMaterialNo()) + .setDescribe(bomMaterialDTO.getMaterialDesc()) + .setDescribeEn(bomMaterialDTO.getMaterialDescEn()) + .setDrawingNo(bomMaterialDTO.getDrawingNo()) + .setImage(url) + .setCreateBy(UserUtil.getUserName()) + .setCreateTime(LocalDateTime.now()); + materials.add(material); + } else { + existingMaterial.setImage(url); + existingMaterial.setUpdateBy(UserUtil.getUserName()); + existingMaterial.setUpdateTime(LocalDateTime.now()); + materials.add(existingMaterial); + } + } + } + + if (CollectionUtil.isEmpty(pics)) { + if (CollectionUtil.isNotEmpty(materials)) { + shipmentMaterialService.saveOrUpdateBatch(materials); + } + return ApiResult.success(); + } else { + return ApiResult.error("以下图片物料编号无效:" + StrUtil.join(",", pics)); + } + } + + /** + * 构建文件路径 + */ + private String buildFilePath(String fileName) { + String fileType = "." + FilenameUtils.getExtension(fileName); + return StrUtil.format("shipment/{}/{}/{}/{}{}", + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")), + UserUtil.getUserId(), + RandomUtil.randomString(4), + IdUtil.fastUUID(), + fileType); + } + + /** + * 上传老鼠图zip压缩包 + */ + @Transactional + public ApiResult uploadZip(@Valid @NotEmpty MultipartFile file) throws Exception { + String name = file.getOriginalFilename(); + VUtil.trueThrowBusinessError(!StrUtil.endWith(name, ".zip")).throwMessage("请上传zip格式的压缩包"); + String url = fileUploadService.upload(buildFilePath(name), file); + + JobInfoQuery query = new JobInfoQuery(); + query.setJobNameEq("老鼠图zip导入"); + ResultDTO> result = powerJobClient.queryJob(query); + + if (result.isSuccess()) { + powerJobClient.runJob(result.getData().get(0).getId(), + url + "|" + UserUtil.getUserName(), + 0); + return ApiResult.success("任务已提交"); + } else { + return ApiResult.error(result.getMessage()); + } + } +}