diff --git a/AGENTS.md b/AGENTS.md index ecc7dd71..024643ee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -76,7 +76,7 @@ | 关键词 | 页面/路由入口 | API 与联查 | |---|---|---| -| 尾程订单控制与柜级入仓计划转换 | `modules/overseas-warehouse/pages/LastMileOrdersView.vue`、`LastMileOrderDetailView.vue` | 柜子工作台按 `sourceContainerBookingId` 消费 `/orders/container-summaries`;服务端分页返回全部稳定来源柜,计划已经齐全的柜仍保留用于接柜仓查询和修改,并按冻结 `plannedArrivalAt` 升序、空值最后排序。详情返回全柜订单且不受列表分页截断;单票手工计划保存后,由服务端在整柜最后一票计划齐全时自动生成并绑定全柜托盘码,一票柜立即生成;`resourcePendingPlanCount` 只表示自动生成异常的重试入口,不是正常人工步骤。柜级确认弹框先调用 `/inbound-plans/container-preview`,按服务端 FBA/一件代发/私人地址分组展示托数、`readiness/blockers`,再把同一 `snapshotVersion/snapshotHash` 原样提交 `/inbound-plans/convert-container`;前端不计算托数、不逐票建计划、不预占托盘,快照冲突后重新获取预览。服务端只为剩余订单逐票生成独立计划,并为异常遗留的人工计划补齐真实托盘,整批原子且重放不得产生第二批资源。单票完整入库计划、暂扣/解除和八行人工节点均从 `api/lastMileOrders.ts` 提交订单版本与幂等键;入仓码只读展示并提交订单冻结值,不允许人工改写,暂扣资格、接柜仓锁定原因和操作能力只消费服务端结果,人工节点一经保存不得回退柜级节点。转仓候选只取 `modules/iam/api/platformIam.ts` 的平台公共 `ACTIVE + FBA` 仓主档;Backend `lastleg-service/` | +| 尾程订单控制与柜级入仓计划转换 | `modules/overseas-warehouse/pages/LastMileOrdersView.vue`、`LastMileOrderDetailView.vue` | 柜子工作台按 `sourceContainerBookingId` 消费 `/orders/container-summaries`;服务端分页返回全部稳定来源柜,计划已经齐全的柜仍保留用于接柜仓查询和修改,并按冻结 `plannedArrivalAt` 升序、空值最后排序。详情返回全柜订单且不受列表分页截断;单票手工计划保存后,由服务端在整柜最后一票计划齐全时自动生成并绑定全柜托盘码,一票柜立即生成;`resourcePendingPlanCount` 只表示自动生成异常的重试入口,不是正常人工步骤。柜级确认弹框先调用 `/inbound-plans/container-preview`,按服务端 FBA/一件代发/私人地址分组展示头程已有、海外仓补充和最终托数以及 `readiness/blockers`;最终托数不得少于头程已有托盘码,差额连续补码且不阻断流程。前端不计算托数、不逐票建计划、不预占托盘,再把同一 `snapshotVersion/snapshotHash` 原样提交 `/inbound-plans/convert-container`,快照冲突后重新获取预览。服务端只为剩余订单逐票生成独立计划,并为异常遗留的人工计划补齐真实托盘,整批原子且重放不得产生第二批资源。单票完整入库计划、暂扣/解除和八行人工节点均从 `api/lastMileOrders.ts` 提交订单版本与幂等键;入仓码只读展示并提交订单冻结值,不允许人工改写,暂扣资格、接柜仓锁定原因和操作能力只消费服务端结果,人工节点一经保存不得回退柜级节点。转仓候选只取 `modules/iam/api/platformIam.ts` 的平台公共 `ACTIVE + FBA` 仓主档;Backend `lastleg-service/` | | 入仓单、入仓计划、FBA 预约 | `modules/overseas-warehouse/pages/InboundOrdersView.vue`、`InboundOrderDetailView.vue` | 列表/预约 `modules/overseas-warehouse/api/inboundOrders.ts`,计划列表/详情 `inboundPlans.ts`;Backend `lastleg-service/inboundplan/` | | 排车查询、智能预排与转派送 | `modules/overseas-warehouse/pages/DispatchesView.vue`、`DispatchDetailView.vue`、`components/SmartDispatchDialog.vue` | `modules/overseas-warehouse/api/dispatches.ts`;Backend `lastleg-service/dispatch/`、`delivery/`;覆盖详情、候选、草稿柜、托盘锁、`pre-arrange` 和 `transfer-delivery`。页面能力必须由正式路由、API 调用和测试共同证明 | | 海外出库与派送 | `pages/OutboundsView.vue`、`OutboundDetailView.vue`、`DeliveryOrdersView.vue`、`DeliveryOrderDetailView.vue` | `api/outbounds.ts`、`deliveryOrders.ts`;出库列表按类型筛选并展示中文类型。一件代发新建弹窗直接跨客户加载服务端可用候选,不单独展示客户筛选,海外仓必选并优先默认洛杉矶仓;订单条件可按订单号、入库单号、客户、托盘号、SKU 或品名查询/重置,以托盘+SKU 行分页多选。提交时从所选行解析唯一客户,并校验所选行属于当前唯一海外仓,不要求先选客户。退货出库客户下拉同时展示客户名称与联系电话并支持手机号检索,客户和仓库选项独立容错加载;选择客户后须立即按当前默认/已选海外仓加载库存。SKU 与箱号查询均使用输入态/已查询态分离,只允许点击查询按钮后生效;支持英文逗号批量条件,查询时清除空格并按任一条件命中,左右列表分别提供每页 5/10/20/50 条选择。SKU 列表只展示 `availableQuantity > 0` 的未占用可用数量,合箱后已扣减为零的 SKU 不再作为可选库存显示,实际作业以可用箱唛选择和箱内 SKU 明细扣减为准。取消、派送列表/详情及退回入口对应 Backend `lastleg-service/delivery/`、`dropship/` | diff --git a/src/modules/overseas-warehouse/api/lastMileOrders.ts b/src/modules/overseas-warehouse/api/lastMileOrders.ts index c07cd5d1..d104e71e 100644 --- a/src/modules/overseas-warehouse/api/lastMileOrders.ts +++ b/src/modules/overseas-warehouse/api/lastMileOrders.ts @@ -60,7 +60,7 @@ export interface LastMileOrderSummaryDto { transferWarehouseCode?: string | null fbaWarehouseCode?: string | null containerNo?: string | null - containerStatus?: string | null + containerNode?: string | null abnormal?: boolean | null detained?: boolean | null holdChargeable?: boolean | null @@ -229,6 +229,9 @@ export interface ContainerInboundPlanPreviewOrderDto { packageCount: number volumeCbm: number suggestedPalletCount: number | null + sourcePalletCount: number + targetPalletCount: number + supplementPalletCount: number plannedPalletCount: number | null existingPlanNo: string | null planStatus: string | null @@ -245,6 +248,8 @@ export interface ContainerInboundPlanPreviewGroupDto { orderCount: number pendingOrderCount: number pendingPalletCount: number + sourcePalletCount: number + supplementPalletCount: number existingPlannedPalletCount: number suggestedPalletCount: number plannedPalletCount: number @@ -264,6 +269,8 @@ export interface ContainerInboundPlanPreviewDto { blockedOrderCount: number pendingOrderCount: number pendingPalletCount: number + sourcePalletCount: number + supplementPalletCount: number existingPlannedPalletCount: number totalSuggestedPalletCount: number totalPlannedPalletCount: number diff --git a/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts b/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts index ec2b8832..77aefdc3 100644 --- a/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts +++ b/src/modules/overseas-warehouse/pages/LastMileOrdersView.behavior.test.ts @@ -71,17 +71,20 @@ const preview = { overseasWarehouseId: summary.overseasWarehouseId, overseasWarehouseCode: summary.overseasWarehouseCode, overseasWarehouseName: summary.overseasWarehouseName, snapshotVersion: 9, snapshotHash: 'a'.repeat(64), totalOrderCount: 5, readyOrderCount: 5, blockedOrderCount: 0, pendingOrderCount: 5, - pendingPalletCount: 5, existingPlannedPalletCount: 0, totalSuggestedPalletCount: 5, + pendingPalletCount: 5, sourcePalletCount: 4, supplementPalletCount: 1, + existingPlannedPalletCount: 0, totalSuggestedPalletCount: 5, totalPlannedPalletCount: 0, ready: true, groups: [{ destinationType: 'FBA', destinationWarehouseId: null, destinationWarehouseCode: 'ONT8', destinationWarehouseName: 'Ontario FBA', orderCount: 5, pendingOrderCount: 5, pendingPalletCount: 5, + sourcePalletCount: 4, supplementPalletCount: 1, existingPlannedPalletCount: 0, suggestedPalletCount: 5, plannedPalletCount: 0, orders: [{ customerId, customerName: '测试客户', orderId: '2092873463568596994', businessOrderNo: 'LMO-1', inboundCode: 'IN-1', orderType: 'FIRST_LEG', destinationType: 'FBA', destinationWarehouseId: null, destinationWarehouseCode: 'ONT8', destinationWarehouseName: 'Ontario FBA', packageCount: 10, - volumeCbm: 1, suggestedPalletCount: 5, plannedPalletCount: null, existingPlanNo: null, + volumeCbm: 1, suggestedPalletCount: 5, sourcePalletCount: 4, targetPalletCount: 5, + supplementPalletCount: 1, plannedPalletCount: null, existingPlanNo: null, planStatus: null, orderVersion: 3, readiness: 'READY', blockers: [], }], }], @@ -455,7 +458,8 @@ describe('LastMileOrdersView pending order and container conversion', () => { await openHiddenContainerWorkbench(wrapper) await button(wrapper, '生成入库计划')!.trigger('click') await flushPromises() - expect(document.body.textContent).toContain('预览已就绪,本次将处理 5 票订单、生成或补齐 5 个托盘码') + expect(document.body.textContent).toContain('头程已有 4 个托盘码,海外仓补充 1 个,最终生成 5 个托盘') + expect(document.body.textContent).toContain('头程已有 4 托 / 海外仓补充 1 托') const confirm = [...document.body.querySelectorAll('button')].find((item) => item.textContent?.includes('确认生成')) as HTMLButtonElement expect(confirm.disabled).toBe(false) confirm.click() diff --git a/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue b/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue index 9e8e1082..05d0177c 100644 --- a/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue +++ b/src/modules/overseas-warehouse/pages/LastMileOrdersView.vue @@ -834,13 +834,13 @@ onMounted(() => { void load() })
{{ [containerPreview.overseasWarehouseCode, containerPreview.overseasWarehouseName].filter(Boolean).join(' / ') || '未关联海外仓' }}
-
本次新增托盘码{{ containerPreview.pendingPalletCount }}
+
头程已有托盘码{{ containerPreview.sourcePalletCount }}
+
海外仓补充托盘码{{ containerPreview.supplementPalletCount }}
+
最终生成托盘{{ containerPreview.pendingPalletCount }}
本次处理订单{{ containerPreview.pendingOrderCount }}
-
已有计划托盘{{ containerPreview.existingPlannedPalletCount }}
-
阻断订单{{ containerPreview.blockedOrderCount }}
- +
生成完成新建 {{ containerConversionResult.newPlanCount }} 个 / 已有 {{ containerConversionResult.existingPlanCount }} 个
@@ -854,8 +854,8 @@ onMounted(() => { void load() })
- {{ previewGroupTitle(group) }}:{{ group.pendingPalletCount }}托 - 本次处理 {{ group.pendingOrderCount }} 票 / 已有 {{ group.existingPlannedPalletCount }} 托 / 共 {{ group.orderCount }} 票 + {{ previewGroupTitle(group) }}:最终 {{ group.pendingPalletCount }} 托 + 头程已有 {{ group.sourcePalletCount }} 托 / 海外仓补充 {{ group.supplementPalletCount }} 托 / 本次处理 {{ group.pendingOrderCount }} 票
@@ -863,7 +863,9 @@ onMounted(() => { void load() }) - + + + diff --git a/src/modules/overseas-warehouse/pages/containerPlanPreviewContract.test.ts b/src/modules/overseas-warehouse/pages/containerPlanPreviewContract.test.ts index 7a808bbc..422dc445 100644 --- a/src/modules/overseas-warehouse/pages/containerPlanPreviewContract.test.ts +++ b/src/modules/overseas-warehouse/pages/containerPlanPreviewContract.test.ts @@ -13,7 +13,8 @@ describe('container inbound plan preview contract', () => { it('renders backend groups, pallet totals, readiness and blockers without local grouping or sorting', () => { expect(pageSource).toContain('containerPreview.pendingPalletCount') - expect(pageSource).toContain('containerPreview.existingPlannedPalletCount') + expect(pageSource).toContain('containerPreview.sourcePalletCount') + expect(pageSource).toContain('containerPreview.supplementPalletCount') expect(pageSource).toContain('v-for="group in containerPreview.groups"') expect(pageSource).toContain('readinessText(row.readiness)') expect(pageSource).toContain('blockerText(row.blockers)')