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) }}