Files
LWLT-AI/archive/handoff/2026-07-12/legacy-erp-handoff/tools/tests/erp_operation_handlers.test.js
2026-07-13 19:57:46 +08:00

238 lines
8.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const registry = require('../erp_order_registry');
const handlers = require('../erp_operation_handlers');
function tempRegistryPath() {
return path.join(fs.mkdtempSync(path.join(os.tmpdir(), 'erp-op-handler-')), 'orders.jsonl');
}
test('executeExportConfirmation exports confirmation source files without PDF conversion', async () => {
const registryPath = tempRegistryPath();
registry.appendRawRecord({
identifier: 'LW-260919A-A',
route: 'team_batch',
groupNo: 'LW-260919A-A',
departureDate: '2026-09-19',
product: '老挝行程-广东 8D7N',
customer: 'LW customer',
ddid: '14067',
tid: '14067',
updatedAt: '2026-06-22T01:00:00.000Z',
}, { registryPath });
const calls = [];
const result = await handlers.executeExportConfirmation({
operation: 'export_confirmation',
identifier: 'LW-260919A-A',
exportTypes: ['xingyou-confirm'],
}, {
config: { paths: { orderRegistry: registryPath } },
operationsByRoute: {
team_batch: {
exportDocuments: async (plan, submitResult, updateResult, options) => {
calls.push(['exportDocuments', plan.route, submitResult.groups[0].groupNo, options.exportTypes.join(',')]);
return {
sources: [
{ groupNo: 'LW-260919A-A', type: 'xingyou-confirm', path: 'downloads/xingyou.doc' },
{ groupNo: 'LW-260919A-A', type: 'liantai-confirm', path: 'downloads/liantai.doc' },
{ groupNo: 'LW-260919A-A', type: 'job-order', path: 'downloads/job.doc' },
],
};
},
},
},
});
assert.equal(result.status, 'completed');
assert.equal(result.identifiers.groupNo, 'LW-260919A-A');
assert.deepEqual(calls, [
['exportDocuments', 'team_batch', 'LW-260919A-A', 'xingyou-confirm'],
]);
assert.equal(result.artifacts.length, 1);
assert.equal(result.artifacts[0].type, 'xingyou-confirm');
assert.equal(result.artifacts[0].path, 'downloads/xingyou.doc');
assert.equal(result.stageResults.pdf, undefined);
assert.doesNotMatch(result.customerMessage, /PDF/i);
assert.doesNotMatch(result.customerMessage, /JOB/i);
});
test('executeExportConfirmation blocks when the identifier is not registered', async () => {
const result = await handlers.executeExportConfirmation({
operation: 'export_confirmation',
identifier: 'D99999',
}, {
config: { paths: { orderRegistry: tempRegistryPath() } },
});
assert.equal(result.status, 'blocked');
assert.equal(result.reason, 'order_record_not_found');
assert.match(result.customerMessage, /D99999/);
});
test('executeExportConfirmation blocks split child export when departure date is missing', async () => {
const registryPath = tempRegistryPath();
registry.appendRawRecord({
identifier: 'D14079',
route: 'split_child',
childOrderNo: 'D14079',
parentGroupNo: 'LW-260919A-A',
updatedAt: '2026-06-22T01:00:00.000Z',
}, { registryPath });
let exportCalled = false;
const result = await handlers.executeExportConfirmation({
operation: 'export_confirmation',
identifier: 'D14079',
}, {
config: { paths: { orderRegistry: registryPath } },
operationsByRoute: {
split_child: {
exportDocuments: async () => {
exportCalled = true;
throw new Error('export should not run without departure date');
},
convertToPdf: async () => {
throw new Error('convert should not run without departure date');
},
},
},
});
assert.equal(result.status, 'blocked');
assert.equal(result.reason, 'order_record_missing_departure_date');
assert.equal(exportCalled, false);
assert.match(result.customerMessage, /D14079/);
assert.doesNotMatch(result.customerMessage, /Invalid date|split_child|departureDate|registry|code/i);
});
test('executeUpdateOrder finds the order but blocks until field mapping is implemented', async () => {
const registryPath = tempRegistryPath();
registry.appendRawRecord({
identifier: 'D14079',
route: 'split_child',
childOrderNo: 'D14079',
parentGroupNo: 'LW-260919A-A',
updatedAt: '2026-06-22T01:00:00.000Z',
}, { registryPath });
const result = await handlers.executeUpdateOrder({
operation: 'update_order',
identifier: 'D14079',
updateText: '航班信息CZ6091',
}, {
config: { paths: { orderRegistry: registryPath } },
});
assert.equal(result.status, 'blocked');
assert.equal(result.reason, 'update_order_operations_missing');
assert.equal(result.orderRecord.route, 'split_child');
assert.match(result.customerMessage, /D14079/);
});
test('executeUpdateOrder calls the route updateOrder operation with the structured plan', async () => {
const registryPath = tempRegistryPath();
registry.appendRawRecord({
identifier: 'D14079',
route: 'split_child',
childOrderNo: 'D14079',
parentGroupNo: 'LW-260919A-A',
departureDate: '2026-09-19',
product: '老挝行程-广东 8D7N',
customer: 'LW云南七彩金桥国旅',
updatedAt: '2026-06-22T01:00:00.000Z',
}, { registryPath });
let received = null;
const updatePlan = {
status: 'ready',
actions: [
{ target: 'pax.adult', operation: 'delta', value: -1, source: '成人减少1' },
{ target: 'rooms.DBL', operation: 'delta', value: -1, source: 'DBL减少1' },
],
missingFields: [],
};
const result = await handlers.executeUpdateOrder({
operation: 'update_order',
identifier: 'D14079',
updatePlan,
}, {
config: { paths: { orderRegistry: registryPath } },
operationsByRoute: {
split_child: {
updateOrder: async (plan, planArg, recordArg, optionsArg) => {
received = { plan, planArg, recordArg, optionsArg };
return {
status: 'completed',
updatedActions: planArg.actions,
customerMessage: '已修改订单 D14079。',
};
},
},
},
});
assert.equal(result.status, 'completed');
assert.equal(result.operation, 'update_order');
assert.equal(result.route, 'split_child');
assert.match(result.customerMessage, /已修改子单 D14079/);
assert.match(result.customerMessage, /母团下其他历史子单未修改/);
assert.equal(received.plan.route, 'split_child');
assert.equal(received.plan.parentGroupNo, 'LW-260919A-A');
assert.deepEqual(received.planArg.actions, updatePlan.actions);
assert.equal(received.recordArg.childOrderNo, 'D14079');
});
test('executeUpdateOrder scopes split child supplemental updates to the target child in the customer message', async () => {
const registryPath = tempRegistryPath();
registry.appendRawRecord({
identifier: 'D14080',
route: 'split_child',
childOrderNo: 'D14080',
parentGroupNo: 'LW-260919A-A',
departureDate: '2026-09-19',
product: '老挝行程-广东 8D7N',
customer: 'LW河北中游天下旅行社有限公司',
updatedAt: '2026-06-22T01:00:00.000Z',
}, { registryPath });
const updatePlan = {
status: 'ready',
actions: [
{ target: 'supplemental.flights', operation: 'upsert', value: [{ flightNo: 'CZ6091' }], source: '航班信息' },
{ target: 'supplemental.hotels', operation: 'upsert', value: ['第1晚万象酒店1间双床房'], source: '酒店信息' },
{ target: 'supplemental.transfer', operation: 'upsert', value: { pickupPlace: '万象机场' }, source: '接送机信息' },
{ target: 'supplemental.specialRequests', operation: 'append', value: ['不吃牛肉'], source: '特殊要求' },
],
missingFields: [],
};
const result = await handlers.executeUpdateOrder({
operation: 'update_order',
identifier: 'D14080',
updatePlan,
}, {
config: { paths: { orderRegistry: registryPath } },
operationsByRoute: {
split_child: {
updateOrder: async () => ({
status: 'completed',
updatedActions: updatePlan.actions,
customerMessage: '旧文案:母团下现有子单均已填入。',
}),
},
},
});
assert.equal(result.status, 'completed');
assert.match(result.customerMessage, /已修改子单 D14080/);
assert.match(result.customerMessage, /共执行 4 项变更/);
assert.match(result.customerMessage, /母团下其他历史子单未修改/);
assert.doesNotMatch(result.customerMessage, /均已填入|全部子单/);
});