From 87e65043f302af4980c94100fe1f73aa4ee35a53 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Thu, 10 Sep 2026 00:18:17 +0800 Subject: [PATCH] fix: treat overseas unload photos as platform evidence --- file/AGENTS.md | 2 +- .../com/baiyue/file/service/BusinessFileCategory.java | 6 +++--- .../file/service/InternalBusinessFileServiceTest.java | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/file/AGENTS.md b/file/AGENTS.md index bfa4e15d0..e432bb45e 100644 --- a/file/AGENTS.md +++ b/file/AGENTS.md @@ -15,7 +15,7 @@ | 测量图片/证据 | `controller/PlatformMeasurementImageController.java`、`InternalMeasurementImageController.java`、`service/MeasurementImageService.java` | | 平台订单商品图片读取 | `controller/PlatformProductImageController.java` 的 `/api/platform/v1/files/product-images/{tenantId}/{fileId}`、`service/ProductImageService.java`;仅平台 `platform:order:list` 可按明确客户与文件 ID 内联读取,响应 `no-store` | | 装柜与业务文件证据 | `controller/PlatformLoadingEvidenceController.java`、`InternalLoadingEvidenceController.java`、`service/LoadingEvidenceService.java`、`src/main/resources/openapi/loading-evidence-v1.yaml`;五类装柜证据固定为平台所有、`tenantId=0`、`businessId=containerBookingId`,不得绑定客户或入仓单。其他业务文件进入 `InternalBusinessFileController.java`、`service/InternalBusinessFileService.java` | -| 财务付款凭证、海外卸柜照片 | 通用业务文件入口 `InternalBusinessFileController.java`、`InternalBusinessFileService.java`;业务类型分别为 `FINANCE_VOUCHER`、`OVERSEAS_UNLOAD_PHOTO`,必须按客户与业务 ID 精确校验 | +| 财务付款凭证、海外卸柜照片 | 通用业务文件入口 `InternalBusinessFileController.java`、`InternalBusinessFileService.java`;`FINANCE_VOUCHER` 按客户与业务 ID 精确校验;`OVERSEAS_UNLOAD_PHOTO` 是多客户共享柜的物理证据,固定平台范围 `tenantId=0` 并按收货会话 ID 精确校验 | | 海外异常订单证据 | 通用内部业务文件入口;固定 `businessType=OVERSEAS_EXCEPTION_EVIDENCE`、`tenantId=异常订单所属客户ID`、`businessId=异常订单ID`,File 只校验文件复合归属,异常状态、完成门禁和证据引用归 Lastleg | | 海外换标 PDF 资料 | 通用内部业务文件入口,契约 `src/main/resources/openapi/overseas-relabel-document-v1.yaml`;`OVERSEAS_RELABEL_TOTAL_DOCUMENT` 按 `application.id`、`OVERSEAS_RELABEL_ITEM_DOCUMENT` 按 `item.id` 归属,必须指定明确客户与正数业务 ID;仅非空 PDF、最大 10MiB,校验 MIME 和文件签名。File 按客户、类型、业务 ID、文件 ID 复合校验,Lastleg 校验申请/明细关系、客户归属、权限和业务状态 | | 入库扣货凭证 | 通用内部业务文件入口;固定 `businessType=INBOUND_HOLD_EVIDENCE`、`tenantId=客户ID`、`businessId=入库单ID`,客户作用域单文件最多 10MiB;可见性与历史引用由 Firstleg 校验 | diff --git a/file/src/main/java/com/baiyue/file/service/BusinessFileCategory.java b/file/src/main/java/com/baiyue/file/service/BusinessFileCategory.java index a0caa102f..f308db828 100644 --- a/file/src/main/java/com/baiyue/file/service/BusinessFileCategory.java +++ b/file/src/main/java/com/baiyue/file/service/BusinessFileCategory.java @@ -22,7 +22,7 @@ enum BusinessFileCategory { LOADING_CUSTOMS_DECLARATION(false, FormatPolicy.STANDARD, Limits.STANDARD, BusinessIdPolicy.POSITIVE_LONG), CONTAINER_DELIVERY_ORDER(false, FormatPolicy.STANDARD, Limits.STANDARD, BusinessIdPolicy.POSITIVE_LONG), CONTAINER_PICKUP_ORDER(false, FormatPolicy.STANDARD, Limits.STANDARD, BusinessIdPolicy.POSITIVE_LONG), - OVERSEAS_UNLOAD_PHOTO(true, FormatPolicy.STANDARD, Limits.STANDARD, BusinessIdPolicy.POSITIVE_LONG), + OVERSEAS_UNLOAD_PHOTO(false, FormatPolicy.STANDARD, Limits.STANDARD, BusinessIdPolicy.POSITIVE_LONG), OVERSEAS_RELABEL_PHOTO(true, FormatPolicy.STANDARD, Limits.STANDARD, BusinessIdPolicy.POSITIVE_LONG), OVERSEAS_RELABEL_TOTAL_DOCUMENT(true, FormatPolicy.PDF, Limits.STANDARD, BusinessIdPolicy.POSITIVE_LONG), OVERSEAS_RELABEL_ITEM_DOCUMENT(true, FormatPolicy.PDF, Limits.STANDARD, BusinessIdPolicy.POSITIVE_LONG), @@ -55,8 +55,8 @@ enum BusinessFileCategory { } void validateOwner(long tenantId) { - if (this == OCEAN_BOOKING_DOCUMENT && tenantId != 0) { - throw new BizException(ResultCode.BAD_REQUEST, "订舱附件必须归属平台"); + if ((this == OCEAN_BOOKING_DOCUMENT || this == OVERSEAS_UNLOAD_PHOTO) && tenantId != 0) { + throw new BizException(ResultCode.BAD_REQUEST, "该附件类型必须归属平台"); } if (customerOwned && tenantId <= 0) { throw new BizException(ResultCode.BAD_REQUEST, "该附件类型必须归属明确客户"); diff --git a/file/src/test/java/com/baiyue/file/service/InternalBusinessFileServiceTest.java b/file/src/test/java/com/baiyue/file/service/InternalBusinessFileServiceTest.java index 9da25ae57..acc3bd48b 100644 --- a/file/src/test/java/com/baiyue/file/service/InternalBusinessFileServiceTest.java +++ b/file/src/test/java/com/baiyue/file/service/InternalBusinessFileServiceTest.java @@ -44,8 +44,6 @@ class InternalBusinessFileServiceTest { when(storage.store(eq(0L), anyString(), same(file), any(BusinessFileCategory.class))).thenAnswer(invocation -> new BusinessFileStorage.Stored("business-files/0/" + invocation.getArgument(1) + "/customs.pdf", "application/pdf", file.getSize(), "b".repeat(64), "customs.pdf")); - when(storage.store(11L, "51", file, BusinessFileCategory.OVERSEAS_UNLOAD_PHOTO)).thenReturn(new BusinessFileStorage.Stored( - "business-files/11/51/unload.jpg", "image/jpeg", file.getSize(), "c".repeat(64), "unload.jpg")); when(files.insert(any(FileObjectEntity.class))).thenAnswer(invocation -> { ((FileObjectEntity) invocation.getArgument(0)).setId(81L); return 1; }); @@ -54,7 +52,7 @@ class InternalBusinessFileServiceTest { var customs = service.upload(0L, "LOADING_CUSTOMS_DECLARATION", "51", 7L, file); var deliveryOrder = service.upload(0L, "CONTAINER_DELIVERY_ORDER", "41", 7L, file); var pickupOrder = service.upload(0L, "CONTAINER_PICKUP_ORDER", "41", 7L, file); - var unloadPhoto = service.upload(11L, "OVERSEAS_UNLOAD_PHOTO", "51", 7L, file); + var unloadPhoto = service.upload(0L, "OVERSEAS_UNLOAD_PHOTO", "51", 7L, file); assertThat(clearance).extracting(InternalBusinessFileService.Metadata::tenantId, InternalBusinessFileService.Metadata::businessType, @@ -67,12 +65,14 @@ class InternalBusinessFileServiceTest { assertThat(unloadPhoto).extracting(InternalBusinessFileService.Metadata::tenantId, InternalBusinessFileService.Metadata::businessType, InternalBusinessFileService.Metadata::businessId) - .containsExactly(11L, "OVERSEAS_UNLOAD_PHOTO", "51"); + .containsExactly(0L, "OVERSEAS_UNLOAD_PHOTO", "51"); verify(storage).store(0L, "41", file, BusinessFileCategory.CONTAINER_CLEARANCE_DOCUMENT); verify(storage).store(0L, "51", file, BusinessFileCategory.LOADING_CUSTOMS_DECLARATION); verify(storage).store(0L, "41", file, BusinessFileCategory.CONTAINER_DELIVERY_ORDER); verify(storage).store(0L, "41", file, BusinessFileCategory.CONTAINER_PICKUP_ORDER); - verify(storage).store(11L, "51", file, BusinessFileCategory.OVERSEAS_UNLOAD_PHOTO); + verify(storage).store(0L, "51", file, BusinessFileCategory.OVERSEAS_UNLOAD_PHOTO); + assertThatThrownBy(() -> service.upload(11L, "OVERSEAS_UNLOAD_PHOTO", "51", 7L, file)) + .isInstanceOf(BizException.class).hasMessageContaining("必须归属平台"); } @Test void oceanBookingDocumentUsesPlatformAndBookingOwnership() {