补齐人工复核转换和列表筛选
This commit is contained in:
1 parent
e12bfd77e1
commit
1282d4aede
12 files changed
+983
-15
No files matched your search
@@ -6,6 +6,9 @@ import { createMemoryHistory, createRouter } from 'vue-router'
|
||||
import zhCN from '@/i18n/locales/zh-CN'
|
||||
import ReservationTaskDetailPanel from '@/components/reservation/ReservationTaskDetailPanel.vue'
|
||||
import type {
|
||||
ReservationManualReviewConversionResult,
|
||||
ReservationOrderListItem,
|
||||
ReservationOrderListResult,
|
||||
ReservationTaskAuditLogResult,
|
||||
ReservationTaskDetailResult,
|
||||
ReservationTaskFieldResult,
|
||||
@@ -18,6 +21,8 @@ vi.mock('@/services/reservationService', async (importOriginal) => {
|
||||
...actual,
|
||||
fetchReservationTaskDetail: vi.fn(),
|
||||
fetchReservationTaskAudits: vi.fn(),
|
||||
fetchReservationOrders: vi.fn(),
|
||||
convertReservationManualReviewTask: vi.fn(),
|
||||
saveReservationTaskDraft: vi.fn(),
|
||||
confirmReservationTask: vi.fn(),
|
||||
}
|
||||
@@ -70,6 +75,50 @@ function createMutationResult(taskStatus = 'PENDING_CONFIRM'): ReservationTaskPa
|
||||
}
|
||||
}
|
||||
|
||||
function createManualReviewConversionResult(
|
||||
overrides: Partial<ReservationManualReviewConversionResult> = {},
|
||||
): ReservationManualReviewConversionResult {
|
||||
return {
|
||||
task_id: '10001',
|
||||
order_id: '20001',
|
||||
original_order_id: '20001',
|
||||
system_task_type: 'NEW_BOOKING',
|
||||
task_card_type: 'NEW_BOOKING',
|
||||
task_status: 'PENDING_CONFIRM',
|
||||
original_order_logic_deleted: false,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
function createOrderCandidate(overrides: Partial<ReservationOrderListItem> = {}): ReservationOrderListItem {
|
||||
return {
|
||||
order_id: '20002',
|
||||
hotel_id: 'HOTEL-TEST',
|
||||
order_status: 'ACTIVE',
|
||||
display_order_key: 'GRP-001',
|
||||
temporary_order_no: null,
|
||||
confirmation_number: 'CNF-001',
|
||||
group_code: 'GRP-001',
|
||||
display_name: 'GRP-001',
|
||||
open_task_count: 1,
|
||||
next_processable_task_id: null,
|
||||
created_at: '2026-07-08T03:00:00Z',
|
||||
updated_at: '2026-07-08T03:10:00Z',
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
||||
function createOrderCandidateResult(items: ReservationOrderListItem[]): ReservationOrderListResult {
|
||||
return {
|
||||
items,
|
||||
page: {
|
||||
page_num: 1,
|
||||
page_size: 8,
|
||||
total: items.length,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function createAudit(auditId: string, action: string): ReservationTaskAuditLogResult {
|
||||
return {
|
||||
audit_id: auditId,
|
||||
@@ -162,6 +211,8 @@ describe('ReservationTaskDetailPanel', () => {
|
||||
beforeEach(() => {
|
||||
vi.mocked(service.fetchReservationTaskDetail).mockReset()
|
||||
vi.mocked(service.fetchReservationTaskAudits).mockReset()
|
||||
vi.mocked(service.fetchReservationOrders).mockReset()
|
||||
vi.mocked(service.convertReservationManualReviewTask).mockReset()
|
||||
vi.mocked(service.saveReservationTaskDraft).mockReset()
|
||||
vi.mocked(service.confirmReservationTask).mockReset()
|
||||
vi.mocked(service.fetchReservationTaskDetail).mockResolvedValue(createTaskDetail())
|
||||
@@ -169,6 +220,8 @@ describe('ReservationTaskDetailPanel', () => {
|
||||
task_id: '10001',
|
||||
items: [],
|
||||
})
|
||||
vi.mocked(service.fetchReservationOrders).mockResolvedValue(createOrderCandidateResult([]))
|
||||
vi.mocked(service.convertReservationManualReviewTask).mockResolvedValue(createManualReviewConversionResult())
|
||||
})
|
||||
|
||||
it('shows draft save errors instead of leaving an unhandled rejection', async () => {
|
||||
@@ -335,4 +388,115 @@ describe('ReservationTaskDetailPanel', () => {
|
||||
expect(wrapper.text()).toContain('查看邮件会话')
|
||||
expect(wrapper.text()).not.toContain('接口待补')
|
||||
})
|
||||
|
||||
it('converts a manual review task to a new booking without a target order', async () => {
|
||||
vi.mocked(service.fetchReservationTaskDetail)
|
||||
.mockResolvedValueOnce(
|
||||
createTaskDetail({
|
||||
system_task_type: 'MANUAL_REVIEW',
|
||||
task_card_type: 'MANUAL_REVIEW',
|
||||
}),
|
||||
)
|
||||
.mockResolvedValueOnce(
|
||||
createTaskDetail({
|
||||
system_task_type: 'NEW_BOOKING',
|
||||
task_card_type: 'NEW_BOOKING',
|
||||
}),
|
||||
)
|
||||
vi.mocked(service.fetchReservationTaskAudits)
|
||||
.mockResolvedValueOnce({
|
||||
task_id: '10001',
|
||||
items: [createAudit('audit-1', 'TASK_LOADED')],
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
task_id: '10001',
|
||||
items: [createAudit('audit-2', 'MANUAL_REVIEW_CONVERT')],
|
||||
})
|
||||
|
||||
const wrapper = await mountPanel()
|
||||
expect(wrapper.text()).toContain('人工转换')
|
||||
|
||||
await wrapper.find('select[name="manual_target_task_type"]').setValue('NEW_BOOKING')
|
||||
await wrapper.find('textarea[name="manual_conversion_reason"]').setValue('识别为新预订')
|
||||
await findButton(wrapper, '转换任务').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(service.convertReservationManualReviewTask).toHaveBeenCalledWith('10001', {
|
||||
target_task_type: 'NEW_BOOKING',
|
||||
reason: '识别为新预订',
|
||||
})
|
||||
expect(service.fetchReservationTaskDetail).toHaveBeenCalledTimes(2)
|
||||
expect(service.fetchReservationTaskAudits).toHaveBeenCalledTimes(2)
|
||||
expect(wrapper.text()).toContain('人工转换已完成')
|
||||
expect(wrapper.text()).toContain('人工转换')
|
||||
expect(wrapper.text()).not.toContain('MANUAL_REVIEW_CONVERT')
|
||||
})
|
||||
|
||||
it('requires a non-deleted target order when converting manual review to update booking', async () => {
|
||||
vi.mocked(service.fetchReservationTaskDetail).mockResolvedValue(
|
||||
createTaskDetail({
|
||||
system_task_type: 'MANUAL_REVIEW',
|
||||
task_card_type: 'MANUAL_REVIEW',
|
||||
}),
|
||||
)
|
||||
vi.mocked(service.fetchReservationOrders).mockResolvedValue(
|
||||
createOrderCandidateResult([
|
||||
createOrderCandidate({
|
||||
order_id: '20002',
|
||||
display_order_key: 'GRP-ACTIVE',
|
||||
group_code: 'GRP-ACTIVE',
|
||||
confirmation_number: 'CNF-ACTIVE',
|
||||
order_status: 'ACTIVE',
|
||||
}),
|
||||
createOrderCandidate({
|
||||
order_id: '20003',
|
||||
display_order_key: 'GRP-DELETED',
|
||||
group_code: 'GRP-DELETED',
|
||||
confirmation_number: 'CNF-DELETED',
|
||||
order_status: 'LOGIC_DELETED',
|
||||
}),
|
||||
]),
|
||||
)
|
||||
vi.mocked(service.convertReservationManualReviewTask).mockResolvedValue(
|
||||
createManualReviewConversionResult({
|
||||
order_id: '20002',
|
||||
original_order_id: '20001',
|
||||
system_task_type: 'UPDATE_BOOKING',
|
||||
task_card_type: 'UPDATE_BOOKING',
|
||||
}),
|
||||
)
|
||||
|
||||
const wrapper = await mountPanel()
|
||||
|
||||
await wrapper.find('select[name="manual_target_task_type"]').setValue('UPDATE_BOOKING')
|
||||
await findButton(wrapper, '转换任务').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(service.convertReservationManualReviewTask).not.toHaveBeenCalled()
|
||||
expect(wrapper.text()).toContain('请选择目标订单')
|
||||
|
||||
await wrapper.find('input[name="manual_target_order_keyword"]').setValue('GRP')
|
||||
await findButton(wrapper, '搜索订单').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(service.fetchReservationOrders).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
keyword: 'GRP',
|
||||
page_num: 1,
|
||||
page_size: 8,
|
||||
}),
|
||||
)
|
||||
expect(wrapper.text()).toContain('GRP-ACTIVE')
|
||||
expect(wrapper.text()).toContain('GRP-DELETED')
|
||||
expect(wrapper.find('input[value="20003"]').attributes('disabled')).toBeDefined()
|
||||
|
||||
await wrapper.find('input[value="20002"]').setValue()
|
||||
await findButton(wrapper, '转换任务').trigger('click')
|
||||
await flushPromises()
|
||||
|
||||
expect(service.convertReservationManualReviewTask).toHaveBeenCalledWith('10001', {
|
||||
target_task_type: 'UPDATE_BOOKING',
|
||||
target_order_id: '20002',
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in new issue
Block a user