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