2026-03-17 22:07:19 +08:00
|
|
|
|
import db from '../config/database';
|
|
|
|
|
|
import { AuditService } from './AuditService';
|
|
|
|
|
|
import { AIService } from './AIService';
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* [BIZ_ECO_04] 基于 AGI 的全球供应链动态重组 (Dynamic Supply Chain Recomposition)
|
|
|
|
|
|
* 负责实时监控全球风险,自动触发供应链节点的替换与重组(如:当某地区罢工时,自动重组至备选工厂与航线)
|
|
|
|
|
|
*/
|
|
|
|
|
|
export class DynamicRecompositionService {
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 触发供应链动态重组分析
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async triggerRecomposition(
|
|
|
|
|
|
tenantId: string,
|
|
|
|
|
|
category: string,
|
|
|
|
|
|
reason: string,
|
|
|
|
|
|
traceId: string
|
|
|
|
|
|
): Promise<void> {
|
|
|
|
|
|
// 1. 获取当前供应链节点快照
|
|
|
|
|
|
const currentNodes = await db('cf_autonomous_eco_contracts')
|
|
|
|
|
|
.where({ tenant_id: tenantId, status: 'SIGNED' })
|
|
|
|
|
|
.limit(10);
|
|
|
|
|
|
|
|
|
|
|
|
// 2. AGI 分析重组方案 (模拟)
|
|
|
|
|
|
const recompositionLogic = await AIService.analyzeSupplyChainRecomposition(tenantId, category, reason);
|
|
|
|
|
|
|
|
|
|
|
|
if (recompositionLogic.needsRecomposition) {
|
|
|
|
|
|
await db.transaction(async (trx) => {
|
|
|
|
|
|
// 3. 记录重组提案
|
|
|
|
|
|
const [id] = await trx('cf_dynamic_recomposition').insert({
|
|
|
|
|
|
tenant_id: tenantId,
|
|
|
|
|
|
category,
|
|
|
|
|
|
current_nodes: JSON.stringify(currentNodes),
|
|
|
|
|
|
new_nodes: JSON.stringify(recompositionLogic.proposedNodes),
|
|
|
|
|
|
logic_snapshot: recompositionLogic.reasoning,
|
|
|
|
|
|
status: 'PROPOSED'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 审计记录
|
|
|
|
|
|
await AuditService.log({
|
2026-03-21 15:04:06 +08:00
|
|
|
|
tenantId: tenantId,
|
2026-03-17 22:07:19 +08:00
|
|
|
|
action: 'SUPPLY_CHAIN_RECOMPOSITION_PROPOSED',
|
2026-03-21 15:04:06 +08:00
|
|
|
|
module: 'SUPPLY_CHAIN',
|
|
|
|
|
|
resourceType: 'SUPPLY_CHAIN',
|
|
|
|
|
|
resourceId: id.toString(),
|
|
|
|
|
|
traceId: traceId,
|
|
|
|
|
|
userId: 'system',
|
|
|
|
|
|
result: 'success',
|
|
|
|
|
|
source: 'console',
|
|
|
|
|
|
afterSnapshot: { reason, proposedNodes: recompositionLogic.proposedNodes },
|
|
|
|
|
|
metadata: { logic: recompositionLogic.reasoning }
|
2026-03-17 22:07:19 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 执行重组方案 (BIZ_ECO_04)
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async executeRecomposition(recompositionId: number, tenantId: string, traceId: string): Promise<void> {
|
|
|
|
|
|
const proposal = await db('cf_dynamic_recomposition').where({ id: recompositionId }).first();
|
|
|
|
|
|
if (!proposal) return;
|
|
|
|
|
|
|
|
|
|
|
|
await db.transaction(async (trx) => {
|
|
|
|
|
|
// 模拟执行重组:更新合同状态,激活新供应商
|
|
|
|
|
|
await trx('cf_dynamic_recomposition').where({ id: recompositionId }).update({
|
|
|
|
|
|
status: 'COMPLETED',
|
|
|
|
|
|
updated_at: db.fn.now()
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 审计记录
|
|
|
|
|
|
await AuditService.log({
|
2026-03-21 15:04:06 +08:00
|
|
|
|
tenantId: tenantId,
|
2026-03-17 22:07:19 +08:00
|
|
|
|
action: 'SUPPLY_CHAIN_RECOMPOSITION_EXECUTED',
|
2026-03-21 15:04:06 +08:00
|
|
|
|
module: 'SUPPLY_CHAIN',
|
|
|
|
|
|
resourceType: 'SUPPLY_CHAIN',
|
|
|
|
|
|
resourceId: recompositionId.toString(),
|
|
|
|
|
|
traceId: traceId,
|
|
|
|
|
|
userId: 'system',
|
|
|
|
|
|
result: 'success',
|
|
|
|
|
|
source: 'console',
|
|
|
|
|
|
afterSnapshot: { status: 'COMPLETED' },
|
|
|
|
|
|
metadata: { category: proposal.category }
|
2026-03-17 22:07:19 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取租户所有重组历史
|
|
|
|
|
|
*/
|
|
|
|
|
|
static async getRecompositionHistory(tenantId: string) {
|
|
|
|
|
|
return await db('cf_dynamic_recomposition')
|
|
|
|
|
|
.where({ tenant_id: tenantId })
|
|
|
|
|
|
.orderBy('created_at', 'desc');
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|