feat: add inbound hold lifecycle
This commit is contained in:
@@ -50,6 +50,7 @@ public interface FirstlegUnifiedOrderClient {
|
||||
LocalDateTime expectedArrivalAt, LocalDateTime requestedPickupAt, String feeReviewStatus,
|
||||
String companyName, String businessType, String taxMode, String containerMode,
|
||||
Boolean customsInspection, String destinationType, String destinationCode,
|
||||
Boolean holdFlag, String currentHoldReason,
|
||||
BigDecimal actualGrossWeightKg, BigDecimal actualNetWeightKg, BigDecimal actualVolumeCbm,
|
||||
BigDecimal volumeWeightKg, BigDecimal chargeableVolumeCbm, Integer palletCount,
|
||||
BigDecimal chargeableWeightKg, LocalDateTime measureCompletedAt,
|
||||
|
||||
@@ -19,6 +19,7 @@ public final class UnifiedOrderResponse {
|
||||
Long receivingWarehouseId, String receivingWarehouseName,
|
||||
Long destinationWarehouseId, String destinationWarehouseName,
|
||||
Long inboundId, Integer inboundVersion, String inboundCode, LocalDate expectedShipDate,
|
||||
Boolean holdFlag, String currentHoldReason,
|
||||
Integer totalPackageCount, String recommendedPalletType, String locationCodes,
|
||||
BigDecimal estimatedVolumeCbm, BigDecimal expectedVolumeCbm,
|
||||
BigDecimal actualGrossWeightKg, BigDecimal actualVolumeCbm,
|
||||
|
||||
@@ -287,7 +287,7 @@ public class UnifiedOrderQueryService {
|
||||
order.getChannelCode(), order.getChannelName(), Boolean.TRUE.equals(order.getChannelChanged()), order.getReceivingWarehouseId(), order.getReceivingWarehouseName(),
|
||||
order.getDestinationWarehouseId(), order.getDestinationWarehouseName(), null, null,
|
||||
order.getInboundCode(),
|
||||
order.getExpectedShipDate(), totalPackageCount(cargo), null, null,
|
||||
order.getExpectedShipDate(), null, null, totalPackageCount(cargo), null, null,
|
||||
order.getEstimatedVolumeCbm(), volumeCbm(cargo), null, null,
|
||||
order.getExpectedArrivalAt(), null, null, null, order.getPickupMethod(), order.getTaxMode(), order.getContainerMode(),
|
||||
order.getCustomsInspection(), order.getDestinationType(), order.getAmazonWarehouseCode(),
|
||||
@@ -306,7 +306,8 @@ public class UnifiedOrderQueryService {
|
||||
order.getCustomerId(), order.getCustomerName(),
|
||||
order.getChannelCode(), order.getChannelName(), Boolean.TRUE.equals(order.getChannelChanged()), order.getReceivingWarehouseId(), order.getReceivingWarehouseName(),
|
||||
order.getDestinationWarehouseId(), order.getDestinationWarehouseName(), inbound.id(), inbound.version(), inbound.inboundCode(),
|
||||
order.getExpectedShipDate(), displayedPackageCount(order, cargo, inbound), null,
|
||||
order.getExpectedShipDate(), inbound.holdFlag(), inbound.currentHoldReason(),
|
||||
displayedPackageCount(order, cargo, inbound), null,
|
||||
distinctLocationCodes(inbound.locationCodes()),
|
||||
order.getEstimatedVolumeCbm(), volumeCbm(cargo),
|
||||
inbound.actualGrossWeightKg(), inbound.actualVolumeCbm(),
|
||||
@@ -333,7 +334,7 @@ public class UnifiedOrderQueryService {
|
||||
inbound.customerId(), inbound.customerName(), inbound.channelCode(), inbound.channelName(),
|
||||
order != null && Boolean.TRUE.equals(order.getChannelChanged()), inbound.warehouseId(),
|
||||
inbound.warehouseName(), inbound.deliveryWarehouseId(), inbound.deliveryWarehouseName(),
|
||||
inbound.id(), inbound.version(), inbound.inboundCode(), null,
|
||||
inbound.id(), inbound.version(), inbound.inboundCode(), null, inbound.holdFlag(), inbound.currentHoldReason(),
|
||||
displayedPackageCount(order, cargo, inbound), null, distinctLocationCodes(inbound.locationCodes()),
|
||||
order == null ? null : order.getEstimatedVolumeCbm(), volumeCbm(cargo),
|
||||
inbound.actualGrossWeightKg(), inbound.actualVolumeCbm(),
|
||||
|
||||
@@ -753,6 +753,8 @@ components:
|
||||
inboundVersion: {type: integer, nullable: true, description: C04 loading/complete 的 expectedVersion}
|
||||
inboundCode: {type: string, nullable: true, description: 当前订单片段的权威入仓码;缺失时为 null,不得回退为 orderId 或 orderNo}
|
||||
expectedShipDate: {type: string, format: date, nullable: true}
|
||||
holdFlag: {type: boolean, nullable: true, description: Firstleg 入库单当前扣货标识;尚未生成入库单时为 null}
|
||||
currentHoldReason: {type: string, nullable: true, description: Firstleg 入库单当前扣货原因;未扣货或尚未生成入库单时为 null}
|
||||
totalPackageCount: {type: integer, nullable: true, description: 无入仓事实时为当前订单有效货物箱数合计;存在入仓业务单元后为该单元履约总箱数,拆分后不以父单原始箱数覆盖}
|
||||
recommendedPalletType: {type: string, nullable: true, description: 当前无列表级权威事实时返回 null,不得返回固定托盘类型}
|
||||
locationCodes: {type: string, nullable: true, description: "库位编码汇总;按首次出现顺序去重并使用中文顿号分隔"}
|
||||
|
||||
@@ -54,6 +54,7 @@ class UnifiedOrderApiContractTest {
|
||||
assertThat(stringMap(row.get("properties"))).containsKeys(
|
||||
"orderId", "mainStatus", "channelCode", "inboundId", "inboundVersion", "measurement", "preload",
|
||||
"loading", "delivery", "transport", "customerRemark", "latestInternalNote",
|
||||
"holdFlag", "currentHoldReason",
|
||||
"expectedArrivalAt", "requestedPickupAt", "feeReviewStatus", "companyName", "businessType", "pickupMethod",
|
||||
"taxMode", "containerMode", "customsInspection", "destinationType", "destinationCode",
|
||||
"totalPalletCount", "chargeableWeightKg", "chargeableVolumeCbm", "volumetricWeightKg", "totalNetWeightKg",
|
||||
@@ -64,6 +65,8 @@ class UnifiedOrderApiContractTest {
|
||||
assertThat(inboundCode.get("description").toString()).contains("不得回退");
|
||||
Map<String, Object> channelCode = stringMap(stringMap(row.get("properties")).get("channelCode"));
|
||||
assertThat(channelCode.get("description").toString()).contains("不由 channelName 推导");
|
||||
assertThat(stringMap(row.get("properties")))
|
||||
.doesNotContainKeys("holdCargo", "holdReason");
|
||||
Map<String, Object> coLoadGroup = stringMap(schemas.get("UnifiedCoLoadGroupSummary"));
|
||||
assertThat(stringMap(coLoadGroup.get("properties")))
|
||||
.containsOnlyKeys("status", "memberCount", "memberInboundCodes");
|
||||
@@ -82,7 +85,9 @@ class UnifiedOrderApiContractTest {
|
||||
"page", String.class, FirstlegUnifiedOrderClient.Query.class);
|
||||
assertThat(page.getAnnotation(PostMapping.class).value()).containsExactly("/query");
|
||||
assertThat(List.of(FirstlegUnifiedOrderClient.Inbound.class.getRecordComponents()).stream()
|
||||
.map(component -> component.getName())).contains("channelCode", "channelName");
|
||||
.map(component -> component.getName()))
|
||||
.contains("channelCode", "channelName", "holdFlag", "currentHoldReason")
|
||||
.doesNotContain("holdCargo", "holdReason");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -74,6 +74,8 @@ class UnifiedOrderQueryServiceTest {
|
||||
assertThat(row.inboundCode()).isEqualTo("RK-77");
|
||||
assertThat(row.channelCode()).isEqualTo("MATSON");
|
||||
assertThat(row.inboundId()).isNull();
|
||||
assertThat(row.holdFlag()).isNull();
|
||||
assertThat(row.currentHoldReason()).isNull();
|
||||
assertThat(row.customerRemark()).isEqualTo("客户要求提货前联系");
|
||||
assertThat(row.latestInternalNote()).isEqualTo("客服已确认提货时间");
|
||||
assertThat(row.relation()).isNull();
|
||||
@@ -98,6 +100,8 @@ class UnifiedOrderQueryServiceTest {
|
||||
assertThat(row.nextAction()).isEqualTo("APPROVE_ORDER");
|
||||
assertThat(row.inboundId()).isEqualTo(88L);
|
||||
assertThat(row.internalOrderStatus()).isEqualTo(OrderStatus.SUBMITTED);
|
||||
assertThat(row.holdFlag()).isTrue();
|
||||
assertThat(row.currentHoldReason()).isEqualTo("等待客户补充资料");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -592,6 +596,8 @@ class UnifiedOrderQueryServiceTest {
|
||||
assertThat(result.summary().mainStatus()).isEqualTo("LOADED");
|
||||
assertThat(result.summary().internalOrderStatus()).isEqualTo(OrderStatus.APPROVED);
|
||||
assertThat(result.summary().inboundId()).isEqualTo(88L);
|
||||
assertThat(result.summary().holdFlag()).isTrue();
|
||||
assertThat(result.summary().currentHoldReason()).isEqualTo("等待客户补充资料");
|
||||
ArgumentCaptor<FirstlegUnifiedOrderClient.DetailRequest> captor =
|
||||
ArgumentCaptor.forClass(FirstlegUnifiedOrderClient.DetailRequest.class);
|
||||
verify(firstleg).detail(eq("internal-token"), captor.capture());
|
||||
@@ -701,6 +707,8 @@ class UnifiedOrderQueryServiceTest {
|
||||
when(inbound.deliveryWarehouseName()).thenReturn("ONT8");
|
||||
when(inbound.channelName()).thenReturn("美森");
|
||||
when(inbound.channelCode()).thenReturn("MATSON");
|
||||
when(inbound.holdFlag()).thenReturn(true);
|
||||
when(inbound.currentHoldReason()).thenReturn("等待客户补充资料");
|
||||
when(inbound.totalPackageCount()).thenReturn(10);
|
||||
when(inbound.locationCodes()).thenReturn("A0-01, B2-03");
|
||||
when(inbound.companyName()).thenReturn("测试客户有限公司");
|
||||
|
||||
Reference in New Issue
Block a user