feat: 初始化项目结构并添加核心功能模块
- 新增文档模板和导航结构 - 实现服务器基础API路由和控制器 - 添加扩展插件配置和前端框架 - 引入多租户和权限管理模块 - 集成日志和数据库配置 - 添加核心业务模型和类型定义
This commit is contained in:
111
server/src/services/SLAScoringService.ts
Normal file
111
server/src/services/SLAScoringService.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import db from '../config/database';
|
||||
import { logger } from '../utils/logger';
|
||||
import { SupplierService } from './SupplierService';
|
||||
import { DecisionExplainabilityEngine } from '../core/ai/DecisionExplainabilityEngine';
|
||||
import { AdviceService } from '../domains/Strategy/AdviceService';
|
||||
|
||||
/**
|
||||
* [BIZ_OPS_132] 供应商响应时效动态分级 (Supplier SLA)
|
||||
* @description 核心逻辑:基于响应速度 (avg_response_hours) 与交期 (avg_delivery_days) 自动标记低效方,并提供切换建议。
|
||||
*/
|
||||
export class SLAScoringService {
|
||||
private static readonly AUDIT_TABLE = 'cf_sourcing_audit';
|
||||
|
||||
/**
|
||||
* 审计供应商 SLA 并生成警告/建议 (BIZ_OPS_132)
|
||||
*/
|
||||
static async auditSupplierSLA(tenantId: string, supplierId: string): Promise<any> {
|
||||
logger.info(`[SLAScoring] Auditing SLA for Supplier: ${supplierId}, Tenant: ${tenantId}`);
|
||||
|
||||
try {
|
||||
// 1. 获取供应商最新绩效报告
|
||||
const supplierReport = await SupplierService.getSupplierTrustReport(supplierId);
|
||||
const metrics = supplierReport.metrics;
|
||||
const score = supplierReport.trustScore;
|
||||
|
||||
// 2. SLA 阈值校验 (务实点)
|
||||
// 响应速度 > 24h 或 交期 > 10d 触发预警
|
||||
let slaBreached = false;
|
||||
let breachReason = '';
|
||||
|
||||
if (metrics.responseHours > 24) {
|
||||
slaBreached = true;
|
||||
breachReason += `Response time (${metrics.responseHours}h) exceeds 24h limit. `;
|
||||
}
|
||||
|
||||
if (metrics.deliveryDays > 10) {
|
||||
slaBreached = true;
|
||||
breachReason += `Delivery time (${metrics.deliveryDays}d) exceeds 10d limit. `;
|
||||
}
|
||||
|
||||
if (score < 50) {
|
||||
slaBreached = true;
|
||||
breachReason += `Overall TrustScore (${score.toFixed(1)}) is dangerously low. `;
|
||||
}
|
||||
|
||||
if (slaBreached) {
|
||||
logger.warn(`[SLAScoring] SLA Breach detected for ${supplierId}: ${breachReason}`);
|
||||
|
||||
// 3. 寻找同租户下同类目更好的备选供应商 (模拟逻辑)
|
||||
const alternatives = await db('cf_suppliers')
|
||||
.where({ tenant_id: tenantId })
|
||||
.where('rating_score', '>', score + 10)
|
||||
.orderBy('rating_score', 'desc')
|
||||
.limit(1);
|
||||
|
||||
const bestAlt = alternatives[0];
|
||||
const reason = `SLA BREACH: ${breachReason} ` +
|
||||
(bestAlt ? `Recommended to switch to ${bestAlt.name} (Score: ${bestAlt.rating_score.toFixed(1)}).` : 'Immediate review required.');
|
||||
|
||||
// 4. 生成建议 (Suggestion-First) -> 统一至 AdviceService
|
||||
const suggestionId = await AdviceService.recordAdvice({
|
||||
tenantId,
|
||||
shopId: 'GLOBAL', // 供应商审核通常是全局的
|
||||
traceId: 'sla-audit-' + Date.now(),
|
||||
insight: {
|
||||
type: 'SUPPLIER',
|
||||
title: `SLA Breach: ${supplierReport.name}`,
|
||||
description: reason,
|
||||
impact: 'high',
|
||||
confidence: 0.95,
|
||||
suggestedAction: bestAlt ? `SWITCH_TO_${bestAlt.id}` : 'MANUAL_REVIEW',
|
||||
metadata: {
|
||||
supplierId,
|
||||
bestAlternativeId: bestAlt?.id,
|
||||
metrics
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 5. [UX_XAI_01] 记录决策证据链
|
||||
await DecisionExplainabilityEngine.logDecision({
|
||||
tenantId,
|
||||
module: 'SUPPLIER_SLA',
|
||||
resourceId: String(suggestionId),
|
||||
decisionType: 'SLA_BREACH_WARNING',
|
||||
causalChain: reason,
|
||||
factors: [
|
||||
{ name: 'ResponseHours', value: metrics.responseHours, weight: 0.4, impact: 'NEGATIVE' },
|
||||
{ name: 'DeliveryDays', value: metrics.deliveryDays, weight: 0.4, impact: 'NEGATIVE' },
|
||||
{ name: 'TrustScore', value: score, weight: 0.2, impact: 'NEGATIVE' }
|
||||
],
|
||||
traceId: 'sla-audit-' + Date.now()
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
suggestionId,
|
||||
slaBreached,
|
||||
reason,
|
||||
bestAlternative: bestAlt?.name,
|
||||
status: 'PENDING_REVIEW'
|
||||
};
|
||||
}
|
||||
|
||||
return { success: true, slaBreached: false, message: 'SLA compliant' };
|
||||
} catch (err: any) {
|
||||
logger.error(`[SLAScoring][WARN] SLA audit failed: ${err.message}`);
|
||||
return { success: false, error: err.message };
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user