变更问题修复

This commit is contained in:
andy committed 2026-09-14 16:34:36 +08:00
1 parent 6de4422733
commit 9625110f44
62 files changed
+18116 -95

No files matched your search

+2 -2
View File
@@ -79,8 +79,8 @@ export function effectiveParserModeForRoute(route: BusinessRouteDefinition, conf
return route.parserPolicy === 'program_only' ? 'program' : 'ai';
}
const PROGRAM_VERSION = 'ltjt-program-parser-v1.0.11';
export const BUSINESS_INPUT_CONTRACT_VERSION = 'business-input-templates-0.5.132';
const PROGRAM_VERSION = 'ltjt-program-parser-v1.0.12';
export const BUSINESS_INPUT_CONTRACT_VERSION = 'business-input-templates-0.5.133';
const lookupFields = ({ customerRequired = true } = {}): ProgramFieldDefinition[] => [
{ key: 'order_no', label: '单号', aliases: ['团号', '订单号'], kind: 'text' },
+22 -1
View File
@@ -187,6 +187,23 @@ function parseDateParts(rawValue: string): { year: number | null; month: number;
return null;
}
function parseOriginalDate(rawValue: string): FieldParseResult {
const parts = parseDateParts(rawValue);
if (!parts || !validDate(parts.year ?? 2000, parts.month, parts.day)) return { ok: false, message: '请填写有效的原安排日期 YYYY-MM-DD 或 MM-DD。' };
return { ok: true, value: parts.year === null ? `${pad2(parts.month)}-${pad2(parts.day)}` : formatDate(parts.year, parts.month, parts.day) };
}
function parseOriginalDateRange(rawValue: string): FieldParseResult {
const pieces = compactText(rawValue).split(/\s*(?:到|至|~|~|—|–)\s*/u).filter(Boolean);
if (pieces.length !== 2) return { ok: false, message: '请填写原用车开始日期和结束日期。' };
const start = parseOriginalDate(pieces[0]);
const end = parseOriginalDate(pieces[1]);
if (!start.ok) return start;
if (!end.ok) return end;
if (String(start.value).length === 10 && String(end.value).length === 10 && String(end.value) < String(start.value)) return { ok: false, message: '原用车结束日期不能早于开始日期。' };
return { ok: true, value: { start_date: start.value, end_date: end.value } };
}
function parseDate(rawValue: string, context: DateContext, {
nextOccurrence = false,
referenceYear
@@ -910,7 +927,7 @@ function buildOperation(route: BusinessRouteDefinition, values: Map<string, unkn
if (values.get('hotel_changes')) return { ok: false, code: 'program_field_conflict', message: '按日期变更酒店时,请使用入住日期、离店日期、酒店搜索和间数,不要混填目标变更。', field: 'hotel_changes' };
const missing = datedFields.find((key) => !values.has(key));
if (missing) return { ok: false, code: 'program_missing_required', message: '请补齐原安排的入住日期、离店日期,以及新酒店搜索和间数。', field: missing };
if (String(values.get('end_date')) <= String(values.get('start_date'))) return { ok: false, code: 'program_invalid_value', message: '原安排的离店日期必须晚于入住日期。', field: 'end_date' };
if (String(values.get('start_date')).length === 10 && String(values.get('end_date')).length === 10 && String(values.get('end_date')) <= String(values.get('start_date'))) return { ok: false, code: 'program_invalid_value', message: '原安排的离店日期必须晚于入住日期。', field: 'end_date' };
return { ok: true, operation: operation(route.action, {
existing_refs: { identifier: values.get('group_no') },
arrangement: {
@@ -959,6 +976,10 @@ function buildOperation(route: BusinessRouteDefinition, values: Map<string, unkn
function parseField(field: ProgramFieldDefinition, rawValue: string, route: BusinessRouteDefinition, context: DateContext, parsed: Map<string, unknown>): FieldParseResult {
if (isPlaceholder(rawValue)) return { ok: false, message: '该字段尚未填写。' };
if (['arrangement_hotel_update', 'arrangement_vehicle_update', 'arrangement_transport_update', 'arrangement_other_update'].includes(route.routeId)) {
if (field.kind === 'date') return parseOriginalDate(rawValue);
if (field.kind === 'date_range') return parseOriginalDateRange(rawValue);
}
const nextOccurrence = NEXT_OCCURRENCE_DATE_ROUTES.has(route.routeId);
switch (field.kind) {
case 'text': return { ok: true, value: compactText(rawValue) };