rwadurian/backend/services/contribution-service/src/application/services/contribution-distribution-p...

150 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Injectable, Logger } from '@nestjs/common';
import { OutboxRepository } from '../../infrastructure/persistence/repositories/outbox.repository';
import { ContributionDistributionResult } from '../../domain/services/contribution-calculator.service';
import { SyncedAdoption } from '../../domain/repositories/synced-data.repository.interface';
/**
* 贡献值分配结果发布服务
* 将计算完成的分配结果发布到 Kafka供 mining-wallet-service 消费
*/
@Injectable()
export class ContributionDistributionPublisherService {
private readonly logger = new Logger(
ContributionDistributionPublisherService.name,
);
constructor(private readonly outboxRepository: OutboxRepository) {}
/**
* 发布分配结果到 Kafka
*/
async publishDistributionResult(
adoption: SyncedAdoption,
result: ContributionDistributionResult,
provinceCode: string,
cityCode: string,
): Promise<void> {
const eventId = `dist-${adoption.originalAdoptionId}-${Date.now()}`;
const payload = {
eventType: 'ContributionDistributionCompleted',
eventId,
timestamp: new Date().toISOString(),
payload: {
// 认种信息
adoptionId: adoption.originalAdoptionId.toString(),
adopterAccountSequence: adoption.accountSequence,
treeCount: adoption.treeCount,
adoptionDate: adoption.adoptionDate.toISOString(),
// 用户贡献值分配
userContributions: this.mapUserContributions(result),
// 系统账户分配
systemContributions: this.mapSystemContributions(
result,
provinceCode,
cityCode,
),
// 未分配(归总部)
unallocatedToHeadquarters: this.mapUnallocated(result),
},
};
await this.outboxRepository.save({
eventType: 'ContributionDistributionCompleted',
topic: 'contribution.distribution.completed',
key: adoption.accountSequence,
payload,
aggregateId: adoption.originalAdoptionId.toString(),
aggregateType: 'Adoption',
});
this.logger.debug(
`Published distribution result for adoption ${adoption.originalAdoptionId}`,
);
}
private mapUserContributions(result: ContributionDistributionResult): any[] {
const contributions: any[] = [];
// 个人贡献
if (result.personalRecord) {
contributions.push({
accountSequence: result.personalRecord.accountSequence,
contributionType: 'PERSONAL',
amount: result.personalRecord.amount.value.toString(),
effectiveDate: result.personalRecord.effectiveDate.toISOString(),
expireDate: result.personalRecord.expireDate.toISOString(),
sourceAdoptionId: result.personalRecord.sourceAdoptionId.toString(),
sourceAccountSequence: result.personalRecord.sourceAccountSequence,
});
}
// 团队层级贡献
for (const record of result.teamLevelRecords) {
contributions.push({
accountSequence: record.accountSequence,
contributionType: 'TEAM_LEVEL',
amount: record.amount.value.toString(),
levelDepth: record.levelDepth,
effectiveDate: record.effectiveDate.toISOString(),
expireDate: record.expireDate.toISOString(),
sourceAdoptionId: record.sourceAdoptionId.toString(),
sourceAccountSequence: record.sourceAccountSequence,
});
}
// 团队奖励贡献
for (const record of result.teamBonusRecords) {
contributions.push({
accountSequence: record.accountSequence,
contributionType: 'TEAM_BONUS',
amount: record.amount.value.toString(),
bonusTier: record.bonusTier,
effectiveDate: record.effectiveDate.toISOString(),
expireDate: record.expireDate.toISOString(),
sourceAdoptionId: record.sourceAdoptionId.toString(),
sourceAccountSequence: record.sourceAccountSequence,
});
}
return contributions;
}
private mapSystemContributions(
result: ContributionDistributionResult,
provinceCode: string,
cityCode: string,
): any[] {
return result.systemContributions.map((sys) => ({
accountType: sys.accountType,
amount: sys.amount.value.toString(),
// 省份代码PROVINCE 用自己的 regionCodeCITY 需要传递省份代码用于创建省份
provinceCode:
sys.accountType === 'PROVINCE'
? sys.regionCode || provinceCode
: sys.accountType === 'CITY'
? provinceCode // CITY 需要省份代码来创建省份(如果省份不存在)
: undefined,
// 城市代码:只有 CITY 类型有
cityCode:
sys.accountType === 'CITY' ? sys.regionCode || cityCode : undefined,
neverExpires: sys.accountType === 'OPERATION', // 运营账户永不过期
}));
}
private mapUnallocated(result: ContributionDistributionResult): any[] {
return result.unallocatedContributions.map((u) => ({
reason: u.reason,
amount: u.amount.value.toString(),
wouldBeAccountSequence: u.wouldBeAccountSequence,
levelDepth: u.levelDepth,
bonusTier: u.type.startsWith('BONUS_TIER_')
? parseInt(u.type.split('_')[2])
: undefined,
}));
}
}