(function (root, factory) { const api = factory(); if (typeof module === 'object' && module.exports) module.exports = api; root.LTJTHotelBatch = api; })(typeof self !== 'undefined' ? self : globalThis, function () { 'use strict'; const object = value => value && typeof value === 'object' && !Array.isArray(value) ? value : {}; const group = value => String(value || '').normalize('NFKC').replace(/\s+/gu, '').toUpperCase(); function verified(result, identifier) { const report = object(result?.report), refs = object(report.resolved_refs); return result?.status === 'completed' && report.status === 'lifecycle_completed' && report.server_response?.completed === true && report.requery?.matched === true && report.requery?.skipped !== true && !result.uncertain && !result.manual_review_required && !report.manual_review_required && ![result.blockers, report.blockers].some(value => Array.isArray(value) && value.length) && refs.kind !== 'shared_child_order' && group(refs.identifier || refs.group_no) === group(identifier); } function inspect(value) { const batch = object(value), items = batch.items; if (batch.version !== 1 || !group(batch.group_number) || !Array.isArray(items) || items.length < 2 || items.length > 10) return null; let stopped = false, pending = false, completed = 0, failed = 0, uncertain = 0; const rowIds = new Set(); for (let index = 0; index < items.length; index++) { const item = object(items[index]); if (item.index !== index || item.arrangement?.mode !== 'create') return null; if (item.status === 'completed') { if (stopped || pending || !verified(item.result, batch.group_number)) return null; const subpage = object(item.result.report.requery.subpage), target = object(subpage.arrangement_target); const rowId = String(target.row_id || ''); if (!rowId || rowId === '0' || rowIds.has(rowId)) return null; rowIds.add(rowId); const normalizeDate = value => String(value || '').replace(/^(\d{4})-(\d{1,2})-(\d{1,2})$/, (_, y, m, d) => `${y}-${m.padStart(2, '0')}-${d.padStart(2, '0')}`); const checks = Array.isArray(subpage.checks) ? subpage.checks : []; const actual = pattern => checks.filter(check => check.matched === true && pattern.test(check.field)); for (const [pattern, expected] of [[/^riqi\d+$/, item.arrangement.start_date], [/^riqis\d+$/, item.arrangement.end_date]]) { const matches = actual(pattern); if (matches.length !== 1 || normalizeDate(matches[0].actual) !== expected) return null; } if (Number(target.quantity_value) !== item.arrangement.room_count) return null; completed++; } else if (item.status === 'failed') { if (stopped || pending || item.result?.no_erp_write !== true || item.result?.write_attempted === true) return null; stopped = true; failed++; } else if (item.status === 'uncertain') { if (stopped || pending) return null; stopped = true; uncertain++; } else if (item.status === 'running') { if (stopped || pending) return null; pending = true; } else if (item.status === 'not_started') pending = true; else return null; } return { completed, failed, uncertain, total: items.length, not_started: items.filter(item => item.status === 'not_started').length, allCompleted: completed === items.length, knownStopped: (failed === 1 || (batch.stopped === true && completed > 0 && !items.some(item => item.status === 'running'))) && uncertain === 0 }; } function resultText(batch) { const stats = inspect(batch); if (!stats) return ''; const lines = [`共 ${stats.total} 条:成功 ${stats.completed} 条,失败 ${stats.failed} 条,待核验 ${stats.uncertain} 条,未执行 ${stats.not_started} 条`]; const labels = { completed: '已完成', failed: '失败', uncertain: '结果不确定,待只读回查', not_started: '未执行', running: '处理中' }; batch.items.forEach(item => { const a = item.arrangement; lines.push('', `${item.index + 1}. ${String(a.start_date).replaceAll('-', '/')}—${String(a.end_date).replaceAll('-', '/')}`, ` 酒店搜索:${a.resource?.keyword || a.resource?.name || ''};${a.room_count} 间`, ` ${labels[item.status]}`); if (item.status === 'failed') lines.push(` 原因:${String(item.result?.failure_message || item.result?.message || '执行阻断').slice(0, 250)}`); }); if (!stats.allCompleted) lines.push('', '已完成的安排已保留,请勿整批重复提交。'); return lines.join('\n'); } return { verified, inspect, resultText }; });