Files
makemd/server/src/services/StuckTrackingService.ts

58 lines
2.3 KiB
TypeScript
Raw Normal View History

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<any> {
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 };
}
}
}