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
@@ -59,10 +59,20 @@ public class HttpWarehouseResourceGateway implements WarehouseResourceGateway {
"businessId", businessId, "reservationKey", reservationKey))
.retrieve()
.onStatus(HttpStatusCode::isError, (request, result) -> {
throw new IllegalStateException("Warehouse rejected pallet reservation: HTTP " + result.getStatusCode());
throw warehouseReservationFailure(result.getStatusCode());
})
.body(ReserveEnvelope.class);
if (response == null || response.data() == null) throw new IllegalStateException("Warehouse returned an empty lock response");
if (response == null) {
throw new ResponseStatusException(HttpStatus.SERVICE_UNAVAILABLE,
"Warehouse resource reservation returned no response");
}
if (response.data() == null) {
HttpStatus status = "A0409".equals(response.code()) ? HttpStatus.CONFLICT
: "A0404".equals(response.code()) ? HttpStatus.NOT_FOUND : HttpStatus.SERVICE_UNAVAILABLE;
throw new ResponseStatusException(status,
response.message() == null || response.message().isBlank()
? "Warehouse resource reservation was rejected" : response.message());
}
return response.data().lockId();
}
@@ -120,6 +130,7 @@ public class HttpWarehouseResourceGateway implements WarehouseResourceGateway {
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());
@@ -133,6 +144,7 @@ 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());
@@ -144,6 +156,26 @@ public class HttpWarehouseResourceGateway implements WarehouseResourceGateway {
status.value() == 404 ? "Warehouse pallet was not found" : "Warehouse pallet lookup failed");
}
private ResponseStatusException warehouseReservationFailure(HttpStatusCode status) {
HttpStatus mapped = status.value() == 409 ? HttpStatus.CONFLICT
: status.value() == 404 ? HttpStatus.NOT_FOUND
: status.is4xxClientError() ? HttpStatus.BAD_REQUEST : HttpStatus.SERVICE_UNAVAILABLE;
return new ResponseStatusException(mapped, "Warehouse resource reservation was rejected");
}
private void requireReservable(WarehousePalletData pallet) {
if (pallet.reservable()) return;
String reason = switch (pallet.reservationBlockReason() == null
? "RESOURCE_STATE_UNKNOWN" : pallet.reservationBlockReason()) {
case "PALLET_NOT_IDLE" -> "Pallet is not idle";
case "LOCATION_NOT_FOUND" -> "Pallet location was not found";
case "VIRTUAL_LOCATION_NOT_ACTIVE" -> "Pallet virtual location is not active";
case "LOCATION_NOT_IDLE" -> "Pallet location is not idle";
default -> "Pallet resource availability could not be verified";
};
throw new ResponseStatusException(HttpStatus.CONFLICT, reason);
}
@Override
public WarehouseLocationReference resolveLocation(long warehouseId, String locationCode) {
WarehouseLocationResponse response = client.get()
@@ -200,8 +232,10 @@ public class HttpWarehouseResourceGateway implements WarehouseResourceGateway {
private record WarehousePalletResponse(String code, String message, WarehousePalletData data) {}
private record WarehousePalletData(@JsonAlias("palletId") long id, String palletCode, long warehouseId, long locationId,
String status, String fbaWarehouseCode, java.math.BigDecimal unitPrice, int version) {}
private record ReserveEnvelope(ReserveData data) {}
String status, String fbaWarehouseCode, java.math.BigDecimal unitPrice, int version,
String locationType, String locationStatus, boolean reservable,
String reservationBlockReason) {}
private record ReserveEnvelope(String code, String message, ReserveData data) {}
private record ReserveData(long lockId) {}
private record WarehouseReferenceResponse(String code, String message, WarehouseReference data) {}
private record WarehouseLocationResponse(String code, String message, WarehouseLocationReference data) {}