package com.baiyue.lastleg.relabel; import com.baiyue.lastleg.relabel.dto.RelabelRequests; import org.junit.jupiter.api.Test; import java.lang.reflect.RecordComponent; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; class RelabelContractTest { @Test void createHeaderDoesNotExposeWaybillLabelFileAndItemCarriesRequestedFileFields() { assertFalse(Arrays.stream(RelabelRequests.Create.class.getRecordComponents()) .map(RecordComponent::getName) .anyMatch(name -> name.toLowerCase().contains("waybill") || name.toLowerCase().contains("labelFile"))); assertTrue(Arrays.stream(RelabelRequests.Item.class.getRecordComponents()) .map(RecordComponent::getName).toList().containsAll(Arrays.asList("skuCode", "productImageFileId", "productNameZh", "totalPackageCount", "notifiedPackageCount", "shipmentNo", "trackingCode", "newSkuCode", "labelRequirement", "relabelFileId"))); } @Test void schemasDefineRelabelApplicationItemsAndHistoryContracts() throws Exception { String baseline = Files.readString(Path.of("src/main/resources/db/lastleg.sql"), StandardCharsets.UTF_8).toLowerCase(); String migration = Files.readString(Path.of("..", "scripts", "db", "incremental.sql"), StandardCharsets.UTF_8).toLowerCase(); String deployment = Files.readString(Path.of("..", "deploy", "sql", "海外区域统一增量-MySQL8.sql"), StandardCharsets.UTF_8).toLowerCase(); for (String schema : new String[] { baseline, migration }) { assertTrue(schema.contains("ll_relabel_application")); assertTrue(schema.contains("ll_relabel_item")); assertTrue(schema.contains("ll_relabel_status_history")); assertTrue(schema.contains("customer_id")); assertTrue(schema.contains("idempotency_key")); assertTrue(schema.contains("request_hash")); } for (String schema : new String[] { baseline, migration, deployment }) { assertTrue(schema.contains("ll_relabel_item")); assertTrue(schema.contains("remark")); assertTrue(schema.contains("carton_mark")); assertTrue(schema.contains("fba_carton_mark")); assertTrue(schema.contains("destination_warehouse_id")); } for (String field : new String[] { "source_inventory_balance_id", "source_inventory_position_id", "source_inbound_order_id", "source_inbound_order_no", "source_inbound_code", "source_warehouse_id", "source_warehouse_code", "source_warehouse_name", "idx_ll_relabel_item_source_position" }) { assertTrue(deployment.contains(field), () -> "deployment SQL must include " + field); } for (String field : new String[] { "delivery_method", "print_shipping_label", "shipping_label_file_id", "shipping_label_file_name", "shipping_label_file_url", "fulfillment_status", "outbound_order_no", "customer_confirmation_key", "customer_confirmed_at" }) { assertTrue(baseline.contains(field), () -> "baseline SQL must include " + field); assertTrue(migration.contains(field), () -> "migration SQL must include " + field); assertTrue(deployment.contains(field), () -> "deployment SQL must include " + field); } } @Test void openApiDocumentsAllRelabelApplicationOperations() throws Exception { String openApi = Files.readString(Path.of("src/main/resources/openapi/overseas-business-v1.yaml"), StandardCharsets.UTF_8); assertTrue(openApi.contains("/api/platform/v1/last-leg/relabel-applications:")); assertTrue(openApi.contains("/api/platform/v1/last-leg/relabel-applications/{relabelNo}:")); assertTrue(openApi.contains("/api/platform/v1/last-leg/relabel-applications/{relabelNo}/status:")); assertTrue(openApi.contains("RelabelCreate")); assertTrue(openApi.contains("RelabelStatusChange")); assertTrue(openApi.contains("platform:overseas-warehouse:relabel-order:list")); assertTrue(openApi.contains("platform:overseas-warehouse:relabel-order:create")); assertTrue(openApi.contains("platform:overseas-warehouse:relabel-order:status")); for (String path : new String[] { "/api/merchant/v1/last-leg/relabel-applications/inventory-candidates:", "/api/merchant/v1/last-leg/relabel-applications:", "/api/merchant/v1/last-leg/relabel-applications/{relabelNo}:", "/api/merchant/v1/last-leg/relabel-applications/{relabelNo}/shipping-label:", "/api/merchant/v1/last-leg/relabel-applications/{relabelNo}/shipping-label/{fileId}/download:", "/api/merchant/v1/last-leg/relabel-applications/{relabelNo}/completion-photos/{fileId}/download:", "/api/merchant/v1/last-leg/relabel-applications/{relabelNo}/confirm-completion:" }) { assertTrue(openApi.contains(path), () -> "merchant relabel path missing: " + path); } assertTrue(openApi.contains("RelabelMerchantPageResponse")); assertTrue(openApi.contains("RelabelCustomerConfirm")); assertTrue(openApi.contains("merchant:warehouse:relabel")); String relabelPaths = openApi.substring(openApi.indexOf("/api/platform/v1/last-leg/relabel-applications:"), openApi.indexOf("components:")); assertTrue(relabelPaths.contains("name: customerId, in: query, required: true")); String relabelCreate = openApi.substring(openApi.indexOf(" RelabelCreate:"), openApi.indexOf(" RelabelItem:")); assertFalse(relabelCreate.contains("customerId")); } }