package com.baiyue.common.event; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.List; /** 装柜完成 V3:在 V2 货物快照上增加整柜五类国内装柜照片引用。 */ public record FirstLegLoadingPlanCompletedV3( String loadingPlanId, String planNo, @JsonProperty("sourceContainerBookingId") String containerBookingId, String containerNo, String cabinetNo, String warehouseId, String warehouseName, String estimatedPortArrivalAt, String actualPortArrivalAt, String estimatedWarehouseArrivalAt, List orders, List loadingEvidence) { public FirstLegLoadingPlanCompletedV3 { if (loadingPlanId == null || loadingPlanId.isBlank() || containerBookingId == null || containerBookingId.isBlank()) { throw new IllegalArgumentException("loadingPlanId and sourceContainerBookingId are required"); } containerNo = ContainerNumbers.requireCanonical(containerNo); orders = orders == null ? List.of() : List.copyOf(orders); loadingEvidence = loadingEvidence == null ? List.of() : List.copyOf(loadingEvidence); if (orders.isEmpty()) throw new IllegalArgumentException("orders are required"); var owner = orders.get(0); if (orders.stream().anyMatch(order -> !owner.customerId().equals(order.customerId()) || !owner.customerName().equals(order.customerName()))) { throw new IllegalArgumentException("orders must share one immutable customerId/customerName snapshot"); } if (loadingEvidence.size() != 5 || loadingEvidence.stream().map(LoadingEvidence::evidenceType).distinct().count() != 5) { throw new IllegalArgumentException("five unique loading evidence types are required"); } } public record LoadingEvidence(String evidenceType, long fileId, String fileName) { public LoadingEvidence { if (evidenceType == null || !evidenceType.matches("PHOTO_STEP_[1-4]|SEAL")) { throw new IllegalArgumentException("unsupported loading evidence type"); } if (fileId <= 0) throw new IllegalArgumentException("loading evidence fileId must be positive"); if (fileName == null || fileName.isBlank() || fileName.length() > 255) { throw new IllegalArgumentException("loading evidence fileName is required"); } fileName = fileName.trim(); } } }