diff --git a/scripts/admin-test-env-modules/phase4-overseas-pda-contract.test.mjs b/scripts/admin-test-env-modules/phase4-overseas-pda-contract.test.mjs index 823d7c048..b7707691f 100644 --- a/scripts/admin-test-env-modules/phase4-overseas-pda-contract.test.mjs +++ b/scripts/admin-test-env-modules/phase4-overseas-pda-contract.test.mjs @@ -62,6 +62,7 @@ test('PDA module covers the container-number receiving contract and excludes out assert.doesNotMatch(source, /requestOverseas\('POST', '\/api\/platform\/v1\/warehouse-admin'/) assert.doesNotMatch(source, /requestOverseas\('GET', '\/api\/platform\/v1\/warehouse-admin'/) assert.match(source, /receiving-containers\/current\/pallets\/resolve/) + assert.match(source, /const locationCode = resolvedPallet\.data\?\.locationCode \|\| pallet\.locationCode/) assert.match(source, /overseasWarehouseId, password/) assert.match(source, /inbound\?\.overseasWarehouseId/) assert.doesNotMatch(source, /const warehouseId = id\(inbound\?\.destinationWarehouseId\)/) diff --git a/scripts/admin-test-env-modules/phase4-overseas-pda.mjs b/scripts/admin-test-env-modules/phase4-overseas-pda.mjs index eebb2aaa0..ad3153a8b 100644 --- a/scripts/admin-test-env-modules/phase4-overseas-pda.mjs +++ b/scripts/admin-test-env-modules/phase4-overseas-pda.mjs @@ -203,14 +203,6 @@ async function verifyWarehouseQueries(context, token, inboundCode, pallet, desti && inventoryItems.every((item) => nonBlank(item?.skuCode) && Number(item?.availablePackages) > 0), `skuCodes=${[...new Set(inventoryItems.map((item) => item?.skuCode).filter(nonBlank))].join('|') || 'missing'}, availablePackages=${inventoryItems.reduce((total, item) => total + Number(item?.availablePackages || 0), 0)}; ${trace(inventory.response)}`, OPTIONS) - const location = await pda(context, token, 'POST', '完成入库后扫码查询库位', - '/api/pda/v1/last-leg/locations/resolve', { code: pallet.locationCode }) - context.assert(MODULE, '库位查询返回当前仓真实占用汇总', location.response, - success(location.response) && id(location.data?.locationId) === pallet.locationId - && location.data?.locationCode === pallet.locationCode - && Number(location.data?.occupiedPackages) > 0 && Number(location.data?.inventoryPositionCount) > 0, - `locationId=${id(location.data?.locationId) || 'missing'}; ${trace(location.response)}`, OPTIONS) - const resolvedPallet = await pda(context, token, 'POST', '完成入库后扫码查询托盘内容', '/api/pda/v1/last-leg/pallets/resolve', { code: pallet.palletCode }) context.assert(MODULE, '托盘查询返回当前位置与库存明细', resolvedPallet.response, @@ -220,6 +212,15 @@ async function verifyWarehouseQueries(context, token, inboundCode, pallet, desti && Number(resolvedPallet.data?.occupiedPackages) > 0, `palletId=${id(resolvedPallet.data?.palletId) || 'missing'}; ${trace(resolvedPallet.response)}`, OPTIONS) + const locationCode = resolvedPallet.data?.locationCode || pallet.locationCode + const location = await pda(context, token, 'POST', '完成入库后扫码查询库位', + '/api/pda/v1/last-leg/locations/resolve', { code: locationCode }) + context.assert(MODULE, '库位查询返回当前仓真实占用汇总', location.response, + success(location.response) && id(location.data?.locationId) === pallet.locationId + && location.data?.locationCode === locationCode + && Number(location.data?.occupiedPackages) > 0 && Number(location.data?.inventoryPositionCount) > 0, + `locationId=${id(location.data?.locationId) || 'missing'}; ${trace(location.response)}`, OPTIONS) + const history = await pda(context, token, 'GET', '查询当前仓管PDA作业历史', '/api/pda/v1/last-leg/operations?page=1&size=50') const historyRows = records(history.data) diff --git a/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/service/WarehousePalletBatchService.java b/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/service/WarehousePalletBatchService.java index d649a00c0..cf2548c28 100644 --- a/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/service/WarehousePalletBatchService.java +++ b/warehouse-overseas-service/src/main/java/com/baiyue/warehouse/service/WarehousePalletBatchService.java @@ -21,6 +21,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.beans.factory.annotation.Value; import java.math.BigDecimal; import java.nio.charset.StandardCharsets; @@ -46,6 +47,8 @@ public class WarehousePalletBatchService { @Resource private WarehouseResourceLockRepository lockRecords; @Resource private WarehouseResourceRepository repository; @Resource private ObjectMapper objectMapper; + @Value("${baiyue.pallet.auto-created-unit-price:1.00}") + private BigDecimal autoCreatedPalletUnitPrice; @Transactional public WarehousePalletBatchResponse ensureReserved(WarehousePalletBatchRequests.EnsureReserved request) { @@ -81,7 +84,8 @@ public class WarehousePalletBatchService { for (WarehousePalletBatchRequests.Item requested : normalized.items()) { Long palletId = resources.createPallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, normalized.warehouseId(), new PalletRequests.SaveRequest(null, requested.palletType(), null, - BigDecimal.ZERO, "IDLE", null, "Auto-created for inbound plan " + requested.inboundPlanNo(), + requiredAutoCreatedPalletUnitPrice(), "IDLE", null, + "Auto-created for inbound plan " + requested.inboundPlanNo(), requested.fbaWarehouseCode())); WarehousePalletEntity pallet = resources.pallet(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE, normalized.warehouseId(), palletId); @@ -110,6 +114,13 @@ public class WarehousePalletBatchService { return response(batch, created, false); } + private BigDecimal requiredAutoCreatedPalletUnitPrice() { + if (autoCreatedPalletUnitPrice == null || autoCreatedPalletUnitPrice.signum() <= 0) { + throw new IllegalStateException("Auto-created pallet unit price must be greater than zero"); + } + return autoCreatedPalletUnitPrice.setScale(2, java.math.RoundingMode.HALF_UP); + } + @Transactional public WarehousePalletBatchResponse confirm(WarehousePalletBatchRequests.Confirm request) { WarehousePalletBatchRequests.Confirm normalized = normalize(request); diff --git a/warehouse-overseas-service/src/main/resources/application.yml b/warehouse-overseas-service/src/main/resources/application.yml index 2f2a1d1b6..a62da5112 100644 --- a/warehouse-overseas-service/src/main/resources/application.yml +++ b/warehouse-overseas-service/src/main/resources/application.yml @@ -39,6 +39,8 @@ spring: management.endpoints.web.exposure.include: health,info,prometheus baiyue: + pallet: + auto-created-unit-price: ${AUTO_CREATED_PALLET_UNIT_PRICE:1.00} clients: domestic-warehouse: url: ${DOMESTIC_WAREHOUSE_URL:} diff --git a/warehouse-overseas-service/src/test/java/com/baiyue/warehouse/service/WarehousePalletBatchServiceTest.java b/warehouse-overseas-service/src/test/java/com/baiyue/warehouse/service/WarehousePalletBatchServiceTest.java index 49157c4a2..fca4795bf 100644 --- a/warehouse-overseas-service/src/test/java/com/baiyue/warehouse/service/WarehousePalletBatchServiceTest.java +++ b/warehouse-overseas-service/src/test/java/com/baiyue/warehouse/service/WarehousePalletBatchServiceTest.java @@ -26,6 +26,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.util.ReflectionTestUtils; import java.util.List; +import java.math.BigDecimal; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -62,6 +63,7 @@ class WarehousePalletBatchServiceTest { ReflectionTestUtils.setField(service, "lockRecords", lockRecords); ReflectionTestUtils.setField(service, "repository", repository); ReflectionTestUtils.setField(service, "objectMapper", new ObjectMapper()); + ReflectionTestUtils.setField(service, "autoCreatedPalletUnitPrice", new BigDecimal("1.00")); } @Test @@ -74,8 +76,11 @@ class WarehousePalletBatchServiceTest { assertThat(response.status()).isEqualTo("RESERVED"); assertThat(response.items()).extracting(item -> item.customerId()).containsExactly(CUSTOMER_A, CUSTOMER_B); ArgumentCaptor scope = ArgumentCaptor.forClass(Long.class); - verify(resources, times(2)).createPallet(scope.capture(), anyLong(), any(PalletRequests.SaveRequest.class)); + ArgumentCaptor palletRequests = ArgumentCaptor.forClass(PalletRequests.SaveRequest.class); + verify(resources, times(2)).createPallet(scope.capture(), anyLong(), palletRequests.capture()); assertThat(scope.getAllValues()).containsOnly(WarehouseResourceService.PUBLIC_RESOURCE_SCOPE); + assertThat(palletRequests.getAllValues()).extracting(PalletRequests.SaveRequest::unitPrice) + .containsOnly(new BigDecimal("1.00")); verify(batches, never()).lockByKey(WAREHOUSE, "container-1"); ArgumentCaptor reservations = ArgumentCaptor.forClass(WarehouseResourceLockRequests.ReserveRequest.class);