fix(fleet): distinguish signed returned and remaining trip cargo

This commit is contained in:
2026-10-03 15:00:10 +08:00
parent 5641ea0f7e
commit 6a135c3982
6 changed files with 36 additions and 9 deletions
@@ -25,7 +25,7 @@ const detail: TripDetail = { trip, driverQualification: null, dispatches: [], lo
const layout = { template: '<div><slot name="header"/><slot/></div>' }
const input = { name: 'ElInput', props: ['modelValue'], emits: ['update:modelValue'], template: '<input :value="modelValue" @input="$emit(\'update:modelValue\',$event.target.value)" />' }
const dialog = { name: 'AppDialog', props: ['modelValue'], emits: ['confirm'], template: '<div v-if="modelValue"><slot/><button @click="$emit(\'confirm\')">保存计划</button></div>' }
const table = { name: 'DataTable', props: ['data', 'columns', 'page', 'pageSize'], emits: ['update:page'], template: '<div><slot name="toolbar-actions"/><div v-for="(row,index) in data" :key="index"><slot name="actions" :row="row"/><slot name="weight" :row="row"/><slot name="volume" :row="row"/></div></div>' }
const table = { name: 'DataTable', props: ['data', 'columns', 'page', 'pageSize'], emits: ['update:page'], template: '<div><slot name="toolbar-actions"/><div v-for="(row,index) in data" :key="index"><slot name="actions" :row="row"/><slot name="status" :row="row"/><slot name="weight" :row="row"/><slot name="volume" :row="row"/></div></div>' }
const wrappers: VueWrapper[] = []
function mount(component: object, props: Record<string, unknown> = {}): VueWrapper {
const wrapper = shallowMount(component, { props, global: { directives: { loading: () => undefined }, stubs: {
@@ -46,6 +46,27 @@ beforeEach(() => {
})
afterEach(() => wrappers.splice(0).forEach(wrapper => wrapper.unmount()))
it('shows mixed signature and return quantities from one lazy completion read', async () => {
vi.mocked(api.getTrip).mockResolvedValue({ ...structuredClone(detail), trip: { ...trip, status: 'IN_TRANSIT' } })
const outcome = { dispatchNo: 'DP-1', deliveryNo: 'DL-1', customerId: 'A', destination: 'ONT8', status: 'DELIVERED',
packages: 12, signedPackages: 8, returnedPackages: 4, remainingPackages: 0, terminalAt: trip.updatedAt }
vi.mocked(api.getTripCompletion).mockResolvedValue({ tripNo: trip.tripNo, recordVersion: 3, canComplete: true, blockReason: null, outcomes: [outcome] })
const wrapper = mount(TripDetailView); await flushPromises()
expect(api.getTripCompletion).not.toHaveBeenCalled()
wrapper.findComponent({ name: 'ElTabs' }).vm.$emit('update:modelValue', 'completion'); await flushPromises()
expect(api.getTripCompletion).toHaveBeenCalledExactlyOnceWith('TR-TEST')
const result = wrapper.findComponent({ name: 'DataTable' })
expect(result.props('data')).toEqual([outcome])
expect(result.props('columns')).toEqual(expect.arrayContaining([
expect.objectContaining({ prop: 'packages', label: '原实发箱数' }),
expect.objectContaining({ prop: 'signedPackages', label: '实签箱数' }),
expect.objectContaining({ prop: 'returnedPackages', label: '本趟实退箱数' }),
expect.objectContaining({ prop: 'remainingPackages', label: '未结箱数' }),
]))
expect(wrapper.text()).toContain('余货已签收')
expect(api.completeTrip).not.toHaveBeenCalled()
})
it('mounts direct costs only when the costs tab is selected', async () => {
const wrapper = mount(TripDetailView); await flushPromises()
expect(wrapper.findComponent({ name: 'TripCostPanel' }).exists()).toBe(false)