优化
This commit is contained in:
@@ -176,9 +176,9 @@ describe('LastMileOrdersView pending order and container conversion', () => {
|
||||
|
||||
it.each([
|
||||
[[], ['查看'], false],
|
||||
[['inbound-order:create'], ['查看', '入库计划'], false],
|
||||
[['inbound-order:create'], ['查看', '生成入库计划'], false],
|
||||
[['last-mile-order:edit'], ['查看', '暂扣订单', '人工修改节点'], false],
|
||||
[['inbound-order:create', 'last-mile-order:edit'], ['查看', '入库计划', '暂扣订单', ''], true],
|
||||
[['inbound-order:create', 'last-mile-order:edit'], ['查看', '生成入库计划', '暂扣订单', ''], true],
|
||||
])('only collapses row actions above three for %j', async (allowed, labels, overflow) => {
|
||||
canAccess.mockImplementation(code => allowed.some(action => code === 'platform:overseas-warehouse:' + action))
|
||||
vi.mocked(listLastMileOrders).mockResolvedValue({ records: [{ id: 'order-1', customerId, orderNo: 'LM-1', currentStatus: 'PENDING_ASSIGNMENT', orderType: 'FIRST_LEG' }], page: 1, size: 10, total: 1, pages: 1 })
|
||||
@@ -227,6 +227,22 @@ describe('LastMileOrdersView pending order and container conversion', () => {
|
||||
expect((holdButton.element as HTMLButtonElement).disabled).toBe(disabled)
|
||||
})
|
||||
|
||||
it('removes generation and hold actions after an inbound plan has been submitted', async () => {
|
||||
canAccess.mockReturnValue(true)
|
||||
vi.mocked(listLastMileOrders).mockResolvedValue({ records: [{
|
||||
id: 'order-planned', customerId, orderNo: 'LM-PLANNED', currentStatus: 'INBOUND_PLANNED', orderType: 'FIRST_LEG', detained: false,
|
||||
}], page: 1, size: 10, total: 1, pages: 1 })
|
||||
|
||||
const wrapper = await mountView()
|
||||
const actions = wrapper.get('.el-table__body-wrapper .row-actions')
|
||||
expect(actions.text()).toContain('查看')
|
||||
expect(actions.text()).not.toContain('生成入库计划')
|
||||
expect(actions.text()).not.toContain('暂扣订单')
|
||||
|
||||
await selectRows(wrapper, [(wrapper.findComponent(DataTable).props('data') as object[])[0]])
|
||||
expect((button(wrapper, '生成入库计划')!.element as HTMLButtonElement).disabled).toBe(true)
|
||||
})
|
||||
|
||||
it('keeps the original pending order table and does not render a view switch or container table', async () => {
|
||||
const wrapper = await openPending()
|
||||
expect(wrapper.text()).toContain('尾程单号')
|
||||
@@ -342,7 +358,7 @@ describe('LastMileOrdersView pending order and container conversion', () => {
|
||||
expect(payload).not.toHaveProperty('plannedWarehouseName')
|
||||
})
|
||||
|
||||
it('allows a historically held order to generate its inbound plan', async () => {
|
||||
it('blocks a held order from generating its inbound plan', async () => {
|
||||
const wrapper = await openPending()
|
||||
await selectRows(wrapper, [selectedRow({
|
||||
detained: true,
|
||||
@@ -352,10 +368,10 @@ describe('LastMileOrdersView pending order and container conversion', () => {
|
||||
await button(wrapper, '生成入库计划')!.trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(getContainerInboundPlanPreview).toHaveBeenCalledWith(bookingId)
|
||||
expect(getContainerInboundPlanPreview).not.toHaveBeenCalled()
|
||||
const confirm = [...document.body.querySelectorAll('button')]
|
||||
.find((item) => item.textContent?.includes('保存并生成入库单')) as HTMLButtonElement
|
||||
expect(confirm.disabled).toBe(false)
|
||||
expect(confirm).toBeUndefined()
|
||||
})
|
||||
|
||||
it('blocks manual plan creation when the cabinet has no frozen expected arrival time', async () => {
|
||||
|
||||
@@ -445,6 +445,7 @@ function isRejectedReturn(source: object) {
|
||||
return row.orderTypeCode === 'RETURN_RELABEL' && row.currentStatusCode === 'REJECTED'
|
||||
}
|
||||
function hasSelectedRejectedReturn() { return selectedRows.value.some(isRejectedReturn) }
|
||||
function hasSelectedInboundPlan() { return selectedRows.value.some(hasInboundPlan) }
|
||||
async function loadTransferWarehouseOptions() {
|
||||
transferWarehouseLoading.value = true
|
||||
transferWarehouseError.value = null
|
||||
@@ -500,6 +501,7 @@ function openInboundPlan(source?: object) {
|
||||
const target = source ? source as LastMileOrderListItem : (selectedRows.value.length === 1 ? selectedRows.value[0] : null)
|
||||
if (!target) { ElMessage.warning('生成入库计划时请选择 1 条尾程订单'); return }
|
||||
if (isRejectedReturn(target)) { ElMessage.warning('已驳回的退货预报只能查看详情'); return }
|
||||
if (hasInboundPlan(target)) { ElMessage.warning('当前订单已提交入库计划,不能重复生成'); return }
|
||||
if (target.detained) { ElMessage.warning('订单处于暂扣状态,解除暂扣后才能生成入库计划'); return }
|
||||
actionTarget.value = target
|
||||
const volumeMinimum = typeof target.volume === 'number' && target.volume > 0 ? Math.ceil(target.volume / 2) : 1
|
||||
@@ -811,13 +813,27 @@ function hasRelabelActions(row: LastMileOrderListItem) {
|
||||
&& Boolean(row.relabelOrderNo)
|
||||
&& (canConfirmRelabel(row) || canReworkRelabel(row))
|
||||
}
|
||||
const inboundPlanCreatedStatuses = new Set([
|
||||
'INBOUND_PLANNED',
|
||||
'PENDING_RECEIVING',
|
||||
'WAIT_PDA_RECEIVING',
|
||||
'INBOUND_MEASURING',
|
||||
'WAIT_CUSTOMER_CONFIRMATION',
|
||||
'PARTIALLY_RECEIVED',
|
||||
'INBOUND_COMPLETED',
|
||||
])
|
||||
function hasInboundPlan(row: LastMileOrderListItem) {
|
||||
return inboundPlanCreatedStatuses.has(row.currentStatusCode)
|
||||
|| Boolean(row.inboundOrderNo && row.inboundOrderNo !== '—')
|
||||
}
|
||||
function lastMileRowActions(row: LastMileOrderListItem): RowActionItem[] {
|
||||
const inboundPlanCreated = hasInboundPlan(row)
|
||||
return [
|
||||
{ key: 'detail', label: '查看', priority: 500 },
|
||||
{ key: 'review-return', label: '审核', priority: 460, tone: 'warning', visible: access.can(permission.returnOrderReview) && row.orderTypeCode === 'RETURN_RELABEL' && row.currentStatusCode === 'PENDING_REVIEW' },
|
||||
{ key: 'review', label: '审核', priority: 450, tone: 'warning', visible: access.can(permission.warehouseTransferApprove) && row.orderTypeCode === 'WAREHOUSE_TRANSFER' && row.currentStatusCode === 'PENDING_REVIEW' },
|
||||
{ key: 'inbound-plan', label: '入库计划', priority: 400, visible: access.can(permission.inboundOrderCreate) },
|
||||
{ key: 'hold', label: row.detained ? '解除暂扣' : '暂扣订单', priority: 300, tone: 'warning', visible: access.can(permission.lastMileOrderTransfer), disabled: !row.detained && row.currentStatusCode !== 'INBOUND_COMPLETED' },
|
||||
{ key: 'inbound-plan', label: '生成入库计划', priority: 400, visible: access.can(permission.inboundOrderCreate) && !inboundPlanCreated },
|
||||
{ key: 'hold', label: row.detained ? '解除暂扣' : '暂扣订单', priority: 300, tone: 'warning', visible: access.can(permission.lastMileOrderTransfer) && (row.detained || !inboundPlanCreated || row.currentStatusCode === 'INBOUND_COMPLETED'), disabled: !row.detained && row.currentStatusCode !== 'INBOUND_COMPLETED' },
|
||||
{ key: 'manual-nodes', label: '人工修改节点', priority: 200, visible: access.can(permission.lastMileOrderTransfer) },
|
||||
{ key: 'confirm-relabel', label: '换标完成确认', priority: 150, visible: access.can(permission.relabelOrderStatus) && Boolean(row.relabelOrderNo) && canConfirmRelabel(row) },
|
||||
{ key: 'rework-relabel', label: '重新换标', priority: 100, tone: 'danger', divided: true, visible: access.can(permission.relabelOrderStatus) && Boolean(row.relabelOrderNo) && canReworkRelabel(row) },
|
||||
@@ -925,7 +941,7 @@ onMounted(() => { void load() })
|
||||
</div>
|
||||
</section>
|
||||
<section v-else-if="!loadError" class="surface-panel table-panel"><DataTable v-model:page="page" v-model:page-size="pageSize" :data="rows" :columns="columns" :loading="loading" :total="total" preference-key="overseas-last-mile-orders" row-key="id" empty-text="暂无尾程订单" @selection-change="onSelectionChange" @update:page="load()" @update:page-size="page = 1; load()">
|
||||
<template #toolbar-actions><el-button v-if="access.can(permission.lastMileOrderExport)" plain :loading="exportLoading" @click="exportOrders"><Download :size="16" />导出订单</el-button><el-button v-if="access.can(permission.lastMileOrderTransfer)" plain :disabled="!selectedRows.length || hasSelectedRejectedReturn() || actionLoading" @click="openTransfer">转仓</el-button><el-button v-if="access.can(permission.inboundOrderCreate)" type="primary" plain :disabled="selectedRows.length !== 1 || hasSelectedRejectedReturn() || actionLoading" @click="openInboundPlan()">生成入库计划</el-button><el-button v-if="statusTab === '待分配' && access.can(permission.inboundOrderCreate)" type="primary" :disabled="actionLoading" @click="openContainerConversion">按柜批量生成</el-button></template>
|
||||
<template #toolbar-actions><el-button v-if="access.can(permission.lastMileOrderExport)" plain :loading="exportLoading" @click="exportOrders"><Download :size="16" />导出订单</el-button><el-button v-if="access.can(permission.lastMileOrderTransfer)" plain :disabled="!selectedRows.length || hasSelectedRejectedReturn() || actionLoading" @click="openTransfer">转仓</el-button><el-button v-if="access.can(permission.inboundOrderCreate)" type="primary" plain :disabled="selectedRows.length !== 1 || hasSelectedRejectedReturn() || hasSelectedInboundPlan() || actionLoading" @click="openInboundPlan()">生成入库计划</el-button><el-button v-if="statusTab === '待分配' && access.can(permission.inboundOrderCreate)" type="primary" :disabled="actionLoading" @click="openContainerConversion">按柜批量生成</el-button></template>
|
||||
<template #actions="{ row }"><RowActions :actions="lastMileRowActions(row as LastMileOrderListItem)" :more-label="`更多尾程订单操作 · ${(row as LastMileOrderListItem).orderNo || '当前记录'}`" @action="handleLastMileRowAction($event, row as LastMileOrderListItem)" /></template>
|
||||
<template #orderNo="{ row }"><OrderReferenceText :value="String(row.orderNo || '')" copyable /></template>
|
||||
<template #cartonDifference="{ row }"><span :class="{ 'package-difference--nonzero': typeof row.cartonDifference === 'number' && row.cartonDifference !== 0 }">{{ packageDifferenceText(row.cartonDifference) }}</span></template>
|
||||
|
||||
Reference in New Issue
Block a user