Merge remote-tracking branch 'origin/release/test' into release/test
This commit is contained in:
@@ -355,6 +355,11 @@ export interface ChangeContainerReceivingWarehousePayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LastMileOrderDetailDto {
|
export interface LastMileOrderDetailDto {
|
||||||
|
returnReceipt?: {
|
||||||
|
order: { returnNo: string; receivedQuantity: number; expectedQuantity: number }
|
||||||
|
receipts: Array<{ receiptNo: string; unitType: string; unitCode?: string; palletCode?: string; receivedQuantity: number; boxCount: number; signedAt: string }>
|
||||||
|
cartons?: Array<{ receiptNo: string; palletCode?: string; cartonMark: string; countStatus: string; countedAt?: string; items: Array<{ skuCode: string; productNameZh?: string; quantity: number }> }>
|
||||||
|
} | null
|
||||||
order: LastMileOrderDto
|
order: LastMileOrderDto
|
||||||
manualNodes?: ManualNodesResponse['nodes']
|
manualNodes?: ManualNodesResponse['nodes']
|
||||||
cargo: LastMileCargoDto[]
|
cargo: LastMileCargoDto[]
|
||||||
|
|||||||
@@ -13,6 +13,19 @@ vi.mock('../api/warehouseTransfers', () => ({ getWarehouseTransfer: vi.fn() }))
|
|||||||
enableAutoUnmount(afterEach)
|
enableAutoUnmount(afterEach)
|
||||||
|
|
||||||
describe('LastMileOrderDetailView domestic detail alignment', () => {
|
describe('LastMileOrderDetailView domestic detail alignment', () => {
|
||||||
|
it('shows signed box contents and actual quantities on return orders', async () => {
|
||||||
|
vi.mocked(getLastMileOrder).mockResolvedValue({ order: { id: 'tail-return', customerId: 'customer-1', orderNo: 'RETU-1', orderType: 'RETURN_RELABEL', currentStatus: 'INBOUND_COMPLETED' }, cargo: [], fees: [], statusHistory: [], operationHistory: [],
|
||||||
|
returnReceipt: { order: { returnNo: 'RT-1', receivedQuantity: 10, expectedQuantity: 10 }, receipts: [{ receiptNo: 'RR-1', unitType: 'PALLET', unitCode: 'PLT-1', receivedQuantity: 10, boxCount: 2, signedAt: '' }],
|
||||||
|
cartons: [{ receiptNo: 'RR-1', cartonMark: 'RC#2-1', countStatus: 'CONFIRMED', items: [{ skuCode: 'SKU-A', quantity: 3 }, { skuCode: 'SKU-B', quantity: 7 }] }, { receiptNo: 'RR-2', cartonMark: 'RC-PENDING', countStatus: 'PENDING', items: [] }] } })
|
||||||
|
const wrapper = mount(LastMileOrderDetailView, { global: { plugins: [ElementPlus] } }); await flushPromises()
|
||||||
|
await wrapper.findAll('[role="tab"]').find(tab => tab.text().includes('退货签收与箱内清点'))!.trigger('click'); await flushPromises()
|
||||||
|
const panel = wrapper.get('[aria-label="退货签收与箱内清点"]')
|
||||||
|
expect(panel.text()).toContain('实收 10 / 预报 10 件')
|
||||||
|
expect(panel.text()).toContain('RC#2-1')
|
||||||
|
expect(panel.text()).toContain('SKU-A')
|
||||||
|
expect(panel.text()).toContain('实际签收数量')
|
||||||
|
expect(panel.text()).toContain('待清点')
|
||||||
|
})
|
||||||
it('loads transfer fulfillment only on the plan tab using sourceOrderNo, never the tail order number', async () => {
|
it('loads transfer fulfillment only on the plan tab using sourceOrderNo, never the tail order number', async () => {
|
||||||
vi.mocked(getLastMileOrder).mockResolvedValue({ order: { id: 'internal-transfer-tail', customerId: 'customer-1', orderNo: 'WT-TAIL-1', sourceOrderNo: 'WT-SOURCE-1', orderType: 'WAREHOUSE_TRANSFER', currentStatus: 'INBOUND_COMPLETED' }, cargo: [], fees: [], statusHistory: [], operationHistory: [] })
|
vi.mocked(getLastMileOrder).mockResolvedValue({ order: { id: 'internal-transfer-tail', customerId: 'customer-1', orderNo: 'WT-TAIL-1', sourceOrderNo: 'WT-SOURCE-1', orderType: 'WAREHOUSE_TRANSFER', currentStatus: 'INBOUND_COMPLETED' }, cargo: [], fees: [], statusHistory: [], operationHistory: [] })
|
||||||
vi.mocked(getWarehouseTransfer).mockResolvedValue({ id: 'internal-transfer', transferNo: 'WT-SOURCE-1', needRelabel: true, status: 'WAIT_RELABEL', relabelNo: 'RL-1', relabelStatus: 'CUSTOMER_CONFIRM_PENDING', packageCount: 2, items: [], cartons: [], pallets: [], relabelBindings: [] })
|
vi.mocked(getWarehouseTransfer).mockResolvedValue({ id: 'internal-transfer', transferNo: 'WT-SOURCE-1', needRelabel: true, status: 'WAIT_RELABEL', relabelNo: 'RL-1', relabelStatus: 'CUSTOMER_CONFIRM_PENDING', packageCount: 2, items: [], cartons: [], pallets: [], relabelBindings: [] })
|
||||||
|
|||||||
@@ -227,6 +227,33 @@ onMounted(load)
|
|||||||
</dl>
|
</dl>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane name="cargo"><template #label><span class="density-tab-icon" aria-hidden="true">📦</span><span>货物信息</span></template><section class="table-panel"><DataTable :data="cargo" :columns="cargoColumns" column-settings-mode="hide" row-key="id" empty-text="暂无货物明细"></DataTable></section></el-tab-pane>
|
<el-tab-pane name="cargo"><template #label><span class="density-tab-icon" aria-hidden="true">📦</span><span>货物信息</span></template><section class="table-panel"><DataTable :data="cargo" :columns="cargoColumns" column-settings-mode="hide" row-key="id" empty-text="暂无货物明细"></DataTable></section></el-tab-pane>
|
||||||
|
<el-tab-pane v-if="detail?.order.orderType === 'RETURN_RELABEL'" name="return-receipt"><template #label><span class="density-tab-icon" aria-hidden="true">📦</span><span>退货签收与箱内清点</span></template>
|
||||||
|
<section v-if="detail.returnReceipt" class="table-panel" aria-label="退货签收与箱内清点">
|
||||||
|
<h3>{{ detail.returnReceipt.order.returnNo }} · 实收 {{ detail.returnReceipt.order.receivedQuantity }} / 预报 {{ detail.returnReceipt.order.expectedQuantity }} 件</h3>
|
||||||
|
<el-table :data="detail.returnReceipt.receipts" size="small" border>
|
||||||
|
<el-table-column prop="receiptNo" label="签收单号" min-width="190" />
|
||||||
|
<el-table-column label="签收方式" width="90"><template #default="{ row }">{{ row.unitType === 'PALLET' ? '托盘' : row.unitType === 'BOX' ? '箱子' : '包裹' }}</template></el-table-column>
|
||||||
|
<el-table-column prop="unitCode" label="签收载体" min-width="220" />
|
||||||
|
<el-table-column prop="boxCount" label="实收箱数" width="100" />
|
||||||
|
<el-table-column prop="receivedQuantity" label="实收数量" width="100" />
|
||||||
|
</el-table>
|
||||||
|
<h3>签收箱号明细({{ detail.returnReceipt.cartons?.length || 0 }} 箱)</h3>
|
||||||
|
<el-collapse v-if="detail.returnReceipt.cartons?.length">
|
||||||
|
<el-collapse-item v-for="box in detail.returnReceipt.cartons" :key="box.cartonMark" :name="box.cartonMark">
|
||||||
|
<template #title>{{ box.cartonMark }} · {{ box.countStatus === 'CONFIRMED' ? `已确认 · ${box.items.length} 种 SKU · ${box.items.reduce((sum, item) => sum + Number(item.quantity), 0)} 件` : box.countStatus === 'PENDING' ? '待清点' : '未留存箱内签收明细' }}</template>
|
||||||
|
<p>签收单 {{ box.receiptNo }}<template v-if="box.palletCode"> · 托盘 {{ box.palletCode }}</template><template v-if="box.countedAt"> · 确认时间 {{ formatOverseasDateTime(box.countedAt) }}</template></p>
|
||||||
|
<el-table v-if="box.countStatus === 'CONFIRMED'" :data="box.items" size="small" border>
|
||||||
|
<el-table-column prop="skuCode" label="SKU" min-width="220" />
|
||||||
|
<el-table-column prop="productNameZh" label="中文品名" min-width="180" />
|
||||||
|
<el-table-column prop="quantity" label="实际签收数量" width="130" />
|
||||||
|
</el-table>
|
||||||
|
<p v-else>{{ box.countStatus === 'PENDING' ? '箱内数量待仓库清点确认' : '未留存原始箱内明细,不以当前库存代替签收数量' }}</p>
|
||||||
|
</el-collapse-item>
|
||||||
|
</el-collapse>
|
||||||
|
<el-empty v-else description="暂无签收箱号明细" />
|
||||||
|
</section>
|
||||||
|
<el-empty v-else description="暂无退货签收记录" />
|
||||||
|
</el-tab-pane>
|
||||||
<el-tab-pane name="plan" lazy><template #label><span class="density-tab-icon" aria-hidden="true">🗓️</span><span>计划信息</span></template>
|
<el-tab-pane name="plan" lazy><template #label><span class="density-tab-icon" aria-hidden="true">🗓️</span><span>计划信息</span></template>
|
||||||
<WarehouseTransferFulfillmentPanel v-if="detail?.order.orderType === 'WAREHOUSE_TRANSFER'" :customer-id="detail.order.customerId" :transfer-no="detail.order.sourceOrderNo || ''" />
|
<WarehouseTransferFulfillmentPanel v-if="detail?.order.orderType === 'WAREHOUSE_TRANSFER'" :customer-id="detail.order.customerId" :transfer-no="detail.order.sourceOrderNo || ''" />
|
||||||
<section class="info-panel plan-panel" aria-label="计划信息"><dl class="detail-fields plan-fields density-fields"><div v-for="field in planFields" :key="field.label"><dt>{{ field.label }}</dt><dd :class="{ 'detail-field-value--business': isSingleLineBusinessField(field) }" :title="isSingleLineBusinessField(field) ? String(field.value) : undefined">{{ field.value }}</dd></div></dl></section>
|
<section class="info-panel plan-panel" aria-label="计划信息"><dl class="detail-fields plan-fields density-fields"><div v-for="field in planFields" :key="field.label"><dt>{{ field.label }}</dt><dd :class="{ 'detail-field-value--business': isSingleLineBusinessField(field) }" :title="isSingleLineBusinessField(field) ? String(field.value) : undefined">{{ field.value }}</dd></div></dl></section>
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ function warehouseName(warehouseId?: string) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
function statusLabel(status?: string) {
|
function statusLabel(status?: string) {
|
||||||
return status === "AVAILABLE" ? "可用" : status === "MERGED" ? "已合箱" : "—";
|
return status === "PENDING_COUNT" ? "箱内待清点" : status === "AVAILABLE" ? "可用" : status === "MERGED" ? "已合箱" : "—";
|
||||||
}
|
}
|
||||||
async function loadCustomerOptions() {
|
async function loadCustomerOptions() {
|
||||||
const records: PlatformTenantResource[] = [];
|
const records: PlatformTenantResource[] = [];
|
||||||
@@ -634,7 +634,7 @@ const tableColumns = computed(() =>
|
|||||||
v-model="query.status"
|
v-model="query.status"
|
||||||
clearable
|
clearable
|
||||||
placeholder="箱状态"
|
placeholder="箱状态"
|
||||||
><el-option label="可用" value="AVAILABLE" /><el-option
|
><el-option label="箱内待清点" value="PENDING_COUNT" /><el-option label="可用" value="AVAILABLE" /><el-option
|
||||||
label="已合箱"
|
label="已合箱"
|
||||||
value="MERGED" /></el-select
|
value="MERGED" /></el-select
|
||||||
><el-button type="primary" @click="search"
|
><el-button type="primary" @click="search"
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ describe('approved Admin density ownership', () => {
|
|||||||
visit(node.children)
|
visit(node.children)
|
||||||
} }
|
} }
|
||||||
visit(ast.children)
|
visit(ast.children)
|
||||||
expect(panes).toBe(file === 'LastMileOrderDetailView' ? 5 : 4)
|
expect(panes).toBe(file === 'LastMileOrderDetailView' ? 6 : 4)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user