装柜回归测试
This commit is contained in:
@@ -12,7 +12,7 @@ import java.time.LocalDateTime;
|
||||
public record UnifiedOrderQuery(
|
||||
@Size(max = 64) String keyword,
|
||||
@Size(max = 64) String orderNo,
|
||||
@Schema(allowableValues = {"PENDING_REVIEW", "WAIT_MEASURE", "INBOUNDED", "WAIT_SPLIT",
|
||||
@Schema(allowableValues = {"PENDING_REVIEW", "WAIT_MEASURE", "INBOUNDED",
|
||||
"LOADING", "LOADED", "DELIVERED"})
|
||||
@Size(max = 32) String mainStatus,
|
||||
Long customerId,
|
||||
|
||||
@@ -78,37 +78,6 @@ public class OrderMasterDataGuard {
|
||||
throw downstreamFailure(exception);
|
||||
}
|
||||
}
|
||||
public PartnerClient.Partner validateCarrier(long id) {
|
||||
try {
|
||||
ApiResponse<PartnerClient.Partner> response;
|
||||
try {
|
||||
response = partners.active(token, publicTenantId, id);
|
||||
} catch (FeignException.NotFound exception) {
|
||||
throw new BizException(ResultCode.NOT_FOUND, "承运商不存在或不可用");
|
||||
}
|
||||
requireSuccessful(response, "承运商");
|
||||
if (response.data() == null) throw unavailable("承运商");
|
||||
var value = response.data();
|
||||
if (!Long.valueOf(id).equals(value.id())) throw unavailable("承运商");
|
||||
if (!Long.valueOf(publicTenantId).equals(value.tenantId()))
|
||||
throw new BizException(ResultCode.FORBIDDEN, "承运商不属于平台公共主数据");
|
||||
if (!"ACTIVE".equals(value.status()))
|
||||
throw new BizException(ResultCode.CONFLICT, "承运商已停用");
|
||||
boolean hasCarrierType = value.types() != null && value.types().contains("CARRIER");
|
||||
boolean legacyCarrierType = (value.types() == null || value.types().isEmpty())
|
||||
&& "CARRIER".equals(value.partnerType());
|
||||
if (!hasCarrierType && !legacyCarrierType)
|
||||
throw new BizException(ResultCode.VALIDATION_FAILED, "所选往来单位不具备承运商类型");
|
||||
if (!StringUtils.hasText(value.partnerName())) throw unavailable("承运商");
|
||||
return value;
|
||||
} catch (FeignException exception) {
|
||||
throw downstreamFailure(exception);
|
||||
} catch (BizException exception) {
|
||||
throw exception;
|
||||
} catch (RuntimeException exception) {
|
||||
throw downstreamFailure(exception);
|
||||
}
|
||||
}
|
||||
private PartnerClient.Partner loadPartner(long id) {
|
||||
ApiResponse<PartnerClient.Partner> response;
|
||||
try {
|
||||
|
||||
@@ -31,7 +31,8 @@ import java.util.stream.Collectors;
|
||||
@Service
|
||||
public class UnifiedOrderQueryService {
|
||||
private static final Set<String> MAIN_STATUSES = Set.of(
|
||||
"PENDING_REVIEW", "WAIT_MEASURE", "INBOUNDED", "WAIT_SPLIT", "LOADING", "LOADED", "DELIVERED");
|
||||
"PENDING_REVIEW", "WAIT_MEASURE", "INBOUNDED", "LOADING", "LOADED", "DELIVERED");
|
||||
private static final String LEGACY_WAIT_SPLIT = "WAIT_SPLIT";
|
||||
private static final Set<String> REVIEW_STATUSES = Set.of("UNRECORDED", "PENDING", "APPROVED", "REJECTED");
|
||||
private static final List<OrderStatus> ACTIVE_ORDER_STATUSES = List.copyOf(EnumSet.of(
|
||||
OrderStatus.SUBMITTED, OrderStatus.APPROVED, OrderStatus.ACCEPTED,
|
||||
@@ -92,7 +93,7 @@ public class UnifiedOrderQueryService {
|
||||
return new PageResult<>(List.of(), query.page(), query.size(), 0, 0);
|
||||
}
|
||||
FirstlegUnifiedOrderClient.Query request = new FirstlegUnifiedOrderClient.Query(
|
||||
tenantId, query.keyword(), query.orderNo(), query.mainStatus(), query.customerId(),
|
||||
tenantId, query.keyword(), query.orderNo(), canonicalMainStatus(query.mainStatus()), query.customerId(),
|
||||
query.receivingWarehouseId(), query.destinationWarehouseId(), query.inboundCode(),
|
||||
query.internalOrderStatus(), query.expectedArrivalDate(), query.feeReviewStatus(), query.channelName(),
|
||||
query.containerNo(), query.cabinetNo(), query.sailingDate(), query.loaded(), query.fullContainer(),
|
||||
@@ -199,8 +200,7 @@ public class UnifiedOrderQueryService {
|
||||
if (status == null) return null;
|
||||
return switch (status) {
|
||||
case "WAIT_MEASURE", "MEASURING", "MEASURE_PENDING", "MEASURE_REJECTED" -> "WAIT_MEASURE";
|
||||
case "WAIT_PRICING", "FEE_CONFIRMING", "INBOUNDING", "INBOUNDED" -> "INBOUNDED";
|
||||
case "WAIT_SPLIT" -> "WAIT_SPLIT";
|
||||
case "WAIT_PRICING", "FEE_CONFIRMING", "INBOUNDING", "INBOUNDED", LEGACY_WAIT_SPLIT -> "INBOUNDED";
|
||||
case "LOADING", "LOADED", "DELIVERED" -> status;
|
||||
default -> null;
|
||||
};
|
||||
@@ -211,7 +211,9 @@ public class UnifiedOrderQueryService {
|
||||
}
|
||||
|
||||
private void validate(UnifiedOrderQuery query) {
|
||||
if (StringUtils.hasText(query.mainStatus()) && !MAIN_STATUSES.contains(query.mainStatus())) {
|
||||
if (StringUtils.hasText(query.mainStatus())
|
||||
&& !MAIN_STATUSES.contains(query.mainStatus())
|
||||
&& !LEGACY_WAIT_SPLIT.equals(query.mainStatus())) {
|
||||
throw new BizException(ResultCode.BAD_REQUEST, "统一订单主状态不合法");
|
||||
}
|
||||
if (query.createdFrom() != null && query.createdTo() != null
|
||||
@@ -241,6 +243,10 @@ public class UnifiedOrderQueryService {
|
||||
|| StringUtils.hasText(query.measurementReviewStatus());
|
||||
}
|
||||
|
||||
private static String canonicalMainStatus(String status) {
|
||||
return LEGACY_WAIT_SPLIT.equals(status) ? "INBOUNDED" : status;
|
||||
}
|
||||
|
||||
private <T> ApiResponse<T> call(java.util.concurrent.Callable<ApiResponse<T>> invocation) {
|
||||
try { return invocation.call(); }
|
||||
catch (FeignException exception) { throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "头程服务暂时不可用"); }
|
||||
|
||||
@@ -311,7 +311,7 @@ components:
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
enum: [PENDING_REVIEW, WAIT_MEASURE, INBOUNDED, WAIT_SPLIT, LOADING, LOADED, DELIVERED]
|
||||
enum: [PENDING_REVIEW, WAIT_MEASURE, INBOUNDED, LOADING, LOADED, DELIVERED]
|
||||
UnifiedInboundCode:
|
||||
{name: inboundCode, in: query, required: false, description: 客户提交后生成的入仓码,待审核订单同样可查询, schema: {type: string, maxLength: 40}}
|
||||
UnifiedInternalOrderStatus:
|
||||
|
||||
@@ -25,7 +25,7 @@ class UnifiedOrderApiContractTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void documentsPhaseTwoWaitSplitStatus() throws Exception {
|
||||
void documentsInboundedAsThePhaseTwoTerminalStatus() throws Exception {
|
||||
String yaml = new ClassPathResource("openapi/order-v1.yaml")
|
||||
.getContentAsString(StandardCharsets.UTF_8);
|
||||
Map<String, Object> document = stringMap(new Yaml().load(yaml));
|
||||
@@ -39,8 +39,7 @@ class UnifiedOrderApiContractTest {
|
||||
Map<String, Object> mainStatus = stringMap(parameters.get("UnifiedMainStatus"));
|
||||
Map<String, Object> schema = stringMap(mainStatus.get("schema"));
|
||||
assertThat(stringList(schema.get("enum"))).containsExactly(
|
||||
"PENDING_REVIEW", "WAIT_MEASURE", "INBOUNDED", "WAIT_SPLIT",
|
||||
"LOADING", "LOADED", "DELIVERED");
|
||||
"PENDING_REVIEW", "WAIT_MEASURE", "INBOUNDED", "LOADING", "LOADED", "DELIVERED");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -45,31 +45,6 @@ class OrderMasterDataGuardTest {
|
||||
assertThat(result.receiving().warehouse().warehouseName()).isEqualTo("深圳仓");
|
||||
}
|
||||
@Test
|
||||
void carrierValidationReturnsTrustedPublicCarrierSnapshot() {
|
||||
var carrier = new PartnerClient.Partner(9L, PUBLIC_TENANT_ID, "服务端船司名", "ACTIVE", "CARRIER", List.of("SUPPLIER", "CARRIER"));
|
||||
when(partners.active("token", PUBLIC_TENANT_ID, 9L)).thenReturn(ApiResponse.success(carrier));
|
||||
|
||||
assertThat(guard.validateCarrier(9L).partnerName()).isEqualTo("服务端船司名");
|
||||
}
|
||||
@Test
|
||||
void carrierValidationSupportsLegacySingleTypeSnapshot() {
|
||||
var carrier = new PartnerClient.Partner(9L, PUBLIC_TENANT_ID, "旧数据船司", "ACTIVE", "CARRIER", null);
|
||||
when(partners.active("token", PUBLIC_TENANT_ID, 9L)).thenReturn(ApiResponse.success(carrier));
|
||||
|
||||
assertThat(guard.validateCarrier(9L).partnerName()).isEqualTo("旧数据船司");
|
||||
}
|
||||
@Test
|
||||
void partnerWithoutCarrierTypeCannotBeAssignedToOrder() {
|
||||
var supplier = new PartnerClient.Partner(9L, PUBLIC_TENANT_ID, "普通供应商", "ACTIVE", "SUPPLIER", List.of("SUPPLIER"));
|
||||
when(partners.active("token", PUBLIC_TENANT_ID, 9L)).thenReturn(ApiResponse.success(supplier));
|
||||
|
||||
assertThatThrownBy(() -> guard.validateCarrier(9L))
|
||||
.isInstanceOf(BizException.class)
|
||||
.hasMessageContaining("不具备承运商类型")
|
||||
.extracting(exception -> ((BizException) exception).getResultCode())
|
||||
.isEqualTo(ResultCode.VALIDATION_FAILED);
|
||||
}
|
||||
@Test
|
||||
void inactiveOrCrossTenantMasterDataIsRejected() {
|
||||
when(partners.active("token",PUBLIC_TENANT_ID,7)).thenReturn(ApiResponse.success(null));
|
||||
assertThatThrownBy(() -> guard.validate(10002,request(7L,8L)))
|
||||
@@ -255,7 +230,7 @@ class OrderMasterDataGuardTest {
|
||||
var cargo=new OrderRequests.Cargo("货物",null,"CARTON",1,BigDecimal.ONE,BigDecimal.ONE,
|
||||
null,null,null,null,null,false,null,null,null,null,null,null,null,null,null,null,null,null,null,
|
||||
null,null,null,null,null,null);
|
||||
return new OrderRequests.SaveRequest(partner,"不可信客户名","SEA",null,"CN",destinationWarehouseId,"私人地址",null,null,party,party,List.of(cargo),"PICKUP",warehouse,"不可信收货仓","CH","渠道",9L,"船司","BUY_DECLARATION",null,"LCL",false,destinationType,null,null,null);
|
||||
return new OrderRequests.SaveRequest(partner,"不可信客户名","SEA",null,"CN",destinationWarehouseId,"私人地址",null,null,party,party,List.of(cargo),"PICKUP",warehouse,"不可信收货仓","CH","渠道",null,null,"BUY_DECLARATION",null,"LCL",false,destinationType,null,null,null);
|
||||
}
|
||||
private WarehouseClient.Detail warehouse(long id,String type,boolean receiving) {
|
||||
var value=new WarehouseClient.Warehouse(id,PUBLIC_TENANT_ID,"WH-"+id,"仓库"+id,type,"CN","ACTIVE");
|
||||
|
||||
@@ -141,9 +141,9 @@ class UnifiedOrderQueryServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void waitSplitFilterForwardsExactStatusAndPreservesSummaryForMerchantScope() {
|
||||
void historicalWaitSplitFilterForwardsInboundedAndReturnsInbounded() {
|
||||
UnifiedOrderQuery query = query("WAIT_SPLIT");
|
||||
var summary = summary("WAIT_SPLIT", null);
|
||||
var summary = summary("INBOUNDED", null);
|
||||
when(firstleg.page(eq("internal-token"), any()))
|
||||
.thenReturn(ApiResponse.success(new PageResult<>(List.of(summary), 1, 20, 1, 1)));
|
||||
when(orders.findByIds(eq(10001L), eq(List.of(77L)))).thenReturn(List.of(order(OrderStatus.PROCESSING)));
|
||||
@@ -151,18 +151,18 @@ class UnifiedOrderQueryServiceTest {
|
||||
var result = service.page(10001L, query);
|
||||
|
||||
assertThat(result.records()).singleElement()
|
||||
.extracting(row -> row.mainStatus()).isEqualTo("WAIT_SPLIT");
|
||||
.extracting(row -> row.mainStatus()).isEqualTo("INBOUNDED");
|
||||
ArgumentCaptor<FirstlegUnifiedOrderClient.Query> captor =
|
||||
ArgumentCaptor.forClass(FirstlegUnifiedOrderClient.Query.class);
|
||||
verify(firstleg).page(eq("internal-token"), captor.capture());
|
||||
assertThat(captor.getValue().tenantId()).isEqualTo(10001L);
|
||||
assertThat(captor.getValue().mainStatus()).isEqualTo("WAIT_SPLIT");
|
||||
assertThat(captor.getValue().mainStatus()).isEqualTo("INBOUNDED");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fulfillmentTabsForwardStatusSearchAndPaginationToFirstleg() {
|
||||
List<String> statuses = List.of(
|
||||
"WAIT_MEASURE", "INBOUNDED", "WAIT_SPLIT", "LOADING", "LOADED", "DELIVERED");
|
||||
"WAIT_MEASURE", "INBOUNDED", "LOADING", "LOADED", "DELIVERED");
|
||||
when(firstleg.page(eq("internal-token"), any()))
|
||||
.thenReturn(ApiResponse.success(new PageResult<>(List.of(), 3, 20, 0, 0)));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user