import db from '../config/database'; import { logger } from '../utils/logger'; import { DecisionExplainabilityEngine } from '../core/ai/DecisionExplainabilityEngine'; /** * [BIZ_OPS_147] 物流轨迹停留时间过长报警 (Stuck) * @description 核心逻辑:自动识别在特定节点(如海关、转运中心)停留超过 72 小时的包裹,生成预警建议并提示自动催促货代。 */ export class StuckTrackingService { /** * 预警停留时间过长的包裹 (BIZ_OPS_147) */ static async alertStuckTracking(tenantId: string, trackingNumber: string): Promise { logger.info(`[StuckTracking] Analyzing status for: ${trackingNumber}, Tenant: ${tenantId}`); try { // 1. 获取包裹最新轨迹 (模拟) const telemetry = await db('cf_logistic_telemetry') .where({ trackingNumber }) .orderBy('timestamp', 'desc') .first(); if (!telemetry) return { success: true, isStuck: false }; // 2. 计算停留时间 const lastUpdate = new Date(telemetry.timestamp); const hoursStuck = (Date.now() - lastUpdate.getTime()) / (1000 * 3600); // 3. 预警逻辑:如果停留超过 72 小时 if (hoursStuck > 72) { const advice = `STUCK PACKAGE ALERT: Tracking ${trackingNumber} has not updated for ${hoursStuck.toFixed(1)}h at location: ${telemetry.location}. ` + `Suggesting automated carrier follow-up (SLA Breach).`; // 4. [UX_XAI_01] 记录决策证据链 await DecisionExplainabilityEngine.logDecision({ tenantId, module: 'LOGISTICS_MONITORING', resourceId: trackingNumber, decisionType: 'STUCK_TRACKING_ALERT', causalChain: advice, factors: [ { name: 'HoursStuck', value: hoursStuck, weight: 0.9, impact: 'NEGATIVE' }, { name: 'CurrentLocation', value: telemetry.location, weight: 0.1, impact: 'NEUTRAL' } ], traceId: 'stuck-track-' + Date.now() }); return { success: true, isStuck: true, hoursStuck, advice, status: 'PENDING_REVIEW' }; } return { success: true, isStuck: false }; } catch (err: any) { logger.error(`[StuckTracking][WARN] Analysis failed: ${err.message}`); return { success: false, error: err.message }; } } }