fix(lastleg): complete generated pallet receiving flow
This commit is contained in:
+3
@@ -23,6 +23,9 @@ public record InboundPlanListResponse(
|
||||
Integer pickedPackageCount,
|
||||
BigDecimal volumeCbm,
|
||||
Integer palletCount,
|
||||
boolean assigned,
|
||||
boolean mergeAllowed,
|
||||
boolean urgent,
|
||||
String status,
|
||||
String appointmentNo,
|
||||
String appointmentStatus,
|
||||
|
||||
+2
-1
@@ -44,7 +44,8 @@ public interface InboundPlanQueryMapper {
|
||||
"o.customer_name customerName,l.required_package_count packageCount," +
|
||||
"COALESCE((SELECT SUM(pa.picked_package_count) FROM ll_inbound_plan_pallet_allocation pa WHERE pa.line_id=l.id),0) pickedPackageCount," +
|
||||
"l.volume_cbm volumeCbm," +
|
||||
"l.planned_pallet_count palletCount,p.status status,a.appointment_no appointmentNo," +
|
||||
"l.planned_pallet_count palletCount,p.assigned_flag assigned,p.merge_required mergeAllowed," +
|
||||
"p.urgent_flag urgent,p.status status,a.appointment_no appointmentNo," +
|
||||
"a.appointment_status appointmentStatus,a.appointment_at appointmentAt," +
|
||||
"a.expected_loading_at expectedLoadingAt," +
|
||||
"CASE WHEN EXISTS (SELECT 1 FROM ll_dispatch_item di WHERE " +
|
||||
|
||||
+8
-5
@@ -55,7 +55,8 @@ public final class ReceivingContainerResponses {
|
||||
String destinationWarehouseCode, String destinationWarehouseName,
|
||||
String fbaWarehouseCode, int plannedPalletCount, int totalPackages,
|
||||
int receivedPackages, int pendingPackages,
|
||||
boolean palletMergeRequired, String palletMergeHint) { }
|
||||
boolean assigned, boolean mergeAllowed, boolean urgent,
|
||||
String mergeHint) { }
|
||||
|
||||
public record CartonResolved(String cartonMark, String inboundCode,
|
||||
String destinationType, String overseasWarehouseId,
|
||||
@@ -63,7 +64,8 @@ public final class ReceivingContainerResponses {
|
||||
String destinationWarehouseCode, String destinationWarehouseName,
|
||||
String fbaWarehouseCode, int plannedPalletCount, int totalPackages,
|
||||
int receivedPackages, int pendingPackages,
|
||||
boolean palletMergeRequired, String palletMergeHint) {
|
||||
boolean assigned, boolean mergeAllowed, boolean urgent,
|
||||
String mergeHint) {
|
||||
public CartonResolved(String cartonMark, String inboundCode, String destinationType,
|
||||
String overseasWarehouseId, String overseasWarehouseName,
|
||||
String destinationWarehouseId, String destinationWarehouseCode,
|
||||
@@ -73,7 +75,7 @@ public final class ReceivingContainerResponses {
|
||||
this(cartonMark, inboundCode, destinationType, overseasWarehouseId, overseasWarehouseName,
|
||||
destinationWarehouseId, destinationWarehouseCode, destinationWarehouseName,
|
||||
fbaWarehouseCode, plannedPalletCount, totalPackages, receivedPackages,
|
||||
pendingPackages, false, null);
|
||||
pendingPackages, false, false, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,12 +86,13 @@ public final class ReceivingContainerResponses {
|
||||
public record Receipt(String result, String containerNo, String inboundCode,
|
||||
String destinationType, String palletCode, int acceptedPackages,
|
||||
int receivedPackages, int pendingPackages, String sessionStatus,
|
||||
boolean palletMergeRequired, String palletMergeHint) {
|
||||
boolean assigned, boolean mergeAllowed, boolean urgent,
|
||||
String mergeHint) {
|
||||
public Receipt(String result, String containerNo, String inboundCode,
|
||||
String destinationType, String palletCode, int acceptedPackages,
|
||||
int receivedPackages, int pendingPackages, String sessionStatus) {
|
||||
this(result, containerNo, inboundCode, destinationType, palletCode, acceptedPackages,
|
||||
receivedPackages, pendingPackages, sessionStatus, false, null);
|
||||
receivedPackages, pendingPackages, sessionStatus, false, false, false, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -117,6 +117,12 @@ public class HttpWarehouseResourceGateway implements WarehouseResourceGateway {
|
||||
|
||||
@Override
|
||||
public WarehousePalletReference resolvePallet(String palletCode) {
|
||||
WarehousePalletResponse response = lookupPallet(palletCode);
|
||||
return reference(response.data());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WarehousePalletReference resolveAvailablePallet(String palletCode) {
|
||||
WarehousePalletResponse response = lookupPallet(palletCode);
|
||||
requireReservable(response.data());
|
||||
return reference(response.data());
|
||||
@@ -153,7 +159,6 @@ public class HttpWarehouseResourceGateway implements WarehouseResourceGateway {
|
||||
.body(WarehousePalletResponse.class);
|
||||
if (response == null || response.data() == null) throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE,
|
||||
"Warehouse pallet service returned no usable response");
|
||||
requireReservable(response.data());
|
||||
return new WarehousePalletReference(response.data().id(), response.data().palletCode(), response.data().warehouseId(),
|
||||
response.data().locationId(), response.data().status(), response.data().fbaWarehouseCode(),
|
||||
response.data().unitPrice(), response.data().version());
|
||||
|
||||
+3
@@ -11,6 +11,9 @@ public interface WarehouseResourceGateway {
|
||||
void scrapPallet(String customerId, long palletId);
|
||||
WarehousePalletReference resolvePallet(String palletCode);
|
||||
WarehousePalletReference resolvePallet(long palletId);
|
||||
default WarehousePalletReference resolveAvailablePallet(String palletCode) {
|
||||
return resolvePallet(palletCode);
|
||||
}
|
||||
default WarehousePalletReference resolveReservedPallet(String palletCode, String customerId, long warehouseId,
|
||||
long palletId, long locationId, long resourceLockId) {
|
||||
throw new UnsupportedOperationException("Reserved warehouse pallet resolution is not configured");
|
||||
|
||||
+20
-12
@@ -61,7 +61,8 @@ import java.util.stream.Collectors;
|
||||
public class ReceivingContainerService {
|
||||
private static final String PHOTO_DOWNLOAD_PATH =
|
||||
"/api/pda/v1/last-leg/receiving-containers/current/unload-photos/files/{fileId}/download";
|
||||
private static final String PALLET_MERGE_HINT = "该入仓单已标记合托,请按合托要求拣货";
|
||||
private static final String PALLET_MERGE_HINT =
|
||||
"该入库计划可选择合托:合托时扫描同目的仓已使用的托盘码,独立收货时扫描新托盘码;不强制合托";
|
||||
|
||||
@Resource private InboundPlanMapper plans;
|
||||
@Resource private InboundPlanLineMapper lines;
|
||||
@@ -266,7 +267,7 @@ public class ReceivingContainerService {
|
||||
inbound.overseasWarehouseName(), inbound.destinationWarehouseId(),
|
||||
inbound.destinationWarehouseCode(), inbound.destinationWarehouseName(), inbound.fbaWarehouseCode(),
|
||||
inbound.plannedPalletCount(), inbound.totalPackages(), inbound.receivedPackages(), inbound.pendingPackages(),
|
||||
inbound.palletMergeRequired(), inbound.palletMergeHint());
|
||||
inbound.assigned(), inbound.mergeAllowed(), inbound.urgent(), inbound.mergeHint());
|
||||
}
|
||||
|
||||
public ReceivingContainerResponses.PalletResolved resolvePallet(String operatorKey,
|
||||
@@ -311,8 +312,8 @@ public class ReceivingContainerService {
|
||||
int total = fbaPlanRefs.stream().mapToInt(refValue -> value(refValue.line().getRequiredPackageCount())).sum();
|
||||
ReceivingContainerResponses.Receipt result = new ReceivingContainerResponses.Receipt("RECEIVED",
|
||||
session.getContainerNo(), ref.line().getInboundCode(), "FBA", resource.palletNo(), accepted,
|
||||
received, Math.max(0, total - received), session.getStatus(), palletMergeRequired(ref.order()),
|
||||
palletMergeHint(ref.order()));
|
||||
received, Math.max(0, total - received), session.getStatus(), assigned(ref.plan()),
|
||||
mergeAllowed(ref.plan()), urgent(ref.plan()), mergeHint(ref.plan()));
|
||||
save(session, "BULK_RECEIVE", request.idempotencyKey(), request, result);
|
||||
return result;
|
||||
} catch (RuntimeException failure) {
|
||||
@@ -351,7 +352,7 @@ public class ReceivingContainerService {
|
||||
ReceivingContainerResponses.Receipt result = new ReceivingContainerResponses.Receipt("RECEIVED",
|
||||
session.getContainerNo(), inbound.inboundCode(), inbound.destinationType(), resource.palletNo(), 1,
|
||||
inbound.receivedPackages(), inbound.pendingPackages(), session.getStatus(),
|
||||
inbound.palletMergeRequired(), inbound.palletMergeHint());
|
||||
inbound.assigned(), inbound.mergeAllowed(), inbound.urgent(), inbound.mergeHint());
|
||||
save(session, "CARTON_RECEIVE", request.idempotencyKey(), request, result);
|
||||
return result;
|
||||
} catch (RuntimeException failure) {
|
||||
@@ -654,7 +655,7 @@ public class ReceivingContainerService {
|
||||
pallet.getWarehousePalletId(), pallet.getWarehouseLocationId(), pallet.getWarehouseResourceLockId());
|
||||
} else {
|
||||
try {
|
||||
resource = warehouse.resolvePallet(palletCode.trim());
|
||||
resource = warehouse.resolveAvailablePallet(palletCode.trim());
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw notFound("Pallet was not found");
|
||||
}
|
||||
@@ -728,16 +729,23 @@ public class ReceivingContainerService {
|
||||
ref.line().getDestinationWarehouseId(), ref.line().getDestinationWarehouseCode(),
|
||||
ref.line().getDestinationWarehouseName(), ref.line().getFbaWarehouseCode(),
|
||||
value(ref.line().getPlannedPalletCount()), total, received, Math.max(0, total - received),
|
||||
palletMergeRequired(ref.order()), palletMergeHint(ref.order()));
|
||||
assigned(ref.plan()), mergeAllowed(ref.plan()), urgent(ref.plan()), mergeHint(ref.plan()));
|
||||
}
|
||||
|
||||
private boolean palletMergeRequired(LastlegOrder order) {
|
||||
return order != null && ("REQUIRED".equals(order.getPalletMergeFlag())
|
||||
|| "MERGED".equals(order.getPalletMergeFlag()));
|
||||
private boolean assigned(InboundPlan plan) {
|
||||
return plan != null && Boolean.TRUE.equals(plan.getAssignedFlag());
|
||||
}
|
||||
|
||||
private String palletMergeHint(LastlegOrder order) {
|
||||
return palletMergeRequired(order) ? PALLET_MERGE_HINT : null;
|
||||
private boolean mergeAllowed(InboundPlan plan) {
|
||||
return plan != null && Boolean.TRUE.equals(plan.getMergeRequired());
|
||||
}
|
||||
|
||||
private boolean urgent(InboundPlan plan) {
|
||||
return plan != null && Boolean.TRUE.equals(plan.getUrgentFlag());
|
||||
}
|
||||
|
||||
private String mergeHint(InboundPlan plan) {
|
||||
return mergeAllowed(plan) ? PALLET_MERGE_HINT : null;
|
||||
}
|
||||
|
||||
private Totals totals(List<InboundPlan> containerPlans) {
|
||||
|
||||
@@ -1503,7 +1503,7 @@ components:
|
||||
timestamp: { type: string, format: date-time }
|
||||
ReceivingInbound:
|
||||
type: object
|
||||
required: [inboundCode, destinationType, plannedPalletCount, totalPackages, receivedPackages, pendingPackages, palletMergeRequired]
|
||||
required: [inboundCode, destinationType, plannedPalletCount, totalPackages, receivedPackages, pendingPackages, assigned, mergeAllowed, urgent]
|
||||
properties:
|
||||
inboundCode: { type: string }
|
||||
destinationType: { type: string, enum: [FBA, OVERSEAS] }
|
||||
@@ -1517,8 +1517,10 @@ components:
|
||||
totalPackages: { type: integer }
|
||||
receivedPackages: { type: integer }
|
||||
pendingPackages: { type: integer }
|
||||
palletMergeRequired: { type: boolean, description: 尾程订单是否要求PDA合托提醒 }
|
||||
palletMergeHint: { type: string, nullable: true, description: 标记合托时供PDA直接展示的中文提示 }
|
||||
assigned: { type: boolean, description: 入库计划是否已分配 }
|
||||
mergeAllowed: { type: boolean, description: 入库计划是否允许现场选择合托;true不代表强制合托 }
|
||||
urgent: { type: boolean, description: 入库计划是否加急 }
|
||||
mergeHint: { type: string, nullable: true, description: 允许合托时供PDA直接展示的非强制中文提示 }
|
||||
ReceivingWarehouseProfile:
|
||||
type: object
|
||||
required: [warehouseId, warehouseCode, warehouseName]
|
||||
@@ -1598,7 +1600,7 @@ components:
|
||||
compatible: { type: boolean }
|
||||
ReceivingReceipt:
|
||||
type: object
|
||||
required: [result, containerNo, inboundCode, destinationType, palletCode, acceptedPackages, receivedPackages, pendingPackages, sessionStatus, palletMergeRequired]
|
||||
required: [result, containerNo, inboundCode, destinationType, palletCode, acceptedPackages, receivedPackages, pendingPackages, sessionStatus, assigned, mergeAllowed, urgent]
|
||||
properties:
|
||||
result: { type: string }
|
||||
containerNo: { type: string }
|
||||
@@ -1609,8 +1611,10 @@ components:
|
||||
receivedPackages: { type: integer }
|
||||
pendingPackages: { type: integer }
|
||||
sessionStatus: { type: string, enum: [SIGNED, RECEIVING] }
|
||||
palletMergeRequired: { type: boolean }
|
||||
palletMergeHint: { type: string, nullable: true }
|
||||
assigned: { type: boolean }
|
||||
mergeAllowed: { type: boolean, description: 现场可选择合托,不作为实收或完成门禁 }
|
||||
urgent: { type: boolean }
|
||||
mergeHint: { type: string, nullable: true }
|
||||
ReceivingCandidateListApiResponse:
|
||||
allOf:
|
||||
- { $ref: '#/components/schemas/ReceivingApiResponseBase' }
|
||||
@@ -2252,7 +2256,7 @@ components:
|
||||
properties: { records: { type: array, items: { $ref: '#/components/schemas/InboundPlanSummary' } } }
|
||||
InboundPlanSummary:
|
||||
type: object
|
||||
required: [lineId, planId, planNo, customerId, orderId, inboundCode, overseasWarehouseCode, overseasWarehouseName, packageCount, pickedPackageCount, palletCount, status, createdAt, version]
|
||||
required: [lineId, planId, planNo, customerId, orderId, inboundCode, overseasWarehouseCode, overseasWarehouseName, packageCount, pickedPackageCount, palletCount, assigned, mergeAllowed, urgent, status, createdAt, version]
|
||||
properties:
|
||||
lineId: { type: string, pattern: '^[0-9]+$' }
|
||||
planId: { type: string, pattern: '^[0-9]+$' }
|
||||
@@ -2272,6 +2276,9 @@ components:
|
||||
pickedPackageCount: { type: integer }
|
||||
volumeCbm: { type: number, nullable: true }
|
||||
palletCount: { type: integer }
|
||||
assigned: { type: boolean, description: 入库计划是否已分配 }
|
||||
mergeAllowed: { type: boolean, description: 入库计划是否允许现场选择合托;不作为强制门禁 }
|
||||
urgent: { type: boolean, description: 入库计划是否加急 }
|
||||
status: { type: string }
|
||||
appointmentNo: { type: string, nullable: true }
|
||||
appointmentStatus: { type: string, nullable: true }
|
||||
|
||||
+20
-4
@@ -49,7 +49,23 @@ class HttpWarehouseResourceGatewayTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveRejectsPalletWhoseLocationIsNotReservable() {
|
||||
void resolveAllowsOccupiedPalletForInventoryQueryAndOperations() {
|
||||
server.expect(requestTo("http://warehouse/internal/v1/warehouse-pallets/resolve/PAL-OCCUPIED"))
|
||||
.andRespond(withSuccess("""
|
||||
{"code":"200","data":{"palletId":31,"palletCode":"PAL-OCCUPIED",
|
||||
"warehouseId":21,"locationId":41,"status":"OCCUPIED","version":4,
|
||||
"reservable":false,"reservationBlockReason":"PALLET_NOT_IDLE"}}
|
||||
""", MediaType.APPLICATION_JSON));
|
||||
|
||||
var result = gateway.resolvePallet("PAL-OCCUPIED");
|
||||
|
||||
assertThat(result.palletId()).isEqualTo(31L);
|
||||
assertThat(result.status()).isEqualTo("OCCUPIED");
|
||||
server.verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
void availableResolveRejectsPalletWhoseLocationIsNotReservable() {
|
||||
server.expect(requestTo("http://warehouse/internal/v1/warehouse-pallets/resolve/PAL-BLOCKED"))
|
||||
.andRespond(withSuccess("""
|
||||
{"code":"200","data":{"palletId":2092040891261427713,"palletCode":"PAL-BLOCKED",
|
||||
@@ -59,7 +75,7 @@ class HttpWarehouseResourceGatewayTest {
|
||||
"reservationBlockReason":"LOCATION_NOT_IDLE"}}
|
||||
""", MediaType.APPLICATION_JSON));
|
||||
|
||||
assertThatThrownBy(() -> gateway.resolvePallet("PAL-BLOCKED"))
|
||||
assertThatThrownBy(() -> gateway.resolveAvailablePallet("PAL-BLOCKED"))
|
||||
.isInstanceOf(ResponseStatusException.class)
|
||||
.hasMessageContaining("409")
|
||||
.hasMessageContaining("Pallet location is not idle");
|
||||
@@ -99,7 +115,7 @@ class HttpWarehouseResourceGatewayTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveFailsClosedWhenWarehouseOmitsReservationFacts() {
|
||||
void availableResolveFailsClosedWhenWarehouseOmitsReservationFacts() {
|
||||
server.expect(requestTo("http://warehouse/internal/v1/warehouse-pallets/resolve/PAL-UNKNOWN"))
|
||||
.andRespond(withSuccess("""
|
||||
{"code":"200","data":{"palletId":2092040891261427713,"palletCode":"PAL-UNKNOWN",
|
||||
@@ -107,7 +123,7 @@ class HttpWarehouseResourceGatewayTest {
|
||||
"status":"IDLE","fbaWarehouseCode":"ABE3","version":3}}
|
||||
""", MediaType.APPLICATION_JSON));
|
||||
|
||||
assertThatThrownBy(() -> gateway.resolvePallet("PAL-UNKNOWN"))
|
||||
assertThatThrownBy(() -> gateway.resolveAvailablePallet("PAL-UNKNOWN"))
|
||||
.isInstanceOf(ResponseStatusException.class)
|
||||
.hasMessageContaining("409")
|
||||
.hasMessageContaining("availability could not be verified");
|
||||
|
||||
+15
-15
@@ -376,7 +376,7 @@ class ReceivingContainerServiceBehaviorTest {
|
||||
org.mockito.Mockito.reset(plans, lines, orders, sessions, operations, cartons, warehouse, pallets, workflow);
|
||||
stubCurrent("FBA", "CONT-A");
|
||||
stubSku();
|
||||
when(warehouse.resolvePallet("PAL-1")).thenReturn(resource(101L, "FBA-1"));
|
||||
when(warehouse.resolveAvailablePallet("PAL-1")).thenReturn(resource(101L, "FBA-1"));
|
||||
assertThatThrownBy(() -> service.receiveBulk("7", "receiver",
|
||||
new ReceivingContainerRequests.BulkReceive("IN-1", "PAL-1", 1, "pallet-key")))
|
||||
.isInstanceOf(ResponseStatusException.class).hasMessageContaining("409");
|
||||
@@ -387,7 +387,6 @@ class ReceivingContainerServiceBehaviorTest {
|
||||
void overReceiptAndDuplicateCartonFailBeforeRemoteReservation() {
|
||||
stubCurrent("FBA", "CONT-A");
|
||||
stubSku();
|
||||
when(warehouse.resolvePallet("PAL-1")).thenReturn(resource(100L, "FBA-1"));
|
||||
when(pallets.selectList(any())).thenReturn(List.of(planPallet()));
|
||||
doThrow(new ResponseStatusException(org.springframework.http.HttpStatus.CONFLICT, "over receipt"))
|
||||
.when(workflow).validateBulkResolved(any(), any(), any(), anyInt());
|
||||
@@ -399,10 +398,7 @@ class ReceivingContainerServiceBehaviorTest {
|
||||
org.mockito.Mockito.reset(plans, lines, orders, sessions, operations, cartons, warehouse, pallets, workflow);
|
||||
stubCurrent("OVERSEAS", "CONT-A");
|
||||
when(cartons.selectOne(any())).thenReturn(carton(1L, "BOX-1"));
|
||||
when(warehouse.resolvePallet("PAL-1")).thenReturn(resource(100L, null));
|
||||
when(pallets.selectList(any())).thenReturn(List.of(planPallet()));
|
||||
doThrow(new ResponseStatusException(org.springframework.http.HttpStatus.CONFLICT, "duplicate carton"))
|
||||
.when(workflow).validateCartonResolved(any(), any(), any(), any(), any());
|
||||
assertThatThrownBy(() -> service.receiveCarton("7", "receiver",
|
||||
new ReceivingContainerRequests.CartonReceive("BOX-1", "PAL-1", "duplicate-key")))
|
||||
.isInstanceOf(ResponseStatusException.class);
|
||||
@@ -415,7 +411,7 @@ class ReceivingContainerServiceBehaviorTest {
|
||||
InboundPlanLine overseasLine = line("OVERSEAS");
|
||||
overseasLine.setDestinationWarehouseId("900");
|
||||
when(lines.selectList(any())).thenReturn(List.of(overseasLine));
|
||||
when(warehouse.resolvePallet("PAL-1")).thenReturn(resource(100L, null));
|
||||
when(warehouse.resolveAvailablePallet("PAL-1")).thenReturn(resource(100L, null));
|
||||
|
||||
var resolved = service.resolvePallet("7",
|
||||
new ReceivingContainerRequests.PalletResolve("PAL-1", "IN-1"));
|
||||
@@ -453,7 +449,7 @@ class ReceivingContainerServiceBehaviorTest {
|
||||
void localFailureAfterRemoteReservationTriggersReleaseCompensation() {
|
||||
stubCurrent("FBA", "CONT-A");
|
||||
stubSku();
|
||||
when(warehouse.resolvePallet("PAL-1")).thenReturn(resource(100L, "FBA-1"));
|
||||
when(warehouse.resolveAvailablePallet("PAL-1")).thenReturn(resource(100L, "FBA-1"));
|
||||
when(pallets.selectList(any())).thenReturn(List.of(planPallet()));
|
||||
when(workflow.assignResolvedPallet(any(), any(), any(), any())).thenReturn(55L);
|
||||
ResponseStatusException failure = new ResponseStatusException(org.springframework.http.HttpStatus.CONFLICT, "race");
|
||||
@@ -490,7 +486,7 @@ class ReceivingContainerServiceBehaviorTest {
|
||||
new ReceivingContainerRequests.BulkReceive("IN-1", "PAL-RESERVED", 1, "reserved-key"));
|
||||
|
||||
verify(warehouse).resolveReservedPallet("PAL-RESERVED", "100", 100L, 30L, 40L, 50L);
|
||||
verify(warehouse, never()).resolvePallet("PAL-RESERVED");
|
||||
verify(warehouse, never()).resolveAvailablePallet("PAL-RESERVED");
|
||||
verify(workflow).assignResolvedPallet(org.mockito.ArgumentMatchers.eq("100"),
|
||||
any(InboundPlan.class), org.mockito.ArgumentMatchers.same(reserved),
|
||||
org.mockito.ArgumentMatchers.same(occupied));
|
||||
@@ -623,17 +619,21 @@ class ReceivingContainerServiceBehaviorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void cartonResolutionReturnsInboundAndPalletMergeReminderFromTailLegOrder() {
|
||||
void cartonResolutionReturnsAssignmentOptionalMergeAndUrgencyFromInboundPlan() {
|
||||
stubCurrent("FBA", "CONT-A");
|
||||
LastlegOrder marked = order("FBA");
|
||||
marked.setPalletMergeFlag("REQUIRED");
|
||||
when(orders.selectById(1L)).thenReturn(marked);
|
||||
InboundPlan flagged = plan("CONT-A");
|
||||
flagged.setAssignedFlag(true);
|
||||
flagged.setMergeRequired(true);
|
||||
flagged.setUrgentFlag(true);
|
||||
when(plans.selectList(any())).thenReturn(List.of(flagged));
|
||||
|
||||
var resolved = service.resolveCarton("7", new ReceivingContainerRequests.CartonResolve("IN-1#2-1"));
|
||||
|
||||
assertThat(resolved.inboundCode()).isEqualTo("IN-1");
|
||||
assertThat(resolved.palletMergeRequired()).isTrue();
|
||||
assertThat(resolved.palletMergeHint()).contains("合托");
|
||||
assertThat(resolved.assigned()).isTrue();
|
||||
assertThat(resolved.mergeAllowed()).isTrue();
|
||||
assertThat(resolved.urgent()).isTrue();
|
||||
assertThat(resolved.mergeHint()).contains("可选择", "同目的仓", "新托盘码", "不强制");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -700,7 +700,7 @@ class ReceivingContainerServiceBehaviorTest {
|
||||
when(orders.selectById(2L)).thenReturn(secondOrder);
|
||||
when(orderDetails.selectList(any())).thenReturn(List.of(detail("SKU-A", 1), detail("SKU-B", 1)),
|
||||
List.of(detail("SKU-C", 2)));
|
||||
when(warehouse.resolvePallet("PAL-1")).thenReturn(resource(100L, "FBA-1"));
|
||||
when(warehouse.resolveAvailablePallet("PAL-1")).thenReturn(resource(100L, "FBA-1"));
|
||||
when(pallets.selectList(any())).thenReturn(List.of(planPallet()));
|
||||
when(workflow.receiveBulkResolved(any(), any(), any(), any(), anyInt(), any(), any()))
|
||||
.thenAnswer(invocation -> invocation.getArgument(4));
|
||||
|
||||
+6
-1
@@ -49,7 +49,7 @@ class InboundPlanPaginationTest {
|
||||
LocalDateTime.of(2026, 8, 1, 0, 0), LocalDateTime.of(2026, 8, 31, 23, 59));
|
||||
InboundPlanListResponse row = new InboundPlanListResponse(9007199254740993L, 2L, "LIP2", "100",
|
||||
3L, "IN-1", null, "FIRST_LEG", "US-LAX-01", "洛杉矶仓", "W1", "ONT", "安大略仓",
|
||||
"ONT8", "客户A", 10, 0, BigDecimal.ONE, 1, "PENDING_ASSIGNMENT", null, null, null,
|
||||
"ONT8", "客户A", 10, 0, BigDecimal.ONE, 1, true, true, true, "PENDING_ASSIGNMENT", null, null, null,
|
||||
null, "UNSCHEDULED", LocalDateTime.of(2026, 8, 20, 10, 0), 0);
|
||||
when(queryMapper.count("100", query)).thenReturn(11L);
|
||||
when(queryMapper.rows("100", query, 10, 10)).thenReturn(List.of(row));
|
||||
@@ -61,6 +61,9 @@ class InboundPlanPaginationTest {
|
||||
assertThat(result.records().get(0).appointmentStatus()).isNull();
|
||||
assertThat(result.records().get(0).overseasWarehouseCode()).isEqualTo("US-LAX-01");
|
||||
assertThat(result.records().get(0).overseasWarehouseName()).isEqualTo("洛杉矶仓");
|
||||
assertThat(result.records().get(0).assigned()).isTrue();
|
||||
assertThat(result.records().get(0).mergeAllowed()).isTrue();
|
||||
assertThat(result.records().get(0).urgent()).isTrue();
|
||||
assertThat(result.pages()).isEqualTo(2);
|
||||
verify(queryMapper).count("100", query);
|
||||
verify(queryMapper).rows("100", query, 10, 10);
|
||||
@@ -76,6 +79,8 @@ class InboundPlanPaginationTest {
|
||||
assertThat(sql).contains("o.overseas_warehouse_code overseasWarehouseCode",
|
||||
"o.overseas_warehouse_name overseasWarehouseName",
|
||||
"o.overseas_warehouse_id=#{q.overseasWarehouseId}");
|
||||
assertThat(sql).contains("p.assigned_flag assigned", "p.merge_required mergeAllowed",
|
||||
"p.urgent_flag urgent");
|
||||
assertThat(sql).doesNotContain("l.destination_warehouse_id=#{q.overseasWarehouseId}");
|
||||
assertThat(sql).contains("q.planNo", "q.inboundCode", "q.status", "q.overseasWarehouseId",
|
||||
"q.destinationWarehouseCode", "q.warehouse",
|
||||
|
||||
Reference in New Issue
Block a user