修复V4目录字段只读与精确查询

This commit is contained in:
andy
2026-07-19 16:38:44 +07:00
parent d808732107
commit 22767e194d
2 changed files with 230 additions and 9 deletions

View File

@@ -7,6 +7,7 @@ import { createMemoryHistory, createRouter } from 'vue-router'
import zhCN from '@/i18n/locales/zh-CN'
import { useAuthStore } from '@/stores/authStore'
import type {
ReservationV4CatalogLookupResult,
ReservationV4OrderTaskDetailResult,
ReservationV4SourceNotificationDetailResult,
ReservationV4TaskCardResult,
@@ -230,6 +231,7 @@ describe('reservation V4 pages', () => {
'/reservation/order-tasks/9001',
)
await flushPromises()
await flushPromises()
expect(wrapper.text()).toContain('UNKNOWN_ACCOUNT')
expect(wrapper.text()).toContain(zhCN.taskV4.lookup.currentNotInCatalog.replace('{value}', 'UNKNOWN_ACCOUNT'))
@@ -241,6 +243,90 @@ describe('reservation V4 pages', () => {
expect(wrapper.text()).toContain(zhCN.taskV4.validationFailed)
})
it('keeps readonly catalog field values even when active lookup does not contain them', async () => {
const detail = createOrderTaskDetail({
basicAccountValue: 'HISTORICAL_ACCOUNT',
basicCardStatus: 'CONFIRMED',
basicCardAvailability: {
editable: false,
read_only: true,
confirmable: false,
},
})
vi.mocked(service.fetchReservationV4AccountLookups).mockResolvedValue(createCatalogLookupResult('ACCOUNT', []))
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
const wrapper = await mountWithPlugins(
ReservationV4OrderTaskDetailView,
'/reservation/order-tasks/9001',
)
await flushPromises()
expect(service.fetchReservationV4AccountLookups).not.toHaveBeenCalled()
expect(wrapper.text()).toContain('HISTORICAL_ACCOUNT')
expect(wrapper.text()).not.toContain(
zhCN.taskV4.lookup.currentNotInCatalog.replace('{value}', 'HISTORICAL_ACCOUNT'),
)
})
it('keeps a current catalog value found by exact keyword lookup outside the first page', async () => {
const detail = createOrderTaskDetail({
basicAccountValue: 'ACC-101',
basicAccountRequired: true,
})
vi.mocked(service.fetchReservationV4AccountLookups)
.mockResolvedValueOnce(createCatalogLookupResult('ACCOUNT', [
{
code: 'ACC-001',
display_name: 'Account 001',
market_code: 'LEISURE',
source_code: 'TRAVEL_AGENT',
},
], 101))
.mockResolvedValueOnce(createCatalogLookupResult('ACCOUNT', [
{
code: 'ACC-101',
display_name: 'Account 101',
market_code: 'MICE',
source_code: 'DIRECT',
},
], 1, 20))
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
const wrapper = await mountWithPlugins(
ReservationV4OrderTaskDetailView,
'/reservation/order-tasks/9001',
)
await flushPromises()
await flushPromises()
expect(service.fetchReservationV4AccountLookups).toHaveBeenNthCalledWith(1, {
hotel_id: 'HOTEL-TEST',
page_num: 1,
page_size: 100,
})
expect(service.fetchReservationV4AccountLookups).toHaveBeenNthCalledWith(2, {
hotel_id: 'HOTEL-TEST',
keyword: 'ACC-101',
page_num: 1,
page_size: 20,
})
expect(wrapper.text()).toContain('MICE')
expect(wrapper.text()).toContain('DIRECT')
await wrapper.findAll('button').find((button) => button.text().includes('确认卡片'))?.trigger('click')
await flushPromises()
expect(service.confirmReservationV4OrderTaskCard).toHaveBeenCalledWith('9001', 'card-basic', {
version: 7,
confirmed_payload: {
basic_information: {
account_code: 'ACC-101',
},
},
})
})
it('requires confirmed order id before resolving an unresolved V4 review card', async () => {
const detail = createOrderTaskDetail({
businessCardStatus: 'REVIEW_REQUIRED',
@@ -437,6 +523,8 @@ function mockCatalogLookups() {
}
function createOrderTaskDetail(options: {
basicCardStatus?: string
basicCardAvailability?: Partial<ReservationV4TaskCardResult['availability']>
businessCardStatus?: string
businessCardAvailability?: Partial<ReservationV4TaskCardResult['availability']>
sourceDisplayPayload?: ReservationV4TaskCardResult['display_payload']
@@ -457,8 +545,9 @@ function createOrderTaskDetail(options: {
],
},
})
const basicCard = createCard('card-basic', 'BASIC_INFORMATION', 'PENDING_CONFIRM', {
const basicCard = createCard('card-basic', 'BASIC_INFORMATION', options.basicCardStatus ?? 'PENDING_CONFIRM', {
version: 7,
availability: createAvailability(options.basicCardAvailability),
fields: [
createField('/basic_information/account_code', {
display_name: 'Account',
@@ -592,6 +681,39 @@ function createSourceNotificationDetail(): ReservationV4SourceNotificationDetail
}
}
function createCatalogLookupResult(
catalog_type: ReservationV4CatalogLookupResult['catalog_type'],
items: Array<Partial<ReservationV4CatalogLookupResult['items'][number]> & { code: string }>,
total = items.length,
pageSize = 100,
): ReservationV4CatalogLookupResult {
return {
hotel_id: 'HOTEL-TEST',
catalog_type,
catalog_source: 'SYSTEM_MANAGED',
catalog_version: 'catalog-v1',
stale: false,
items: items.map((item) => ({
code: item.code,
display_name: item.display_name ?? item.code,
status: item.status ?? 'ACTIVE',
catalog_source: item.catalog_source ?? 'SYSTEM_MANAGED',
market_code: item.market_code ?? null,
market_name: item.market_name ?? null,
source_code: item.source_code ?? null,
source_name: item.source_name ?? null,
adult_capacity: item.adult_capacity ?? null,
pricing_available: item.pricing_available ?? null,
})),
page: {
page_num: 1,
page_size: pageSize,
total,
},
warnings: [],
}
}
function createCard(
card_id: string,
card_type: string,