Files
makemd/server/src/core/ai/SettlementOptimizationService.ts

199 lines
5.9 KiB
TypeScript
Raw Normal View History

import { Injectable, Logger } from '@nestjs/common';
import { db } from '../../config/database';
interface SettlementData {
id: string;
merchantId: string;
periodStart: Date;
periodEnd: Date;
totalAmount: number;
status: string;
settlementDate: Date;
createdAt: Date;
updatedAt: Date;
}
interface OptimizationResult {
settlementId: string;
merchantId: string;
currentAmount: number;
optimizedAmount: number;
improvement: number;
recommendations: string[];
}
interface SettlementMetrics {
totalSettlements: number;
totalAmount: number;
averageAmount: number;
pendingSettlements: number;
pendingAmount: number;
averageProcessingTime: number;
}
/**
* [BE-SET-001]
*
* AI注意: 所有结算优化操作必须通过此服务进行
*/
@Injectable()
export class SettlementOptimizationService {
private readonly logger = new Logger(SettlementOptimizationService.name);
constructor() {}
/**
*
* @param settlementId ID
* @param traceId ID
* @returns
*/
async optimizeSettlement(settlementId: string, traceId: string): Promise<OptimizationResult> {
this.logger.log(`开始优化结算: ${settlementId}`, { traceId, settlementId });
try {
const settlement = await db('cf_settlement')
.where('id', settlementId)
.first();
if (!settlement) {
throw new Error(`结算不存在: ${settlementId}`);
}
const currentAmount = settlement.amount;
const optimizedAmount = await this.calculateOptimizedAmount(settlement);
const improvement = currentAmount - optimizedAmount;
const recommendations = this.generateRecommendations(settlement, optimizedAmount);
const result: OptimizationResult = {
settlementId,
merchantId: settlement.merchant_id,
currentAmount,
optimizedAmount,
improvement,
recommendations,
};
this.logger.log(`结算优化完成: ${settlementId}`, { traceId, result });
return result;
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger.error(`结算优化失败: ${errorMessage}`, { traceId, settlementId, error });
throw error;
}
}
/**
*
* @param settlementIds ID列表
* @param traceId ID
* @returns
*/
async batchOptimizeSettlements(
settlementIds: string[],
traceId: string
): Promise<OptimizationResult[]> {
this.logger.log(`开始批量优化结算, 数量: ${settlementIds.length}`, { traceId });
const results: OptimizationResult[] = [];
for (const settlementId of settlementIds) {
try {
const result = await this.optimizeSettlement(settlementId, traceId);
results.push(result);
} catch (error) {
this.logger.error(`批量优化结算失败: ${settlementId}`, { traceId, settlementId });
}
}
this.logger.log(`批量优化结算完成, 成功: ${results.length}/${settlementIds.length}`, { traceId });
return results;
}
/**
*
* @param tenantId ID
* @param traceId ID
* @returns
*/
async getSettlementMetrics(tenantId: string, traceId: string): Promise<SettlementMetrics> {
this.logger.log(`获取结算指标: ${tenantId}`, { traceId, tenantId });
try {
const settlements = await db('cf_settlement')
.where('tenant_id', tenantId)
.select('*');
const totalSettlements = settlements.length;
const totalAmount = settlements.reduce((sum, s) => sum + (s.amount || 0), 0);
const averageAmount = totalSettlements > 0 ? totalAmount / totalSettlements : 0;
const pendingSettlements = settlements.filter(s => s.status === 'pending').length;
const pendingAmount = settlements
.filter(s => s.status === 'pending')
.reduce((sum, s) => sum + (s.amount || 0), 0);
const processingTimes = settlements
.filter(s => s.settlement_date && s.created_at)
.map(s => new Date(s.settlement_date).getTime() - new Date(s.created_at).getTime());
const averageProcessingTime = processingTimes.length > 0
? processingTimes.reduce((sum, t) => sum + t, 0) / processingTimes.length
: 0;
const metrics: SettlementMetrics = {
totalSettlements,
totalAmount,
averageAmount,
pendingSettlements,
pendingAmount,
averageProcessingTime,
};
this.logger.log(`获取结算指标完成: ${tenantId}`, { traceId, metrics });
return metrics;
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error);
this.logger.error(`获取结算指标失败: ${errorMessage}`, { traceId, tenantId, error });
throw error;
}
}
/**
*
*/
private async calculateOptimizedAmount(settlement: any): Promise<number> {
const orders = await db('cf_order')
.where('merchant_id', settlement.merchant_id)
.whereBetween('created_at', [settlement.period_start, settlement.period_end])
.select('*');
const totalOrderAmount = orders.reduce((sum, o) => sum + (o.total_amount || 0), 0);
const platformFee = totalOrderAmount * 0.03;
const optimizedAmount = totalOrderAmount - platformFee;
return Math.round(optimizedAmount * 100) / 100;
}
/**
*
*/
private generateRecommendations(settlement: any, optimizedAmount: number): string[] {
const recommendations: string[] = [];
const improvement = settlement.amount - optimizedAmount;
if (improvement > 0) {
recommendations.push(`建议优化结算金额,可节省 ${improvement.toFixed(2)}`);
}
if (settlement.status === 'pending') {
recommendations.push('建议加快结算处理速度');
}
return recommendations;
}
}