diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/MaterialController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/MaterialController.java index c8010bcf..661959ce 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/MaterialController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/MaterialController.java @@ -1,6 +1,7 @@ package com.nflg.wms.admin.controller; import com.nflg.wms.admin.service.MaterialControllerService; +import com.nflg.wms.common.constant.STATE; import com.nflg.wms.common.constant.UserType; import com.nflg.wms.common.pojo.ApiResult; import com.nflg.wms.common.pojo.PageData; @@ -19,6 +20,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -31,6 +33,7 @@ import java.util.Set; /** * 图纸管理 */ +@Slf4j @RestController @RequestMapping("/material") public class MaterialController extends BaseController { @@ -182,7 +185,28 @@ public class MaterialController extends BaseController { */ @PostMapping("/mpm/syncFromMpmBatch") public ApiResult syncFromMpmBatch(/*@Valid */@RequestBody @NotEmpty List requests) { - materialControllerService.syncFromMpmBatch(requests); - return ApiResult.success(); + StringBuilder errorMessages = new StringBuilder(); + int successCount = 0; + int failCount = 0; + + for (MaterialAddQO request : requests) { + try { + materialControllerService.syncFromMpm(request); + successCount++; + } catch (Exception e) { + failCount++; + String errorMsg = String.format("[%s] %s; ", request.getNo(), e.getMessage()); + errorMessages.append(errorMsg); + log.error("同步图纸失败: {}, 错误: {}", request.getNo(), e.getMessage(), e); + } + } + + if (failCount > 0) { + String resultMsg = String.format("批量同步完成,成功%d条,失败%d条。失败详情: %s", + successCount, failCount, errorMessages.toString()); + return ApiResult.error(STATE.BusinessError, resultMsg); + } else { + return ApiResult.success(); + } } } diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/StructuralPackageController.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/StructuralPackageController.java index 65a6616a..332d52ce 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/StructuralPackageController.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/controller/StructuralPackageController.java @@ -1,6 +1,7 @@ package com.nflg.wms.admin.controller; import com.nflg.wms.admin.service.StructuralPackageControllerService; +import com.nflg.wms.common.constant.STATE; import com.nflg.wms.common.pojo.ApiResult; import com.nflg.wms.common.pojo.PageData; import com.nflg.wms.common.pojo.dto.PackageMaterialDTO; @@ -13,6 +14,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; +import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -23,6 +25,7 @@ import java.util.List; /** * 钢构包管理 */ +@Slf4j @RestController @RequestMapping("/package") public class StructuralPackageController extends BaseController { @@ -144,8 +147,13 @@ public class StructuralPackageController extends BaseController { */ @PostMapping("/mpm/syncFromMpm") public ApiResult syncFromMpm(/*@Valid */@RequestBody PackageAddQO request) { - packageControllerService.syncFromMpm(request); - return ApiResult.success(); + try { + packageControllerService.syncFromMpm(request); + return ApiResult.success(); + } catch (Exception e) { + log.error("从MPM系统同步钢构包数据失败: {}, 错误: {}", request.getNo(), e.getMessage(), e); + return ApiResult.error(STATE.BusinessError, "同步失败: " + e.getMessage()); + } } /** @@ -153,8 +161,29 @@ public class StructuralPackageController extends BaseController { */ @PostMapping("/mpm/syncFromMpmBatch") public ApiResult syncFromMpmBatch(/*@Valid */@RequestBody @NotEmpty List requests) { - packageControllerService.syncFromMpmBatch(requests); - return ApiResult.success(); + StringBuilder errorMessages = new StringBuilder(); + int successCount = 0; + int failCount = 0; + + for (PackageAddQO request : requests) { + try { + packageControllerService.syncFromMpm(request); + successCount++; + } catch (Exception e) { + failCount++; + String errorMsg = String.format("[%s] %s; ", request.getNo(), e.getMessage()); + errorMessages.append(errorMsg); + log.error("同步钢构包失败: {}, 错误: {}", request.getNo(), e.getMessage(), e); + } + } + + if (failCount > 0) { + String resultMsg = String.format("批量同步完成,成功%d条,失败%d条。失败详情: %s", + successCount, failCount, errorMessages.toString()); + return ApiResult.error(STATE.BusinessError, resultMsg); + } else { + return ApiResult.success(); + } } // // /** diff --git a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/MaterialControllerService.java b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/MaterialControllerService.java index 648c5749..5823d638 100644 --- a/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/MaterialControllerService.java +++ b/nflg-wms-admin/src/main/java/com/nflg/wms/admin/service/MaterialControllerService.java @@ -32,10 +32,16 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import org.ttzero.excel.entity.ListSheet; import org.ttzero.excel.entity.Workbook; @@ -56,6 +62,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; @@ -81,6 +88,12 @@ public class MaterialControllerService { @Resource private IUserSupplierService userSupplierService; + @Resource + private RestTemplate restTemplate; + + @Value("${mpm.download.url}") + private String mpmDownloadUrl; + public void add(@Valid MaterialAddQO request) { WmsMaterial old = materialService.getCurrent(request.getNo()); VUtil.trueThrowBusinessError(Objects.nonNull(old) && !old.getComplete()) @@ -415,33 +428,141 @@ public class MaterialControllerService { } /** - * 批量从MPM系统同步图纸数据 + * 从MPM系统同步图纸数据(单个) * 每次推送都是新版本,直接新增 */ - @Transactional - public void syncFromMpmBatch(@Valid @NotEmpty List requests) { - log.info("开始批量从MPM系统同步图纸数据,共{}条", requests.size()); + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void syncFromMpm(@Valid MaterialAddQO request) { + log.info("开始从MPM系统同步图纸数据: {}", request.getNo()); - for (MaterialAddQO request : requests) { + WmsMaterial wmsMaterial = Convert.convert(WmsMaterial.class, request); + wmsMaterial.setCreateBy("MPM_SYNC"); + wmsMaterial.setCreateTime(LocalDateTime.now()); + wmsMaterial.setFromMpm(true); // 标记为来自MPM + + // 如果fileindex和filename都不为空,则从MPM下载文件并上传到本系统 + if (StrUtil.isNotBlank(request.getFileindex()) && StrUtil.isNotBlank(request.getFilename())) { try { - log.info("开始从MPM系统同步图纸数据: {}", request.getNo()); - - WmsMaterial wmsMaterial = Convert.convert(WmsMaterial.class, request); - - wmsMaterial.setCreateBy("MPM_SYNC"); - wmsMaterial.setCreateTime(LocalDateTime.now()); - wmsMaterial.setFromMpm(true); // 标记为来自MPM - - materialService.add(wmsMaterial); - - log.info("成功从MPM系统同步图纸数据: {}, 版本: {}", request.getNo(), wmsMaterial.getVersion()); + String fileUrl = downloadAndUploadFileFromMpm(request.getFileindex(), request.getFilename()); + if (StrUtil.isNotBlank(fileUrl)) { + wmsMaterial.setImage(fileUrl); + log.info("成功从MPM下载并上传文件: {}, 文件URL: {}", request.getNo(), fileUrl); + } else { + log.warn("从MPM下载文件失败,但继续同步图纸数据: {}", request.getNo()); + } } catch (Exception e) { - log.error("同步图纸失败: {}, 错误: {}", request.getNo(), e.getMessage(), e); - // 继续处理下一条,不中断整个批量同步 + log.error("从MPM下载并上传文件失败: {}, 错误: {}", request.getNo(), e.getMessage(), e); + // 文件下载失败不影响主流程,继续同步其他数据 } } - log.info("批量从MPM系统同步图纸数据完成"); + materialService.add(wmsMaterial); + + log.info("成功从MPM系统同步图纸数据: {}, 版本: {}", request.getNo(), wmsMaterial.getVersion()); + } + + /** + * 从MPM系统下载文件并上传到本系统 + * + * @param fileindex 文件索引 + * @param filename 文件名 + * @return 上传后的文件URL + */ + private String downloadAndUploadFileFromMpm(String fileindex, String filename) { + try { + // 构建MPM下载请求URL + String mpmRequestUrl = mpmDownloadUrl + "/" + filename + "," + fileindex; + log.info("请求MPM文件下载地址: {}", mpmRequestUrl); + + // 发送GET请求获取文件下载地址 + ResponseEntity> response = restTemplate.exchange( + mpmRequestUrl, + HttpMethod.GET, + null, + new ParameterizedTypeReference>() {} + ); + + Map responseBody = response.getBody(); + if (responseBody != null && Boolean.TRUE.equals(responseBody.get("success"))) { + Map data = (Map) responseBody.get("data"); + if (data != null && data.containsKey(filename)) { + String downloadUrl = data.get(filename); + log.info("获取到MPM文件下载地址: {}", downloadUrl); + + // 下载文件内容 + ResponseEntity fileResponse = restTemplate.exchange( + downloadUrl, + HttpMethod.GET, + null, + byte[].class + ); + + if (fileResponse.getStatusCode().is2xxSuccessful() && fileResponse.getBody() != null) { + byte[] fileContent = fileResponse.getBody(); + + // 生成文件路径 + String filePath = buildFilePathForMpm(filename); + + // 上传到本系统 + String uploadUrl = fileUploadService.upload( + filePath, + new java.io.ByteArrayInputStream(fileContent), + getContentType(filename) + ); + + log.info("文件上传成功,URL: {}", uploadUrl); + return uploadUrl; + } else { + log.error("从MPM下载文件失败,状态码: {}", fileResponse.getStatusCode()); + } + } else { + log.error("MPM响应中未找到文件下载地址: {}", filename); + } + } else { + log.error("MPM请求失败: {}", responseBody != null ? responseBody.get("message") : "未知错误"); + } + } catch (Exception e) { + log.error("从MPM下载并上传文件异常: fileindex={}, filename={}, 错误: {}", fileindex, filename, e.getMessage(), e); + } + + return null; + } + + /** + * 根据文件名生成文件路径 + * + * @param fileName 文件名 + * @return 文件路径 + */ + private String buildFilePathForMpm(String fileName) { + String fileType = "." + FilenameUtils.getExtension(fileName); + return StrUtil.format("admin/{}/{}/{}/{}{}", + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")), + "MPM_SYNC", + RandomUtil.randomString(4), + IdUtil.fastUUID(), + fileType); + } + + /** + * 根据文件扩展名获取Content-Type + * + * @param fileName 文件名 + * @return Content-Type + */ + private String getContentType(String fileName) { + String extension = FilenameUtils.getExtension(fileName).toLowerCase(); + return switch (extension) { + case "pdf" -> "application/pdf"; + case "jpg", "jpeg" -> "image/jpeg"; + case "png" -> "image/png"; + case "gif" -> "image/gif"; + case "doc" -> "application/msword"; + case "docx" -> "application/vnd.openxmlformats-officedocument.wordprocessingml.document"; + case "xls" -> "application/vnd.ms-excel"; + case "xlsx" -> "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"; + default -> "application/octet-stream"; + }; } /** diff --git a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/MaterialAddQO.java b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/MaterialAddQO.java index 6114ff31..a5f4f489 100644 --- a/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/MaterialAddQO.java +++ b/nflg-wms-common/src/main/java/com/nflg/wms/common/pojo/qo/MaterialAddQO.java @@ -76,4 +76,8 @@ public class MaterialAddQO { * 版本号 */ private String version; + + private String filename; + + private String fileindex; }