fix(lastleg): reject unavailable receiving pallets

This commit is contained in:
2026-09-08 14:52:08 +08:00
parent a0ad3382af
commit 6908969307
2 changed files with 108 additions and 5 deletions
@@ -11,6 +11,7 @@ import org.springframework.web.server.ResponseStatusException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus;
import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
class HttpWarehouseResourceGatewayTest {
@@ -32,7 +33,9 @@ class HttpWarehouseResourceGatewayTest {
.andRespond(withSuccess("""
{"code":"200","data":{"palletId":2092040891261427713,"palletCode":"PAL-1",
"warehouseId":2092040869757231105,"locationId":2092040891076878337,
"status":"IDLE","fbaWarehouseCode":"ABE3","version":3}}
"status":"IDLE","fbaWarehouseCode":"ABE3","version":3,
"locationType":"STORAGE","locationStatus":"IDLE","reservable":true,
"reservationBlockReason":null}}
""", MediaType.APPLICATION_JSON));
WarehouseResourceGateway.WarehousePalletReference result = gateway.resolvePallet("PAL-1");
@@ -43,6 +46,40 @@ class HttpWarehouseResourceGatewayTest {
server.verify();
}
@Test
void resolveRejectsPalletWhoseLocationIsNotReservable() {
server.expect(requestTo("http://warehouse/internal/v1/warehouse-pallets/resolve/PAL-BLOCKED"))
.andRespond(withSuccess("""
{"code":"200","data":{"palletId":2092040891261427713,"palletCode":"PAL-BLOCKED",
"warehouseId":2092040869757231105,"locationId":2092040891076878337,
"status":"IDLE","fbaWarehouseCode":"ABE3","version":3,
"locationType":"STORAGE","locationStatus":"OCCUPIED","reservable":false,
"reservationBlockReason":"LOCATION_NOT_IDLE"}}
""", MediaType.APPLICATION_JSON));
assertThatThrownBy(() -> gateway.resolvePallet("PAL-BLOCKED"))
.isInstanceOf(ResponseStatusException.class)
.hasMessageContaining("409")
.hasMessageContaining("Pallet location is not idle");
server.verify();
}
@Test
void resolveFailsClosedWhenWarehouseOmitsReservationFacts() {
server.expect(requestTo("http://warehouse/internal/v1/warehouse-pallets/resolve/PAL-UNKNOWN"))
.andRespond(withSuccess("""
{"code":"200","data":{"palletId":2092040891261427713,"palletCode":"PAL-UNKNOWN",
"warehouseId":2092040869757231105,"locationId":2092040891076878337,
"status":"IDLE","fbaWarehouseCode":"ABE3","version":3}}
""", MediaType.APPLICATION_JSON));
assertThatThrownBy(() -> gateway.resolvePallet("PAL-UNKNOWN"))
.isInstanceOf(ResponseStatusException.class)
.hasMessageContaining("409")
.hasMessageContaining("availability could not be verified");
server.verify();
}
@Test
void ensureDropshipStillMapsWarehouseEntityId() {
server.expect(requestTo("http://warehouse/internal/v1/warehouse-pallets/ensure-dropship"))
@@ -72,4 +109,36 @@ class HttpWarehouseResourceGatewayTest {
server.verify();
}
@Test
void reserveMapsWarehouseLocationConflictToStableConflict() {
server.expect(requestTo("http://warehouse/internal/v1/warehouse-resource-locks"))
.andRespond(withStatus(org.springframework.http.HttpStatus.CONFLICT)
.contentType(MediaType.APPLICATION_JSON)
.body("""
{"code":"A0409","message":"Location is not idle","data":null}
"""));
assertThatThrownBy(() -> gateway.reserve("1", 2L, 3L, 4L,
"LASTLEG_INBOUND", "plan:5", "reservation-1"))
.isInstanceOf(ResponseStatusException.class)
.hasMessageContaining("409")
.hasMessageContaining("Warehouse resource reservation was rejected");
server.verify();
}
@Test
void reserveMapsBusinessConflictEnvelopeToStableConflict() {
server.expect(requestTo("http://warehouse/internal/v1/warehouse-resource-locks"))
.andRespond(withSuccess("""
{"code":"A0409","message":"Location is not idle","data":null}
""", MediaType.APPLICATION_JSON));
assertThatThrownBy(() -> gateway.reserve("1", 2L, 3L, 4L,
"LASTLEG_INBOUND", "plan:5", "reservation-1"))
.isInstanceOf(ResponseStatusException.class)
.hasMessageContaining("409")
.hasMessageContaining("Location is not idle");
server.verify();
}
}