fix(phase4): enforce customer and pallet versions

This commit is contained in:
2026-08-24 15:14:18 +08:00
parent e773816c98
commit 95b72afdcc
12 changed files with 82 additions and 31 deletions
@@ -25,9 +25,10 @@ public class RelabelApplicationController {
@PreAuthorize("hasAuthority('" + OverseasPermissions.RELABEL_ORDER_CREATE + "')")
@Operation(summary = "Create a relabel application", description = "Required authority: " + OverseasPermissions.RELABEL_ORDER_CREATE)
public ApiResponse<RelabelResponses.Detail> create(@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam String customerId,
@Valid @RequestBody RelabelRequests.Create request) {
requirePlatform(user);
return ApiResponse.success(service.create(requiredCustomer(request.customerId()), operator(user), request));
return ApiResponse.success(service.create(requiredCustomer(customerId), operator(user), request));
}
@GetMapping
@PreAuthorize("hasAuthority('" + OverseasPermissions.RELABEL_ORDER_LIST + "')")
@@ -16,7 +16,6 @@ public final class RelabelRequests {
private RelabelRequests() {}
public record Create(
@Size(max = 32) String customerId,
@NotBlank @Size(max = 128) String customerOrderNo,
@NotBlank @Size(max = 128) String overseasWarehouseId,
@NotNull LocalDateTime labelDeadline,
@@ -317,6 +317,8 @@ paths:
summary: 创建海外换标单
description: 权限 platform:overseas-warehouse:relabel-order:create;明细与换标文件按请求快照保存,使用 idempotencyKey 幂等。
security: [{ bearerAuth: [] }]
parameters:
- { name: customerId, in: query, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } }
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelCreate' } } } }
responses: { '200': { description: 统一 ApiResponse 包装的换标单详情 }, '409': { description: 幂等键冲突 } }
/api/platform/v1/last-leg/relabel-applications/{relabelNo}:
@@ -466,9 +468,8 @@ components:
RelabelStatus: { type: string, enum: [PENDING_PROCESSING, PROCESSING, COMPLETED, REJECTED, CANCELLED] }
RelabelCreate:
type: object
required: [customerId, customerOrderNo, overseasWarehouseId, labelDeadline, contactName, contactPhone, idempotencyKey, items]
required: [customerOrderNo, overseasWarehouseId, labelDeadline, contactName, contactPhone, idempotencyKey, items]
properties:
customerId: { type: string, maxLength: 32, description: Target customer ID required by the platform create endpoint }
customerOrderNo: { type: string, maxLength: 128 }
overseasWarehouseId: { type: string, maxLength: 128 }
labelDeadline: { type: string, format: date-time }
@@ -21,21 +21,21 @@ class RelabelApplicationControllerTest {
@Test
void platformCreateUsesExplicitTargetCustomer() {
RelabelRequests.Create request = request("190000000000000001");
RelabelRequests.Create request = request();
controller.create(platform(), request);
controller.create(platform(), "190000000000000001", request);
verify(service).create("190000000000000001", "7", request);
}
@Test
void platformCreateRejectsMissingOrPlatformCustomer() {
assertThrows(ResponseStatusException.class, () -> controller.create(platform(), request(null)));
assertThrows(ResponseStatusException.class, () -> controller.create(platform(), request("0")));
assertThrows(ResponseStatusException.class, () -> controller.create(platform(), null, request()));
assertThrows(ResponseStatusException.class, () -> controller.create(platform(), "0", request()));
}
private RelabelRequests.Create request(String customerId) {
return new RelabelRequests.Create(customerId, "CUSTOMER-1", "WH-1",
private RelabelRequests.Create request() {
return new RelabelRequests.Create("CUSTOMER-1", "WH-1",
LocalDateTime.of(2026, 8, 20, 10, 0), "Li", "13800000000", null, "key-1",
List.of(new RelabelRequests.Item("SKU-A", null, null, null, "Product", 1, 1,
"SHIP-1", null, "SKU-B", "Replace", null, null, null)));
@@ -212,7 +212,7 @@ class RelabelApplicationServiceTest {
}
private static RelabelRequests.Create request(String key, int total, int notified) {
return new RelabelRequests.Create(null, "CUSTOMER-1", "WH-1", LocalDateTime.of(2026, 8, 20, 10, 0),
return new RelabelRequests.Create("CUSTOMER-1", "WH-1", LocalDateTime.of(2026, 8, 20, 10, 0),
"Li", "13800000000", "remark", key, List.of(new RelabelRequests.Item("SKU-A", "img-1",
"image.png", "https://files/image.png", "Chinese name", total, notified, "SHP-1", "TRACK-1",
"SKU-NEW", "Label on carton", "file-1", "relabel.pdf", "https://files/relabel.pdf")));
@@ -92,7 +92,7 @@ class TaillegRealConsumerAcceptanceTest {
if (!exists("ll_relabel_application", MARKER + "-RELABEL-KEY")) {
relabel.create(CUSTOMER, "real-acceptance", new RelabelRequests.Create(
null, MARKER + "-RELABEL", "92", RELABEL_DEADLINE, "验收联系人", "13800000000",
MARKER + "-RELABEL", "92", RELABEL_DEADLINE, "验收联系人", "13800000000",
MARKER, MARKER + "-RELABEL-KEY", List.of(new RelabelRequests.Item("SKU-REAL-A", null, null,
null, "真实验收商品", 3, 3, MARKER + "-SHIP", MARKER + "-TRACK", "SKU-REAL-A-NEW",
"换标验收", null, null, null))));