fix: reserve locations from measured volume

This commit is contained in:
2026-09-04 15:05:44 +08:00
parent 5e013489e0
commit 8a0366af5b
2 changed files with 39 additions and 3 deletions
@@ -174,9 +174,14 @@ public class MeasurementLocationOccupationService {
return order.getActualVolumeCbm();
}
var measurement = measurements.findLatestMeasurement(tenantId, inboundId);
if (measurement != null && measurement.getOriginalVolumeCbm() != null
&& measurement.getOriginalVolumeCbm().signum() > 0) {
return measurement.getOriginalVolumeCbm();
if (measurement != null) {
BigDecimal measuredVolume = positive(measurement.getTotalVolumeCbm());
BigDecimal declaredVolume = positive(measurement.getOriginalVolumeCbm());
if (measuredVolume != null || declaredVolume != null) {
if (measuredVolume == null) return declaredVolume;
if (declaredVolume == null) return measuredVolume;
return measuredVolume.max(declaredVolume);
}
}
if (order.getOrderId() == null || order.getOrderId() <= 0) {
throw new BizException(ResultCode.CONFLICT, "入库单缺少有效实测或客户申报体积");
@@ -200,6 +205,10 @@ public class MeasurementLocationOccupationService {
throw new BizException(ResultCode.CONFLICT, "入库单缺少有效实测或客户申报体积");
}
private static BigDecimal positive(BigDecimal value) {
return value != null && value.signum() > 0 ? value : null;
}
private static int requirePackageCount(InboundOrderEntity order) {
if (order.getTotalPackageCount() == null || order.getTotalPackageCount() <= 0) {
throw new BizException(ResultCode.CONFLICT, "入库单缺少有效总箱数");
@@ -144,6 +144,7 @@ class MeasurementLocationOccupationServiceTest {
InboundOrderEntity inbound = inbound();
inbound.setActualVolumeCbm(null);
InboundMeasurementEntity measurement = new InboundMeasurementEntity();
measurement.setTotalVolumeCbm(new BigDecimal("1.0000"));
measurement.setOriginalVolumeCbm(new BigDecimal("2.5000"));
when(workflow.findOwned(BUSINESS_TENANT, INBOUND)).thenReturn(inbound);
when(measurements.findLatestMeasurement(BUSINESS_TENANT, INBOUND)).thenReturn(measurement);
@@ -162,6 +163,32 @@ class MeasurementLocationOccupationServiceTest {
20, new BigDecimal("2.5000"), block("OCCUPIED", 3));
}
@Test
void reservesByCurrentMeasuredVolumeBeforeFrozenDeclaredVolume() {
InboundOrderEntity inbound = inbound();
inbound.setActualVolumeCbm(null);
InboundMeasurementEntity measurement = new InboundMeasurementEntity();
measurement.setTotalVolumeCbm(new BigDecimal("2.5000"));
measurement.setOriginalVolumeCbm(new BigDecimal("1.0000"));
when(workflow.findOwned(BUSINESS_TENANT, INBOUND)).thenReturn(inbound);
when(measurements.findLatestMeasurement(BUSINESS_TENANT, INBOUND)).thenReturn(measurement);
when(measurements.listWeights(BUSINESS_TENANT, INBOUND))
.thenReturn(confirmedWeights().subList(0, 1));
when(warehouse.reserveBlock(org.mockito.ArgumentMatchers.eq("internal-token"),
org.mockito.ArgumentMatchers.any())).thenReturn(ApiResponse.success(block("RESERVED", 3)));
when(warehouse.confirmBlock(org.mockito.ArgumentMatchers.eq("internal-token"),
org.mockito.ArgumentMatchers.any())).thenReturn(ApiResponse.success(block("OCCUPIED", 3)));
service.ensureForConfirmedWeight(BUSINESS_TENANT, INBOUND, OPERATOR, MEASUREMENT, 3);
verify(orderCargo, never()).measurementDeclaration(org.mockito.ArgumentMatchers.anyString(),
org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong());
verify(warehouse).reserveBlock(org.mockito.ArgumentMatchers.eq("internal-token"),
org.mockito.ArgumentMatchers.argThat(request -> request.requiredSlotCount() == 3));
verify(allocations).replaceBlock(BUSINESS_TENANT, INBOUND, WAREHOUSE,
20, new BigDecimal("2.5000"), block("OCCUPIED", 3));
}
@Test
void fallsBackToLatestOrderDeclarationWhenNoMeasurementBatchExists() {
InboundOrderEntity inbound = inbound();