From afa49bf1f1373e71c59a7034c21821342802fa75 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 14 Sep 2026 14:35:30 +0800 Subject: [PATCH] fix: remove sealed smart-loading rows by pallet --- .../api/platformContainerLoading.test.ts | 13 +++++++++- .../api/platformContainerLoading.ts | 8 ++++++ .../pages/GlobalSmartLoadingView.test.ts | 25 +++++++++++++++++++ .../pages/GlobalSmartLoadingView.vue | 15 +++++++++-- 4 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/modules/container-loading/api/platformContainerLoading.test.ts b/src/modules/container-loading/api/platformContainerLoading.test.ts index df860ff6..812ad0ff 100644 --- a/src/modules/container-loading/api/platformContainerLoading.test.ts +++ b/src/modules/container-loading/api/platformContainerLoading.test.ts @@ -4,7 +4,7 @@ import { resolve } from 'node:path' import { http } from '@/shared/api/http' import { adjustSmartLoadingItem, assignPendingReviewSmartLoadingOrder, assignSmartLoadingGroup, assignSmartLoadingItem, assignSmartLoadingPallet, getContainer, - listContainers, listSmartLoadingCandidates, listSmartLoadingWorkbenchContainers, removeAllUnpickedSmartLoadingItems, removeSmartLoadingGroup, removeSmartLoadingItem, + listContainers, listSmartLoadingCandidates, listSmartLoadingWorkbenchContainers, removeAllUnpickedSmartLoadingItems, removeSmartLoadingGroup, removeSmartLoadingItem, removeSmartLoadingPallet, getContainerClearance, downloadContainerClearance, uploadContainerClearance, completeContainerClearance, getContainerOverview, updateContainerPickupCode, markContainerException, cancelContainerException, uploadContainerDocument, downloadContainerDocument, downloadContainerPdaPhoto, getCustomerContainerTransitSummary, @@ -131,6 +131,17 @@ describe('platform container loading API', () => { ) }) + it('removes a sealed pallet through the whole-pallet command', async () => { + vi.mocked(http.delete).mockResolvedValue({ code: '200', data: plan }) + + await removeSmartLoadingPallet('10', '9007199254740998', 6) + + expect(http.delete).toHaveBeenCalledWith( + '/platform/v1/first-leg/smart-loading/plans/10/pallet-assignments/9007199254740998', + { data: { expectedPlanVersion: 6, operationId: expect.stringContaining('remove-pallet-') } }, + ) + }) + it('uses the dedicated provisional assignment command for a pending-review order', async () => { vi.mocked(http.post).mockResolvedValue({ code: '200', data: plan }) diff --git a/src/modules/container-loading/api/platformContainerLoading.ts b/src/modules/container-loading/api/platformContainerLoading.ts index 19c383ac..c5c163ca 100644 --- a/src/modules/container-loading/api/platformContainerLoading.ts +++ b/src/modules/container-loading/api/platformContainerLoading.ts @@ -395,6 +395,14 @@ export async function removeSmartLoadingItem(planId: string, itemId: string, exp return plan(unwrapApiResponse(response)) } +export async function removeSmartLoadingPallet(planId: string, palletId: string, expectedPlanVersion: number) { + const response = await http.delete, ApiEnvelope>( + `${smartLoadingPath}/plans/${encodeURIComponent(planId)}/pallet-assignments/${encodeURIComponent(palletId)}`, + { data: { expectedPlanVersion, operationId: operationId('remove-pallet') } }, + ) + return plan(unwrapApiResponse(response)) +} + export async function removeSmartLoadingGroup(planId: string, groupId: string, expectedPlanVersion: number) { const response = await http.delete, ApiEnvelope>( `${smartLoadingPath}/plans/${encodeURIComponent(planId)}/group-assignments/${encodeURIComponent(groupId)}`, diff --git a/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts b/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts index aff760e1..ac393792 100644 --- a/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts +++ b/src/modules/container-loading/pages/GlobalSmartLoadingView.test.ts @@ -22,6 +22,7 @@ import { removeAllUnpickedSmartLoadingItems, removeSmartLoadingGroup, removeSmartLoadingItem, + removeSmartLoadingPallet, } from '../api/platformContainerLoading' const { routerPush } = vi.hoisted(() => ({ routerPush: vi.fn() })) @@ -50,6 +51,7 @@ vi.mock('../api/platformContainerLoading', () => ({ adjustSmartLoadingItem: vi.fn(), removeSmartLoadingItem: vi.fn(), removeSmartLoadingGroup: vi.fn(), + removeSmartLoadingPallet: vi.fn(), removeAllUnpickedSmartLoadingItems: vi.fn(), pushSmartLoadingPreload: vi.fn(), })) @@ -861,6 +863,29 @@ describe('GlobalSmartLoadingView', () => { expect(wrapper.findAll('button').some((button) => button.text().includes('移除未拣'))).toBe(false) }) + it('removes a sealed pallet row through the whole-pallet command', async () => { + const palletItem = { + ...plan.items[0], unitType: 'SEALED_PALLET' as const, palletId: '801', palletNo: 'DP-260914-0021', + indivisible: true, packageCount: 10, pickedPackageCount: 0, minPackageCount: 10, + canAdjust: false, canRemove: true, + } + const palletPlan = { ...plan, items: [palletItem] } + const emptyPlan = { ...palletPlan, version: 3, items: [] } + vi.mocked(getSmartLoadingPlanByBooking).mockResolvedValue(palletPlan) + vi.mocked(removeSmartLoadingPallet).mockResolvedValue(emptyPlan) + + const wrapper = mount(GlobalSmartLoadingView, { global: { plugins: [ElementPlus] } }) + await flushPromises() + const row = wrapper.findAll('tr').find((candidateRow) => candidateRow.text().includes('DP-260914-0021')) + expect(row).toBeDefined() + + await row!.find('.el-button--danger').trigger('click') + await flushPromises() + + expect(removeSmartLoadingPallet).toHaveBeenCalledWith(plan.id, '801', 2) + expect(removeSmartLoadingItem).not.toHaveBeenCalled() + }) + it('renders final completion capability as read-only with the server reason', async () => { vi.mocked(getSmartLoadingPlanByBooking).mockResolvedValue({ ...plan, diff --git a/src/modules/container-loading/pages/GlobalSmartLoadingView.vue b/src/modules/container-loading/pages/GlobalSmartLoadingView.vue index 53714eb2..3e05c6a7 100644 --- a/src/modules/container-loading/pages/GlobalSmartLoadingView.vue +++ b/src/modules/container-loading/pages/GlobalSmartLoadingView.vue @@ -26,6 +26,7 @@ import { removeAllUnpickedSmartLoadingItems, removeSmartLoadingGroup, removeSmartLoadingItem, + removeSmartLoadingPallet, } from '../api/platformContainerLoading' import type { SmartLoadingCandidate, @@ -585,10 +586,14 @@ async function remove(source: object) { const item = itemRow(source) if (!plan.value || !item.canRemove) return const row = source as SmartLoadingPlanRow + const sealedPallet = item.unitType === 'SEALED_PALLET' && Boolean(item.palletId) const confirmed = await ElMessageBox.confirm(row.coLoadGroup ? `确认整组移除 ${row.coLoadGroup.groupNo}(${groupMemberLabel(row.coLoadGroup)}、${row.packageCount} 箱)吗?组内所有入仓片段将联动移除。` - : `确认从当前柜次移除入仓码“${item.inboundCode || '—'}”的 ${item.packageCount} 箱吗?`, row.coLoadGroup ? '移除同柜不可拆组' : '移除装柜明细', { - type: 'warning', confirmButtonText: row.coLoadGroup ? '移除整组' : '移除', cancelButtonText: '取消', + : sealedPallet + ? `确认从当前柜次整托移除托盘“${item.palletNo || '—'}”(${item.packageCount} 箱)吗?` + : `确认从当前柜次移除入仓码“${item.inboundCode || '—'}”的 ${item.packageCount} 箱吗?`, + row.coLoadGroup ? '移除同柜不可拆组' : sealedPallet ? '整托移除' : '移除装柜明细', { + type: 'warning', confirmButtonText: row.coLoadGroup ? '移除整组' : sealedPallet ? '整托移除' : '移除', cancelButtonText: '取消', }).catch(() => false) if (!confirmed || !plan.value) return await mutate(async () => { @@ -598,6 +603,12 @@ async function remove(source: object) { ElMessage.success(`同柜不可拆组 ${row.coLoadGroup.groupNo} 已整组移除`) return } + if (sealedPallet && item.palletId) { + acceptPlan(await removeSmartLoadingPallet(plan.value!.id, item.palletId, plan.value!.version)) + await loadCandidateData() + ElMessage.success(`托盘 ${item.palletNo || '—'} 已整托移除`) + return + } let current = plan.value! for (const original of item.sourceItems) { const currentItem = current.items.find((value) => value.id === original.id)