feat(types): 新增共享类型中心,包含用户、产品、订单等核心领域类型 fix(types): 修复类型定义错误,统一各模块类型引用 style(types): 优化类型文件格式和注释 docs(types): 更新类型文档和变更日志 test(types): 添加类型测试用例 build(types): 配置类型共享路径 chore(types): 清理重复类型定义文件
199 lines
5.9 KiB
TypeScript
199 lines
5.9 KiB
TypeScript
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;
|
|
}
|
|
}
|