From 058b0778a2cc0b8e3701adc327475c85bb64b0de Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 5 Oct 2026 02:13:24 +0800 Subject: [PATCH] fix(overseas): reuse original resource command after reopening conversion --- .../overseas-warehouse/api/lastMileOrders.ts | 1 + .../pages/LastMileOrdersView.behavior.test.ts | 31 +++++++++++++++++++ .../pages/LastMileOrdersView.vue | 8 +++-- .../containerPlanPreviewContract.test.ts | 6 ++-- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/modules/overseas-warehouse/api/lastMileOrders.ts b/src/modules/overseas-warehouse/api/lastMileOrders.ts index dc32f320..f43cde9a 100644 --- a/src/modules/overseas-warehouse/api/lastMileOrders.ts +++ b/src/modules/overseas-warehouse/api/lastMileOrders.ts @@ -265,6 +265,7 @@ export interface ContainerInboundPlanPreviewGroupDto { } export interface ContainerInboundPlanPreviewDto { + resourceRetry?: { idempotencyKey: string; snapshotVersion: number; snapshotHash: string } | null sourceContainerBookingId: string containerNo: string | null overseasWarehouseId: string | null diff --git a/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts b/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts index 11ced91b..002c4f7c 100644 --- a/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts +++ b/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts @@ -724,6 +724,37 @@ describe('LastMileOrdersView pending order and container conversion', () => { expect((button(wrapper, '修改接柜仓')!.element as HTMLButtonElement).disabled).toBe(false) }) + it('restores the original resource command after reopening a locally committed cabinet', async () => { + vi.mocked(listContainerPlanProgress).mockResolvedValueOnce({ + records: [{ ...summary, pendingPlanCount: 0, resourcePendingPlanCount: 1, allPlansReady: true }], + page: 1, size: 10, total: 1, pages: 1, + }) + const reopenedPreview = { + ...preview, snapshotVersion: 10, snapshotHash: 'b'.repeat(64), + groups: preview.groups.map((group) => ({ + ...group, destinationType: 'FBA' as const, + orders: group.orders.map((order) => ({ + ...order, destinationType: 'FBA' as const, fbaWarehouseCode: 'ONT8', + readiness: 'RESOURCE_PENDING' as const, existingPlanNo: 'LIP-ORIGINAL', plannedPalletCount: 5, + })), + })), + resourceRetry: { idempotencyKey: 'original-container-command', snapshotVersion: 9, snapshotHash: 'a'.repeat(64) }, + } + vi.mocked(getContainerInboundPlanPreview).mockResolvedValueOnce(reopenedPreview) + const wrapper = await mountView() + await openHiddenContainerWorkbench(wrapper) + await button(wrapper, '重试生成托盘码')!.trigger('click') + await flushPromises() + const confirm = [...document.body.querySelectorAll('button')] + .find((item) => item.textContent?.includes('确认生成')) as HTMLButtonElement + expect(confirm.disabled).toBe(false) + confirm.click() + await flushPromises() + expect(convertLastMileContainerToInboundPlans).toHaveBeenCalledWith({ + sourceContainerBookingId: bookingId, snapshotVersion: 9, snapshotHash: 'a'.repeat(64), + }, 'original-container-command') + }) + it('renders the all-cabinet empty state and unit', async () => { vi.mocked(listContainerPlanProgress).mockResolvedValueOnce({ records: [], page: 1, size: 10, total: 0, pages: 0 }) const wrapper = await mountView() diff --git a/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue b/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue index f950e4c0..3196fc25 100644 --- a/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue +++ b/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue @@ -740,7 +740,8 @@ async function loadContainerPreview(sourceContainerBookingId = selectedContainer const preview = await getContainerInboundPlanPreview(sourceContainerBookingId) if (request !== containerPreviewRequest || selectedContainerBookingId.value !== sourceContainerBookingId || !containerConvertOpen.value) return containerPreview.value = preview - if (!preserveResult) containerConversionIdempotencyKey = idempotencyKey('container-inbound-plan') + if (!preserveResult) containerConversionIdempotencyKey = preview.resourceRetry + ? preview.resourceRetry.idempotencyKey : idempotencyKey('container-inbound-plan') } catch (error) { if (request !== containerPreviewRequest || selectedContainerBookingId.value !== sourceContainerBookingId || !containerConvertOpen.value) return containerPreviewError.value = getApiErrorDetails(error, '加载整柜入库计划预览失败,请重试').message @@ -757,6 +758,7 @@ async function confirmContainerInboundPlans() { if (!preview?.ready || preview.pendingOrderCount <= 0 || actionLoading.value) return if (!containerConversionIdempotencyKey) containerConversionIdempotencyKey = idempotencyKey('container-inbound-plan') const bookingId = preview.sourceContainerBookingId + const commandSnapshot = preview.resourceRetry ?? preview const existingPlanNos = new Set(preview.groups.flatMap((group) => group.orders) .filter((order) => order.readiness !== 'READY' && order.existingPlanNo) .map((order) => String(order.existingPlanNo))) @@ -765,8 +767,8 @@ async function confirmContainerInboundPlans() { try { const plans = await convertLastMileContainerToInboundPlans({ sourceContainerBookingId: bookingId, - snapshotVersion: preview.snapshotVersion, - snapshotHash: preview.snapshotHash, + snapshotVersion: commandSnapshot.snapshotVersion, + snapshotHash: commandSnapshot.snapshotHash, }, containerConversionIdempotencyKey) if (selectedContainerBookingId.value !== bookingId || !containerConvertOpen.value) return const existingPlanCount = plans.filter((plan) => existingPlanNos.has(plan.planNo)).length diff --git a/src/modules/overseas-warehouse/pages/containerPlanPreviewContract.test.ts b/src/modules/overseas-warehouse/pages/containerPlanPreviewContract.test.ts index ddbd5c6c..36552458 100644 --- a/src/modules/overseas-warehouse/pages/containerPlanPreviewContract.test.ts +++ b/src/modules/overseas-warehouse/pages/containerPlanPreviewContract.test.ts @@ -28,8 +28,10 @@ describe('container inbound plan preview contract', () => { expect(pageSource).toContain('request !== containerPreviewRequest || selectedContainerBookingId.value !== sourceContainerBookingId || !containerConvertOpen.value') expect(pageSource).toContain('containerPreviewRequest += 1') expect(pageSource.match(/await convertLastMileContainerToInboundPlans\(\{/g)).toHaveLength(1) - expect(pageSource).toContain('snapshotVersion: preview.snapshotVersion') - expect(pageSource).toContain('snapshotHash: preview.snapshotHash') + expect(pageSource).toContain('const commandSnapshot = preview.resourceRetry ?? preview') + expect(pageSource).toContain('snapshotVersion: commandSnapshot.snapshotVersion') + expect(pageSource).toContain('snapshotHash: commandSnapshot.snapshotHash') + expect(pageSource).toContain('preview.resourceRetry.idempotencyKey') expect(pageSource).toContain('containerConversionIdempotencyKey') expect(pageSource).toContain(':confirm-disabled="containerConfirmDisabled"') })