fix(appointment): show readable source and preview blockers
This commit is contained in:
@@ -15,6 +15,15 @@ const preview: PlanningBatchPreview = { group: { originWarehouseId: 'origin-1',
|
||||
let guard: LeaveGuard
|
||||
function render(input = sources) { return mount(WorkCreateAppointmentForm, { props: { sources: input, canWrite: true }, global: { provide: { 'appointment-work-leave-guard': (value: LeaveGuard) => { guard = value; return () => undefined } }, stubs: { ElButton: { props: ['disabled'], template: '<button :disabled="disabled"><slot /></button>' }, FbaAppointmentFields: { name: 'FbaAppointmentFields', props: ['model', 'disabled'], template: '<input v-model="model.plannedDate" type="date">' }, LoadErrorState: { props: ['message'], template: '<p>{{ message }}</p>' }, ApiErrorMeta: true } } }) }
|
||||
beforeEach(() => { vi.clearAllMocks(); access.write = true; vi.mocked(previewPlanningBatch).mockResolvedValue(preview); vi.mocked(createSourceAppointment).mockResolvedValue(batchContext().appointment) })
|
||||
it('shows readable preview requirements without exposing missing-field machine codes', async () => {
|
||||
vi.mocked(previewPlanningBatch).mockResolvedValue({ ...preview, missingFields: ['READY_WINDOW_UNVERIFIED', 'CARGO_QUANTITY_REVIEW'] })
|
||||
const wrapper = render(); await flushPromises()
|
||||
expect(wrapper.text()).toContain('货物备妥窗口待核实')
|
||||
expect(wrapper.text()).toContain('货量或重复关联需要核对。')
|
||||
expect(wrapper.text()).not.toContain('READY_WINDOW_UNVERIFIED')
|
||||
expect(wrapper.text()).not.toContain('CARGO_QUANTITY_REVIEW')
|
||||
wrapper.unmount()
|
||||
})
|
||||
it('previews and creates the exact canonical external source and customer without inventing times', async () => {
|
||||
const wrapper = render(); await flushPromises()
|
||||
expect(previewPlanningBatch).toHaveBeenCalledWith(sources)
|
||||
|
||||
@@ -9,6 +9,7 @@ import { getApiErrorDetails, type ApiErrorDetails } from '@/shared/api/http'
|
||||
import { previewPlanningBatch, createSourceAppointment, type PlanningBatchPreview, type SourceAppointmentPayload } from './planningApi'
|
||||
import type { SourceReference } from './workApi'
|
||||
import { rejectedCommand, useWorkDraft } from './useWorkDraft'
|
||||
import { workReason } from './workPresentation'
|
||||
const props = defineProps<{ sources: SourceReference[]; canWrite: boolean }>()
|
||||
const emit = defineEmits<{ saved: [] }>()
|
||||
const access = useAccessPreviewStore(), preview = ref<PlanningBatchPreview | null>(null)
|
||||
@@ -50,7 +51,7 @@ onMounted(load)
|
||||
<template v-if="preview && !error">
|
||||
<p>{{ preview.originWarehouseName }} → {{ preview.destinationWarehouseCode }} · {{ preview.group.sourceCount }} 票 · {{ preview.group.packages ?? '箱数待核实' }}</p>
|
||||
<p v-for="source in preview.sources" :key="`${source.customerId}:${source.sourceKey}`">{{ source.inboundCode || source.bookingNo || '原票业务号未提供' }}</p>
|
||||
<p v-for="field in preview.missingFields" :key="field">{{ field }}</p>
|
||||
<p v-for="field in preview.missingFields" :key="field">{{ workReason(field) }}</p>
|
||||
<p v-if="preview.group.readinessIncomplete">货物备妥窗口待核实。</p>
|
||||
<FbaAppointmentFields :model="form" :timezone="preview.destinationTimezone" :disabled="!writable || loading || saving || !!pending" />
|
||||
<LoadErrorState v-if="saveError" title="预约尚未创建" :message="saveError.message" :show-retry="false"><template #details><ApiErrorMeta :details="saveError" /></template></LoadErrorState>
|
||||
|
||||
@@ -1,7 +1,20 @@
|
||||
import { expect, it } from 'vitest'
|
||||
import { actionAllowed, actionRoute, referenceRoute, commandName, workDate, workStatus } from './workPresentation'
|
||||
import { actionAllowed, actionRoute, referenceRoute, commandName, workDate, workStatus, workReason } from './workPresentation'
|
||||
import { followAction, workItem } from './work.test-support'
|
||||
import type { WorkAction } from './workApi'
|
||||
it.each([
|
||||
['SOURCE_TIMEZONE', '原业务作业地点时区待核实'],
|
||||
['SOURCE_CONFIGURATION', '原货源或仓库配置待核实'],
|
||||
['LASTLEG_SOURCE', '尾程货源待建立'],
|
||||
['READY_WINDOW_UNVERIFIED', '货物备妥窗口待核实'],
|
||||
['CARGO_QUANTITY_REVIEW', '货量或重复关联需要核对。'],
|
||||
])('shows readable text for work item reason %s', (code, expected) => {
|
||||
expect(workReason(code)).toBe(expected)
|
||||
})
|
||||
it('preserves the server explanation for an overdue or blocked work item', () => {
|
||||
expect(workReason('作业日期已过,尚未完成')).toBe('作业日期已过,尚未完成')
|
||||
expect(workReason('实际提柜后才能记录直送卸货')).toBe('实际提柜后才能记录直送卸货')
|
||||
})
|
||||
it('links original dispatch and delivery references by business number without inventing unknown routes', () => {
|
||||
expect(referenceRoute({ kind: 'DISPATCH', key: 'DISPATCH:9007199254740999', businessNo: 'DS/001', label: '客户仓排车' })).toBe('/overseas-warehouse/dispatches?dispatchNo=DS%2F001')
|
||||
expect(referenceRoute({ kind: 'DELIVERY', key: 'internal', businessNo: 'DL/001', label: '原派送' })).toBe('/overseas-warehouse/delivery-orders/DL%2F001')
|
||||
|
||||
@@ -3,7 +3,16 @@ import { actionCodes, workCommands, type WorkCommandName } from './workApi'
|
||||
export const typeLabels: Record<WorkType, string> = { PICKUP: '提柜', WAREHOUSE_RECEIPT: '接仓卸柜', DELIVERY: '送仓 / FBA', TRANSPORT: '用车计划', EMPTY_RETURN: '还空柜', ROUTE: '确认路线' }
|
||||
export const flowLabels = { TRANSFER: '海外仓中转', DIRECT: '整柜直送', UNKNOWN: '路线待确认' }
|
||||
export const viewLabels: Record<WorkView, string> = { ALL: '全部待办', FOLLOW_TODAY: '今日需跟进', OVERDUE: '已超期', UNDATED: '未定日期', REVIEW: '需复核' }
|
||||
export function workReason(reason: string) { return reason === 'SOURCE_TIMEZONE' ? '原业务作业地点时区待核实' : reason }
|
||||
export function workReason(reason: string) {
|
||||
switch (reason) {
|
||||
case 'SOURCE_TIMEZONE': return '原业务作业地点时区待核实'
|
||||
case 'SOURCE_CONFIGURATION': return '原货源或仓库配置待核实'
|
||||
case 'LASTLEG_SOURCE': return '尾程货源待建立'
|
||||
case 'READY_WINDOW_UNVERIFIED': return '货物备妥窗口待核实'
|
||||
case 'CARGO_QUANTITY_REVIEW': return '货量或重复关联需要核对。'
|
||||
default: return reason
|
||||
}
|
||||
}
|
||||
export function workStatus(item: WorkItem) {
|
||||
if (item.executionStatus === 'COMPLETED') return '已完成'
|
||||
if (item.reviewRequired) return '需复核'
|
||||
|
||||
Reference in New Issue
Block a user