From dbd51b7fc82fa50447eb0f7c8966247939294e6d Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 7 Sep 2026 16:36:21 +0800 Subject: [PATCH] fix: block unsafe container plan actions --- .../pages/LastMileOrdersView.behavior.test.ts | 23 +++++++++++++++++++ .../pages/LastMileOrdersView.vue | 18 +++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts b/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts index 6646c072..c3cda92f 100644 --- a/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts +++ b/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts @@ -285,6 +285,29 @@ describe('LastMileOrdersView pending order and container conversion', () => { expect(getContainerPlanProgress).not.toHaveBeenCalled() }) + it('keeps an invalid historical cabinet readable while blocking plan generation', async () => { + const invalid = { + ...summary, + overseasWarehouseId: null, + overseasWarehouseCode: null, + overseasWarehouseName: null, + blockingReason: '柜内接柜仓业务快照不一致', + } + vi.mocked(listContainerPlanProgress).mockResolvedValueOnce({ records: [invalid], page: 1, size: 10, total: 1, pages: 1 } as never) + vi.mocked(getContainerPlanProgress).mockResolvedValueOnce({ summary: invalid, orders: [] } as never) + const wrapper = await mountView() + await wrapper.findAll('.el-radio-button').find((item) => item.text().startsWith('柜子'))!.trigger('click') + await flushPromises() + + expect(wrapper.text()).toContain('柜内接柜仓业务快照不一致') + expect((button(wrapper, '生成入库计划')!.element as HTMLButtonElement).disabled).toBe(true) + await wrapper.get('.container-workbench-card__detail').trigger('click') + await flushPromises() + expect(getContainerPlanProgress).toHaveBeenCalledWith(bookingId) + expect(document.body.textContent).toContain('柜子详情 · CONT-15') + expect(convertLastMileContainerToInboundPlans).not.toHaveBeenCalled() + }) + it('shows the receiving warehouse and changes it from ACTIVE OVERSEAS master data with versioning', async () => { vi.mocked(listAllPlatformWarehouses).mockResolvedValueOnce([receivingWarehouse] as never) const wrapper = await mountView() diff --git a/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue b/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue index 629fc165..9b53f9c6 100644 --- a/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue +++ b/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue @@ -181,7 +181,20 @@ function formatDateTime(value: string | null | undefined) { return value ? value.replace('T', ' ').slice(0, 19) : '—' } function canGenerateContainerPlans(container: ContainerPlanProgressSummaryDto) { - return Boolean(container.containerNo) && container.pendingPlanCount > 0 + return Boolean(container.containerNo + && container.overseasWarehouseId + && container.overseasWarehouseCode + && container.overseasWarehouseName + && container.assignmentVersion >= 0 + && container.pendingPlanCount > 0) +} +function containerSnapshotBlockReason(container: ContainerPlanProgressSummaryDto) { + if (!container.containerNo) return container.blockingReason || '来源柜真实集装箱号缺失、格式无效或存在漂移' + if (!container.overseasWarehouseId || !container.overseasWarehouseCode + || !container.overseasWarehouseName || container.assignmentVersion < 0) { + return '柜内接柜仓业务快照不一致' + } + return '' } function pendingInboundCodeCount(container: ContainerPlanProgressSummaryDto) { return Math.max(0, container.inboundCodeCount - container.plannedInboundCodeCount) @@ -498,7 +511,8 @@ onMounted(() => { void load() }) {{ container.containerNo || '柜号待补充' }} 海外接柜仓{{ receivingWarehouseLabel(container) }} - {{ container.receivingWarehouseLockReason }} + {{ containerSnapshotBlockReason(container) }} + {{ container.receivingWarehouseLockReason }} 计划到仓{{ formatDateTime(container.plannedArrivalAt) }}