fix: align audit and dispatch workflows and release failed requests
This commit is contained in:
@@ -12,6 +12,7 @@ import {
|
||||
releaseOceanBooking,
|
||||
updateOceanBookingDraft,
|
||||
updateOceanBookingActualCargo,
|
||||
updateOceanBookingEstimatedArrival,
|
||||
} from '../api/platformOceanBookings'
|
||||
import type { OceanBookingDetail, OceanBookingStatus } from '../types'
|
||||
import OceanBookingDetailView from './OceanBookingDetailView.vue'
|
||||
@@ -32,7 +33,7 @@ vi.mock('@/modules/warehouses', () => ({ listPlatformWarehouses: vi.fn() }))
|
||||
vi.mock('../api/platformOceanBookings', () => ({
|
||||
createOceanBooking: vi.fn(), deleteOceanBookingDraft: vi.fn(), getOceanBooking: vi.fn(),
|
||||
listOceanBookingAgents: vi.fn(), listWarehouseLogisticsChannels: vi.fn(),
|
||||
releaseOceanBooking: vi.fn(), updateOceanBookingDraft: vi.fn(), updateOceanBookingActualCargo: vi.fn(),
|
||||
releaseOceanBooking: vi.fn(), updateOceanBookingDraft: vi.fn(), updateOceanBookingActualCargo: vi.fn(), updateOceanBookingEstimatedArrival: vi.fn(),
|
||||
}))
|
||||
|
||||
function booking(status: OceanBookingStatus = 'DRAFT', version = 3, billOfLadingNo = 'BL-001'): OceanBookingDetail {
|
||||
@@ -65,6 +66,12 @@ function booking(status: OceanBookingStatus = 'DRAFT', version = 3, billOfLading
|
||||
}
|
||||
|
||||
type ViewModel = {
|
||||
arrivalValue: string | null
|
||||
arrivalDialogOpen: boolean
|
||||
arrivalSaving: boolean
|
||||
arrivalError: { message: string; code?: string } | null
|
||||
openArrivalDialog: () => void
|
||||
saveEstimatedArrival: () => Promise<void>
|
||||
form: { data: import('../types').OceanBookingDraftData }
|
||||
saveActualCargo: () => Promise<void>
|
||||
actualReason: string
|
||||
@@ -96,6 +103,63 @@ async function mountView() {
|
||||
}
|
||||
|
||||
describe('OceanBookingDetailView one-click release', () => {
|
||||
it('放舱后仅单独保存预计到港并立即回显,保留尚未提交的实货量', async () => {
|
||||
vi.mocked(getOceanBooking).mockResolvedValue(booking('RELEASED'))
|
||||
const saved = { ...booking('RELEASED', 4), estimatedArrivalAt: '2026-09-25T08:00:00' }
|
||||
vi.mocked(updateOceanBookingEstimatedArrival).mockResolvedValue(saved)
|
||||
const { wrapper, vm } = await mountView()
|
||||
expect(wrapper.findAll('button').some(button => button.text() === '维护预计到港')).toBe(true)
|
||||
vm.form.data.actualPackageCount = 499
|
||||
vm.actualReason = '尚未提交'
|
||||
vm.openArrivalDialog()
|
||||
vm.arrivalValue = saved.estimatedArrivalAt
|
||||
await vm.saveEstimatedArrival()
|
||||
expect(updateOceanBookingEstimatedArrival).toHaveBeenCalledExactlyOnceWith('123', { expectedVersion: 3, estimatedArrivalAt: saved.estimatedArrivalAt })
|
||||
expect(vm.detail?.estimatedArrivalAt).toBe(saved.estimatedArrivalAt)
|
||||
expect(vm.detail?.version).toBe(4)
|
||||
expect(vm.form.data.actualPackageCount).toBe(499)
|
||||
expect(vm.actualReason).toBe('尚未提交')
|
||||
expect(updateOceanBookingDraft).not.toHaveBeenCalled()
|
||||
const coreForm = wrapper.findAllComponents({ name: 'ElForm' }).find(form => form.classes().includes('booking-groups'))!
|
||||
expect(coreForm.props('disabled')).toBe(true)
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('无编辑权限不开放维护入口;版本冲突保留输入并恢复操作', async () => {
|
||||
vi.mocked(getOceanBooking).mockResolvedValue(booking('RELEASED'))
|
||||
deniedPermissions.add('platform:firstleg:ocean-booking:edit')
|
||||
let rendered = await mountView()
|
||||
expect(rendered.wrapper.findAll('button').some(button => button.text() === '维护预计到港')).toBe(false)
|
||||
rendered.vm.openArrivalDialog()
|
||||
await rendered.vm.saveEstimatedArrival()
|
||||
expect(updateOceanBookingEstimatedArrival).not.toHaveBeenCalled()
|
||||
rendered.wrapper.unmount()
|
||||
deniedPermissions.clear()
|
||||
rendered = await mountView()
|
||||
rendered.vm.openArrivalDialog()
|
||||
rendered.vm.arrivalValue = '2026-09-25T08:00:00'
|
||||
vi.mocked(updateOceanBookingEstimatedArrival).mockRejectedValueOnce(new ApiResponseError('版本已变化,请刷新后重试', 'A0409'))
|
||||
await rendered.vm.saveEstimatedArrival()
|
||||
expect(rendered.vm.arrivalDialogOpen).toBe(true)
|
||||
expect(rendered.vm.arrivalValue).toBe('2026-09-25T08:00:00')
|
||||
expect(rendered.vm.arrivalSaving).toBe(false)
|
||||
expect(rendered.vm.arrivalError?.code).toBe('A0409')
|
||||
rendered.wrapper.unmount()
|
||||
})
|
||||
|
||||
it('放舱后预计到港不得清空或早于预计开船', async () => {
|
||||
vi.mocked(getOceanBooking).mockResolvedValue(booking('RELEASED'))
|
||||
const { wrapper, vm } = await mountView()
|
||||
vm.openArrivalDialog()
|
||||
for (const value of [null, '2026-08-01T08:00:00']) {
|
||||
vm.arrivalValue = value
|
||||
await vm.saveEstimatedArrival()
|
||||
expect(vm.arrivalError?.message).toBeTruthy()
|
||||
}
|
||||
expect(updateOceanBookingEstimatedArrival).not.toHaveBeenCalled()
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
routeState.name = 'ocean-booking-detail'; routeState.params.bookingId = '123'
|
||||
vi.clearAllMocks()
|
||||
|
||||
Reference in New Issue
Block a user