接入V4房型信息展示模型
This commit is contained in:
@@ -14,6 +14,7 @@ import type {
|
||||
} from '@/types/reservation'
|
||||
import ReservationV4OrderTaskDetailView from '@/views/reservation/ReservationV4OrderTaskDetailView.vue'
|
||||
import ReservationV4SourceNotificationDetailView from '@/views/reservation/ReservationV4SourceNotificationDetailView.vue'
|
||||
import { ApiError } from '@/services/httpClient'
|
||||
|
||||
vi.mock('@/services/reservationService', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@/services/reservationService')>()
|
||||
@@ -98,6 +99,7 @@ describe('reservation V4 pages', () => {
|
||||
|
||||
it('keeps V4 task card layout classes for styled card metadata and payload summary', async () => {
|
||||
const detail = createOrderTaskDetail()
|
||||
detail.business_cards[0]!.card_type = 'TRACE_RESERVATION_NOTES'
|
||||
detail.business_cards[0]!.display_payload = {
|
||||
booking_scenario: 'STANDARD',
|
||||
relevant_message_excerpt: 'Please keep this visible.',
|
||||
@@ -148,7 +150,318 @@ describe('reservation V4 pages', () => {
|
||||
expect(wrapper.text()).not.toContain('oss://bucket')
|
||||
})
|
||||
|
||||
it('submits V4 review resolution with field_pointer overrides and confirmed order id', async () => {
|
||||
it('renders New Booking Room Information as a business form and confirms stable final values', async () => {
|
||||
const detail = createOrderTaskDetail({
|
||||
businessEventType: 'NEW_BOOKING',
|
||||
businessBookingType: 'GROUP',
|
||||
})
|
||||
detail.business_cards[0]!.fields = [
|
||||
...detail.business_cards[0]!.fields,
|
||||
createField('/room_information/final_values/adult', {
|
||||
display_name: 'Adult',
|
||||
value: 2,
|
||||
}),
|
||||
createField('/room_information/final_values/nights', {
|
||||
display_name: 'Nights',
|
||||
value: 3,
|
||||
}),
|
||||
createField('/room_information/final_values/target_order/locator_value', {
|
||||
display_name: 'Target Locator',
|
||||
value: 'RAW-GRP-001',
|
||||
}),
|
||||
createField('/room_information/final_values/breakfast_included', {
|
||||
display_name: 'Breakfast',
|
||||
value: true,
|
||||
control_type: 'CHECKBOX',
|
||||
}),
|
||||
createField('/business_fields/after/room_items/0/room_type_code', {
|
||||
display_name: 'Legacy Room Type',
|
||||
value: 'LEGACY',
|
||||
}),
|
||||
]
|
||||
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
|
||||
vi.mocked(service.confirmReservationV4OrderTaskCard).mockResolvedValue({
|
||||
...detail,
|
||||
business_cards: [
|
||||
{
|
||||
...detail.business_cards[0]!,
|
||||
card_status: 'CONFIRMED',
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const wrapper = await mountWithPlugins(
|
||||
ReservationV4OrderTaskDetailView,
|
||||
'/reservation/order-tasks/9001',
|
||||
)
|
||||
await flushPromises()
|
||||
|
||||
const roomCard = wrapper.find('[data-testid="room-information-card"]')
|
||||
expect(roomCard.exists()).toBe(true)
|
||||
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.finalValues)
|
||||
expect(roomCard.text()).toContain('TEN-Tentative')
|
||||
expect(roomCard.text()).toContain('3')
|
||||
expect(roomCard.text()).not.toContain('target_order')
|
||||
expect(roomCard.text()).not.toContain('Adult')
|
||||
expect(roomCard.text()).not.toContain('Legacy Room Type')
|
||||
expect(roomCard.find('input[name="/room_information/final_values/adult"]').exists()).toBe(false)
|
||||
expect(roomCard.find('input[name="/room_information/final_values/nights"]').exists()).toBe(false)
|
||||
expect(roomCard.find('input[name="/room_information/final_values/target_order/locator_value"]').exists()).toBe(false)
|
||||
expect(roomCard.find('input[name="/business_fields/after/room_items/0/room_type_code"]').exists()).toBe(false)
|
||||
|
||||
const breakfastInputs = roomCard.findAll('input[type="checkbox"][name="/room_information/final_values/breakfast_included"]')
|
||||
expect(breakfastInputs).toHaveLength(1)
|
||||
const breakfast = breakfastInputs[0]!
|
||||
expect((breakfast.element as HTMLInputElement).checked).toBe(true)
|
||||
expect((breakfast.element as HTMLInputElement).disabled).toBe(true)
|
||||
expect((roomCard.find('input[name="/room_information/final_values/group_block_name"]').element as HTMLInputElement).value)
|
||||
.toBe('GRP-V4-RI-GROUP-001')
|
||||
expect((roomCard.find('input[name="/room_information/final_values/arrival_date"]').element as HTMLInputElement).value)
|
||||
.toBe('2026-07-26')
|
||||
expect((roomCard.find('input[name="/room_information/final_values/departure_date"]').element as HTMLInputElement).value)
|
||||
.toBe('2026-07-29')
|
||||
|
||||
await roomCard.find('input[name="/room_information/final_values/group_block_name"]').setValue('前端修正团队名')
|
||||
await roomCard.find('select[name="/room_information/final_values/group_booking_status"]').setValue('DEF')
|
||||
await roomCard.find('button').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(service.confirmReservationV4OrderTaskCard).toHaveBeenCalledWith('9001', 'card-room', {
|
||||
version: 5,
|
||||
confirmed_payload: {
|
||||
room_information: {
|
||||
final_values: {
|
||||
group_block_name: '前端修正团队名',
|
||||
arrival_date: '2026-07-26',
|
||||
departure_date: '2026-07-29',
|
||||
rate_code: 'GROUP',
|
||||
group_booking_status: 'DEF',
|
||||
room_items: [
|
||||
{
|
||||
room_type_code: 'TWN',
|
||||
room_count: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('keeps backend errors for hidden Room Information fields visible as action messages', async () => {
|
||||
const detail = createOrderTaskDetail({
|
||||
businessEventType: 'NEW_BOOKING',
|
||||
businessBookingType: 'GROUP',
|
||||
})
|
||||
detail.business_cards[0]!.fields = [
|
||||
...detail.business_cards[0]!.fields,
|
||||
createField('/room_information/final_values/nights', {
|
||||
display_name: 'Nights',
|
||||
value: 3,
|
||||
}),
|
||||
]
|
||||
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
|
||||
vi.mocked(service.confirmReservationV4OrderTaskCard).mockRejectedValue(new ApiError('validation failed', 400, {
|
||||
message: '后端校验失败',
|
||||
details: [
|
||||
'room_information.final_values.nights: 晚数不能由前端提交。',
|
||||
'room_information.final_values.group_block_name: 团队名称不能为空。',
|
||||
],
|
||||
}))
|
||||
|
||||
const wrapper = await mountWithPlugins(
|
||||
ReservationV4OrderTaskDetailView,
|
||||
'/reservation/order-tasks/9001',
|
||||
)
|
||||
await flushPromises()
|
||||
|
||||
const roomCard = wrapper.find('[data-testid="room-information-card"]')
|
||||
await roomCard.find('button').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(wrapper.text()).toContain('后端校验失败')
|
||||
expect(wrapper.text()).toContain('room_information.final_values.nights: 晚数不能由前端提交。')
|
||||
expect(wrapper.text()).toContain('room_information.final_values.group_block_name: 团队名称不能为空。')
|
||||
})
|
||||
|
||||
it('renders readonly Room Information fixed select values with business labels', async () => {
|
||||
const detail = createOrderTaskDetail({
|
||||
businessEventType: 'NEW_BOOKING',
|
||||
businessBookingType: 'GROUP',
|
||||
})
|
||||
detail.business_cards[0]!.fields = detail.business_cards[0]!.fields.map((field) =>
|
||||
field.field_pointer === '/room_information/final_values/group_booking_status'
|
||||
? {
|
||||
...field,
|
||||
editable: false,
|
||||
raw_readonly: true,
|
||||
}
|
||||
: field,
|
||||
)
|
||||
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
|
||||
|
||||
const wrapper = await mountWithPlugins(
|
||||
ReservationV4OrderTaskDetailView,
|
||||
'/reservation/order-tasks/9001',
|
||||
)
|
||||
await flushPromises()
|
||||
|
||||
const roomCard = wrapper.find('[data-testid="room-information-card"]')
|
||||
expect(roomCard.find('select[name="/room_information/final_values/group_booking_status"]').exists()).toBe(false)
|
||||
expect(roomCard.text()).toContain('TEN-Tentative')
|
||||
})
|
||||
|
||||
it('renders Update Booking Room Information change summary before final values', async () => {
|
||||
const detail = createOrderTaskDetail({
|
||||
businessEventType: 'UPDATE_BOOKING',
|
||||
businessBookingType: 'GROUP',
|
||||
businessDisplayPayload: createRoomInformationDisplayPayload({
|
||||
event_type: 'UPDATE_BOOKING',
|
||||
current_values: {
|
||||
group_block_name: 'GRP-V4-RI-UPDATE-001',
|
||||
arrival_date: '2026-07-26',
|
||||
departure_date: '2026-07-29',
|
||||
nights: 3,
|
||||
rate_code: 'GROUP',
|
||||
breakfast_included: true,
|
||||
group_booking_status: 'TEN',
|
||||
group_booking_status_label: 'TEN-Tentative',
|
||||
room_items: [
|
||||
{
|
||||
room_type_code: 'TWN',
|
||||
room_count: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
proposed_values: {
|
||||
arrival_date: '2026-07-27',
|
||||
departure_date: '2026-07-31',
|
||||
room_items: [
|
||||
{
|
||||
room_type_code: 'DBL',
|
||||
room_count: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
final_values: {
|
||||
group_block_name: 'GRP-V4-RI-UPDATE-001',
|
||||
arrival_date: '2026-07-27',
|
||||
departure_date: '2026-07-31',
|
||||
nights: 4,
|
||||
rate_code: 'GROUP',
|
||||
breakfast_included: true,
|
||||
group_booking_status: 'TEN',
|
||||
group_booking_status_label: 'TEN-Tentative',
|
||||
room_items: [
|
||||
{
|
||||
room_type_code: 'DBL',
|
||||
room_count: 3,
|
||||
},
|
||||
],
|
||||
},
|
||||
change_summary: [
|
||||
{
|
||||
field: 'arrival_date',
|
||||
before: '2026-07-26',
|
||||
after: '2026-07-27',
|
||||
},
|
||||
{
|
||||
field: 'nights',
|
||||
before: 3,
|
||||
after: 4,
|
||||
},
|
||||
{
|
||||
field: 'adult',
|
||||
before: 'ADULT-BEFORE-SHOULD-NOT-SHOW',
|
||||
after: 'ADULT-AFTER-SHOULD-NOT-SHOW',
|
||||
},
|
||||
{
|
||||
field: 'target_order.locator_value',
|
||||
before: 'RAW-BEFORE-SHOULD-NOT-SHOW',
|
||||
after: 'RAW-AFTER-SHOULD-NOT-SHOW',
|
||||
},
|
||||
],
|
||||
}),
|
||||
})
|
||||
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
|
||||
|
||||
const wrapper = await mountWithPlugins(
|
||||
ReservationV4OrderTaskDetailView,
|
||||
'/reservation/order-tasks/9001',
|
||||
)
|
||||
await flushPromises()
|
||||
|
||||
const roomCard = wrapper.find('[data-testid="room-information-card"]')
|
||||
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.changeSummary)
|
||||
expect(roomCard.text()).toContain('2026-07-26')
|
||||
expect(roomCard.text()).toContain('2026-07-27')
|
||||
expect(roomCard.text()).toContain('3')
|
||||
expect(roomCard.text()).toContain('4')
|
||||
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.finalValues)
|
||||
expect(roomCard.text()).not.toContain('target_order')
|
||||
expect(roomCard.text()).not.toContain('ADULT-BEFORE-SHOULD-NOT-SHOW')
|
||||
expect(roomCard.text()).not.toContain('RAW-BEFORE-SHOULD-NOT-SHOW')
|
||||
})
|
||||
|
||||
it('renders Cancel Booking Room Information as readonly current and final values', async () => {
|
||||
const detail = createOrderTaskDetail({
|
||||
businessEventType: 'CANCEL_BOOKING',
|
||||
businessBookingType: 'GROUP',
|
||||
businessFields: [],
|
||||
businessDisplayPayload: createRoomInformationDisplayPayload({
|
||||
event_type: 'CANCEL_BOOKING',
|
||||
current_values: {
|
||||
group_block_name: 'GRP-V4-RI-CANCEL-001',
|
||||
arrival_date: '2026-08-01',
|
||||
departure_date: '2026-08-05',
|
||||
nights: 4,
|
||||
rate_code: 'GROUP',
|
||||
breakfast_included: true,
|
||||
group_booking_status: 'DEF',
|
||||
group_booking_status_label: 'DEF-Definite',
|
||||
room_items: [
|
||||
{
|
||||
room_type_code: 'KING',
|
||||
room_count: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
final_values: {
|
||||
group_block_name: 'GRP-V4-RI-CANCEL-001',
|
||||
arrival_date: '2026-08-01',
|
||||
departure_date: '2026-08-05',
|
||||
nights: 4,
|
||||
rate_code: 'GROUP',
|
||||
breakfast_included: true,
|
||||
group_booking_status: 'DEF',
|
||||
group_booking_status_label: 'DEF-Definite',
|
||||
room_items: [
|
||||
{
|
||||
room_type_code: 'KING',
|
||||
room_count: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
})
|
||||
vi.mocked(service.fetchReservationV4OrderTaskDetail).mockResolvedValue(detail)
|
||||
|
||||
const wrapper = await mountWithPlugins(
|
||||
ReservationV4OrderTaskDetailView,
|
||||
'/reservation/order-tasks/9001',
|
||||
)
|
||||
await flushPromises()
|
||||
|
||||
const roomCard = wrapper.find('[data-testid="room-information-card"]')
|
||||
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.currentValues)
|
||||
expect(roomCard.text()).toContain(zhCN.taskV4.roomInformation.finalValues)
|
||||
expect(roomCard.text()).toContain('GRP-V4-RI-CANCEL-001')
|
||||
expect(roomCard.text()).toContain('KING')
|
||||
expect(roomCard.find('input[name="/room_information/final_values/arrival_date"]').exists()).toBe(false)
|
||||
expect(roomCard.find('select[name="/room_information/final_values/group_booking_status"]').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('submits V4 review resolution with Room Information field_pointer overrides from the confirm card button', async () => {
|
||||
const detail = createOrderTaskDetail({
|
||||
businessCardStatus: 'REVIEW_REQUIRED',
|
||||
businessCardAvailability: {
|
||||
@@ -175,12 +488,11 @@ describe('reservation V4 pages', () => {
|
||||
)
|
||||
await flushPromises()
|
||||
|
||||
const selects = wrapper.findAll('select')
|
||||
await selects[1]!.setValue('TWN')
|
||||
const inputs = wrapper.findAll('input')
|
||||
await inputs[0]!.setValue('order-2001')
|
||||
const roomCard = wrapper.find('[data-testid="room-information-card"]')
|
||||
await roomCard.find('select[name="/room_information/final_values/room_items/0/room_type_code"]').setValue('TWN')
|
||||
await wrapper.find('input[name="v4_confirmed_order_id"]').setValue('order-2001')
|
||||
await wrapper.find('textarea').setValue('confirmed by email evidence')
|
||||
await wrapper.findAll('button').find((button) => button.text().includes('提交复核'))?.trigger('click')
|
||||
await roomCard.find('button').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(service.resolveReservationV4OrderTaskCardReview).toHaveBeenCalledWith('9001', 'card-room', {
|
||||
@@ -189,7 +501,7 @@ describe('reservation V4 pages', () => {
|
||||
reason: 'confirmed by email evidence',
|
||||
field_overrides: [
|
||||
{
|
||||
field_pointer: '/business_fields/after/room_items/0/room_type_code',
|
||||
field_pointer: '/room_information/final_values/room_items/0/room_type_code',
|
||||
value: 'TWN',
|
||||
},
|
||||
],
|
||||
@@ -365,7 +677,7 @@ describe('reservation V4 pages', () => {
|
||||
)
|
||||
await flushPromises()
|
||||
|
||||
await wrapper.findAll('button').find((button) => button.text().includes('提交复核'))?.trigger('click')
|
||||
await wrapper.find('[data-testid="room-information-card"]').find('button').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(service.resolveReservationV4OrderTaskCardReview).not.toHaveBeenCalled()
|
||||
@@ -534,11 +846,24 @@ function mockCatalogLookups() {
|
||||
catalog_source: 'SYSTEM_MANAGED',
|
||||
catalog_version: 'catalog-v1',
|
||||
stale: false,
|
||||
items: [],
|
||||
items: [
|
||||
{
|
||||
code: 'GROUP',
|
||||
display_name: 'Group Rate',
|
||||
status: 'ACTIVE',
|
||||
catalog_source: 'SYSTEM_MANAGED',
|
||||
market_code: null,
|
||||
market_name: null,
|
||||
source_code: null,
|
||||
source_name: null,
|
||||
adult_capacity: null,
|
||||
pricing_available: null,
|
||||
},
|
||||
],
|
||||
page: {
|
||||
page_num: 1,
|
||||
page_size: 100,
|
||||
total: 0,
|
||||
total: 1,
|
||||
},
|
||||
warnings: [],
|
||||
})
|
||||
@@ -549,6 +874,10 @@ function createOrderTaskDetail(options: {
|
||||
basicCardAvailability?: Partial<ReservationV4TaskCardResult['availability']>
|
||||
businessCardStatus?: string
|
||||
businessCardAvailability?: Partial<ReservationV4TaskCardResult['availability']>
|
||||
businessEventType?: string
|
||||
businessBookingType?: string
|
||||
businessDisplayPayload?: ReservationV4TaskCardResult['display_payload']
|
||||
businessFields?: ReservationV4TaskCardResult['fields']
|
||||
sourceDisplayPayload?: ReservationV4TaskCardResult['display_payload']
|
||||
basicAccountValue?: string
|
||||
basicAccountRequired?: boolean
|
||||
@@ -586,24 +915,20 @@ function createOrderTaskDetail(options: {
|
||||
}),
|
||||
],
|
||||
})
|
||||
const businessEventType = options.businessEventType ?? 'NEW_BOOKING'
|
||||
const businessBookingType = options.businessBookingType ?? 'GROUP'
|
||||
const businessCard = createCard('card-room', 'ROOM_INFORMATION', options.businessCardStatus ?? 'PENDING_CONFIRM', {
|
||||
event_type: businessEventType,
|
||||
version: 5,
|
||||
availability: createAvailability({
|
||||
confirmable: options.businessCardAvailability?.confirmable ?? true,
|
||||
reviewable: options.businessCardAvailability?.reviewable ?? false,
|
||||
}),
|
||||
fields: [
|
||||
createField('/business_fields/after/room_items/0/room_type_code', {
|
||||
display_name: 'Room type',
|
||||
value: '',
|
||||
options_source: 'RESERVATION_V4_ROOM_TYPE_CATALOG',
|
||||
control_type: 'SELECT',
|
||||
edit_scope: options.businessCardStatus === 'REVIEW_REQUIRED' ? 'MANUAL_REVIEW_ONLY' : 'NORMAL_TASK',
|
||||
write_target: options.businessCardStatus === 'REVIEW_REQUIRED'
|
||||
? 'REVIEW_RESOLUTION_FIELD_OVERRIDES'
|
||||
: 'CONFIRMED_PAYLOAD_JSON',
|
||||
}),
|
||||
],
|
||||
display_payload: options.businessDisplayPayload ?? createRoomInformationDisplayPayload({
|
||||
event_type: businessEventType,
|
||||
booking_type: businessBookingType,
|
||||
}),
|
||||
fields: options.businessFields ?? createRoomInformationFields(options.businessCardStatus === 'REVIEW_REQUIRED'),
|
||||
})
|
||||
return {
|
||||
order_task: {
|
||||
@@ -661,6 +986,132 @@ function createOrderTaskDetail(options: {
|
||||
}
|
||||
}
|
||||
|
||||
function createRoomInformationDisplayPayload(overrides: {
|
||||
event_type?: string
|
||||
booking_type?: string
|
||||
current_values?: Record<string, unknown>
|
||||
proposed_values?: Record<string, unknown>
|
||||
final_values?: Record<string, unknown>
|
||||
change_summary?: Array<Record<string, unknown>>
|
||||
} = {}): ReservationV4TaskCardResult['display_payload'] {
|
||||
const eventType = overrides.event_type ?? 'NEW_BOOKING'
|
||||
const bookingType = overrides.booking_type ?? 'GROUP'
|
||||
const finalValues = overrides.final_values ?? {
|
||||
group_block_name: 'GRP-V4-RI-GROUP-001',
|
||||
arrival_date: '2026-07-26',
|
||||
departure_date: '2026-07-29',
|
||||
nights: 3,
|
||||
rate_code: 'GROUP',
|
||||
breakfast_included: true,
|
||||
group_booking_status: 'TEN',
|
||||
group_booking_status_label: 'TEN-Tentative',
|
||||
room_items: [
|
||||
{
|
||||
room_type_code: 'TWN',
|
||||
room_count: 2,
|
||||
},
|
||||
],
|
||||
}
|
||||
return {
|
||||
event_type: eventType,
|
||||
source_event_index: 1,
|
||||
room_information: {
|
||||
event_type: eventType,
|
||||
booking_type: bookingType,
|
||||
current_values: overrides.current_values ?? {},
|
||||
proposed_values: overrides.proposed_values ?? finalValues,
|
||||
final_values: finalValues,
|
||||
change_summary: overrides.change_summary ?? [],
|
||||
group_booking_status_options: [
|
||||
{
|
||||
code: 'TEN',
|
||||
label: 'TEN-Tentative',
|
||||
},
|
||||
{
|
||||
code: 'DEF',
|
||||
label: 'DEF-Definite',
|
||||
},
|
||||
{
|
||||
code: 'INQ',
|
||||
label: 'INQ-Inquiry',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function createRoomInformationFields(reviewMode = false): ReservationV4TaskCardResult['fields'] {
|
||||
const edit_scope = reviewMode ? 'MANUAL_REVIEW_ONLY' : 'CONFIRM'
|
||||
const write_target = reviewMode ? 'REVIEW_RESOLUTION_FIELD_OVERRIDES' : 'CONFIRMED_PAYLOAD_JSON'
|
||||
return [
|
||||
createField('/room_information/final_values/group_block_name', {
|
||||
display_name: 'Group Block Name',
|
||||
value: 'GRP-V4-RI-GROUP-001',
|
||||
required: true,
|
||||
editable: !reviewMode,
|
||||
edit_scope,
|
||||
write_target,
|
||||
}),
|
||||
createField('/room_information/final_values/arrival_date', {
|
||||
display_name: '入住日期',
|
||||
value: '2026-07-26',
|
||||
required: true,
|
||||
control_type: 'DATE',
|
||||
editable: !reviewMode,
|
||||
edit_scope,
|
||||
write_target,
|
||||
}),
|
||||
createField('/room_information/final_values/departure_date', {
|
||||
display_name: '离店日期',
|
||||
value: '2026-07-29',
|
||||
required: true,
|
||||
control_type: 'DATE',
|
||||
editable: !reviewMode,
|
||||
edit_scope,
|
||||
write_target,
|
||||
}),
|
||||
createField('/room_information/final_values/rate_code', {
|
||||
display_name: 'Rate Code',
|
||||
value: 'GROUP',
|
||||
required: true,
|
||||
control_type: 'SELECT',
|
||||
options_source: 'RESERVATION_V4_RATE_CODE_CATALOG',
|
||||
editable: !reviewMode,
|
||||
edit_scope,
|
||||
write_target,
|
||||
}),
|
||||
createField('/room_information/final_values/room_items/0/room_type_code', {
|
||||
display_name: '房型代码',
|
||||
value: reviewMode ? '' : 'TWN',
|
||||
required: true,
|
||||
control_type: 'SELECT',
|
||||
options_source: 'RESERVATION_V4_ROOM_TYPE_CATALOG',
|
||||
validation_errors: reviewMode ? ['房型代码不在第一版目录中。'] : [],
|
||||
edit_scope,
|
||||
write_target,
|
||||
}),
|
||||
createField('/room_information/final_values/room_items/0/room_count', {
|
||||
display_name: '房间数',
|
||||
value: 2,
|
||||
required: true,
|
||||
control_type: 'NUMBER',
|
||||
editable: !reviewMode,
|
||||
edit_scope,
|
||||
write_target,
|
||||
}),
|
||||
createField('/room_information/final_values/group_booking_status', {
|
||||
display_name: 'Group Booking Status',
|
||||
value: 'TEN',
|
||||
required: true,
|
||||
control_type: 'SELECT',
|
||||
options_source: 'reservation_v4_group_booking_status_fixed',
|
||||
editable: !reviewMode,
|
||||
edit_scope,
|
||||
write_target,
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
function createSourceNotificationDetail(): ReservationV4SourceNotificationDetailResult {
|
||||
return {
|
||||
notification: {
|
||||
|
||||
Reference in New Issue
Block a user