fix(booking): simplify entry form and apply cargo defaults
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
import { flushPromises, mount } from '@vue/test-utils'
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import ElementPlus, { ElSelect } from 'element-plus'
|
||||
import ElementPlus from 'element-plus'
|
||||
import { ApiResponseError } from '@/shared/api/http'
|
||||
import { listPlatformTenants, type PlatformTenantResource } from '@/modules/iam'
|
||||
import { listPlatformPartners } from '@/modules/master-data'
|
||||
import { listPlatformWarehouses } from '@/modules/warehouses'
|
||||
import {
|
||||
@@ -28,8 +27,6 @@ vi.mock('vue-router', () => ({
|
||||
const deniedPermissions = vi.hoisted(() => new Set<string>())
|
||||
vi.mock('@/core/access/accessPreview', () => ({ useAccessPreviewStore: () => ({ can: (permission: string) => !deniedPermissions.has(permission) }) }))
|
||||
vi.mock('@/core/workspace-tabs/workspaceTabs', () => ({ useWorkspaceTabsStore: () => ({ removeByIds: vi.fn(), bumpCacheEpoch: vi.fn() }) }))
|
||||
vi.mock('@/modules/iam', async importOriginal => ({
|
||||
...await importOriginal<typeof import('@/modules/iam')>(), listPlatformTenants: vi.fn() }))
|
||||
vi.mock('@/modules/master-data', () => ({ listPlatformPartners: vi.fn() }))
|
||||
vi.mock('@/modules/warehouses', () => ({ listPlatformWarehouses: vi.fn() }))
|
||||
vi.mock('../api/platformOceanBookings', () => ({
|
||||
@@ -75,7 +72,6 @@ type ViewModel = {
|
||||
hasUnsavedActualChanges: boolean
|
||||
printDisabledReason: string
|
||||
save: () => Promise<void>
|
||||
selectCustomer: (value: unknown) => void
|
||||
canManageDocuments: boolean
|
||||
detail: OceanBookingDetail | null
|
||||
actionError: { code?: string; requestId?: string; traceId?: string; message: string } | null
|
||||
@@ -105,7 +101,6 @@ describe('OceanBookingDetailView one-click release', () => {
|
||||
vi.clearAllMocks()
|
||||
deniedPermissions.clear()
|
||||
vi.mocked(getOceanBooking).mockResolvedValue(booking())
|
||||
vi.mocked(listPlatformTenants).mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 })
|
||||
vi.mocked(listPlatformPartners).mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 })
|
||||
vi.mocked(listPlatformWarehouses).mockResolvedValue({ records: [], page: 1, size: 200, total: 0, pages: 0 })
|
||||
vi.mocked(listWarehouseLogisticsChannels).mockResolvedValue([{ channelCode: 'MATSON_CLX_TRUCK', channelName: '美森正班海卡' }])
|
||||
@@ -129,25 +124,21 @@ describe('OceanBookingDetailView one-click release', () => {
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('finds a customer outside the initial page and saves its actual ID and name in a new booking', async () => {
|
||||
it('starts new bookings with the agreed declared defaults and no removed inputs', async () => {
|
||||
routeState.name = 'ocean-booking-create'; routeState.params.bookingId = 'new'
|
||||
const customer = { id: '9007199254740999', tenantName: '柏悦物流', status: 'ACTIVE' } as PlatformTenantResource
|
||||
vi.mocked(listPlatformTenants).mockImplementation(async query => ({
|
||||
records: query.keyword ? [customer] : [], page: 1, size: 50, total: query.keyword ? 1 : 350, pages: query.keyword ? 1 : 7,
|
||||
}))
|
||||
vi.mocked(createOceanBooking).mockResolvedValue({ ...booking(), customerId: String(customer.id), customerName: customer.tenantName })
|
||||
vi.mocked(createOceanBooking).mockResolvedValue(booking())
|
||||
const { wrapper, vm } = await mountView()
|
||||
const selector = wrapper.findAllComponents(ElSelect).find(item => item.props('placeholder') === '单客户可选择,多客户可留空')!
|
||||
expect(selector.props('remote')).toBe(true)
|
||||
selector.vm.$emit('end-reached', 'bottom'); await flushPromises()
|
||||
expect(listPlatformTenants).toHaveBeenLastCalledWith({ page: 2, size: 50, status: 'ACTIVE' })
|
||||
await selector.props('remoteMethod')?.('柏悦'); await flushPromises()
|
||||
expect(listPlatformTenants).toHaveBeenLastCalledWith({ page: 1, size: 50, status: 'ACTIVE', keyword: '柏悦' })
|
||||
selector.vm.$emit('update:modelValue', customer.id); await flushPromises()
|
||||
expect(vm.form.data.customerId).toBe(customer.id)
|
||||
expect(vm.form.data.customerName).toBe('柏悦物流')
|
||||
expect(vm.form.data).toMatchObject({ freightTerm: 'FREIGHT PREPAID', serviceTerm: 'CY-CY', packageUnit: 'CARTONS', declaredPackageCount: 500, declaredGrossWeightKg: 15000, declaredVolumeCbm: 68, actualPackageCount: null, actualGrossWeightKg: null, actualVolumeCbm: null })
|
||||
expect(wrapper.get('[aria-label="预报件数"]').element).toHaveProperty('value', '500')
|
||||
expect(wrapper.get('[aria-label="预报毛重"]').element).toHaveProperty('value', '15000.000')
|
||||
expect(wrapper.get('[aria-label="预报体积"]').element).toHaveProperty('value', '68.000')
|
||||
const labels = wrapper.findAll('.el-form-item__label').map(item => item.text())
|
||||
for (const removed of ['客户(选填)', '预计到港', '包装单位', '备注']) expect(labels).not.toContain(removed)
|
||||
expect(wrapper.find('[aria-label="起运港名称"]').exists()).toBe(false)
|
||||
expect(wrapper.find('[aria-label="目的港名称"]').exists()).toBe(false)
|
||||
expect(wrapper.findAll('.container-table th').map(item => item.text())).toEqual(['操作', '柜型', '数量'])
|
||||
await vm.save()
|
||||
expect(createOceanBooking).toHaveBeenCalledWith(expect.objectContaining({ data: expect.objectContaining({ customerId: customer.id, customerName: '柏悦物流' }) }))
|
||||
expect(createOceanBooking).toHaveBeenCalledWith(expect.objectContaining({ data: expect.objectContaining({ declaredPackageCount: 500, declaredGrossWeightKg: 15000, declaredVolumeCbm: 68, actualPackageCount: null }) }))
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
@@ -170,8 +161,13 @@ describe('OceanBookingDetailView one-click release', () => {
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('shows the matching fixed logistics group instead of the underlying price-book channel', async () => {
|
||||
const { wrapper } = await mountView()
|
||||
it('keeps warehouse and channel in a collapsed operation section with their saved bindings', async () => {
|
||||
const { wrapper, vm } = await mountView()
|
||||
const header = wrapper.get('.booking-operation-config .el-collapse-item__header')
|
||||
expect(header.attributes('aria-expanded')).toBe('false')
|
||||
await header.trigger('click')
|
||||
expect(header.attributes('aria-expanded')).toBe('true')
|
||||
expect(vm.form.data).toMatchObject({ warehouseId: '8', channelCode: 'MATSON_CLX' })
|
||||
expect(wrapper.text()).toContain('美森正班')
|
||||
expect(wrapper.text()).not.toContain('美森正班海卡')
|
||||
wrapper.unmount()
|
||||
@@ -232,16 +228,28 @@ describe('OceanBookingDetailView one-click release', () => {
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('clears an existing customer before saving and releasing with the returned version', async () => {
|
||||
const saved = booking('DRAFT', 4)
|
||||
saved.customerId = null; saved.customerName = null; saved.oceanBooking.customerId = null; saved.oceanBooking.customerName = null
|
||||
vi.mocked(updateOceanBookingDraft).mockResolvedValue(saved)
|
||||
vi.mocked(releaseOceanBooking).mockResolvedValue({ ...saved, status: 'RELEASED', version: 5 })
|
||||
it('allows release without an estimated arrival while preserving other requirements', async () => {
|
||||
const saved = booking()
|
||||
saved.estimatedArrivalAt = null
|
||||
saved.oceanBooking.estimatedArrivalAt = null
|
||||
vi.mocked(getOceanBooking).mockResolvedValue(saved)
|
||||
vi.mocked(releaseOceanBooking).mockResolvedValue({ ...saved, status: 'RELEASED', version: 4 })
|
||||
const { vm, wrapper } = await mountView()
|
||||
vm.selectCustomer('')
|
||||
await vm.submitRelease()
|
||||
expect(updateOceanBookingDraft).toHaveBeenCalledWith('123', expect.objectContaining({ data: expect.objectContaining({ customerId: null, customerName: null }) }))
|
||||
expect(releaseOceanBooking).toHaveBeenCalledWith('123', { expectedVersion: 4 })
|
||||
expect(releaseOceanBooking).toHaveBeenCalledWith('123', { expectedVersion: 3 })
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('opens operation configuration when release is missing a warehouse', async () => {
|
||||
const saved = booking()
|
||||
saved.warehouseId = null
|
||||
vi.mocked(getOceanBooking).mockResolvedValue(saved)
|
||||
const { vm, wrapper } = await mountView()
|
||||
await vm.submitRelease()
|
||||
await flushPromises()
|
||||
expect(vm.actionError?.message).toBe('放舱前请填写装柜仓库')
|
||||
expect(wrapper.get('.booking-operation-config .el-collapse-item__header').attributes('aria-expanded')).toBe('true')
|
||||
expect(releaseOceanBooking).not.toHaveBeenCalled()
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user