fix(contribution): 用户领取奖励时从 HEADQUARTERS 减少算力并删除明细

- 添加 subtractContribution 方法减少系统账户算力
- 添加 deleteContributionRecordsByAdoption 方法删除明细记录
- 在 BonusClaimService 中领取奖励时同步更新 HEADQUARTERS
This commit is contained in:
hailin 2026-01-21 02:56:58 -08:00
parent fda022d29c
commit e0eb734196
2 changed files with 83 additions and 2 deletions

View File

@ -2,13 +2,14 @@ import { Injectable, Logger } from '@nestjs/common';
import { UnallocatedContributionRepository, UnallocatedContribution } from '../../infrastructure/persistence/repositories/unallocated-contribution.repository';
import { ContributionAccountRepository } from '../../infrastructure/persistence/repositories/contribution-account.repository';
import { ContributionRecordRepository } from '../../infrastructure/persistence/repositories/contribution-record.repository';
import { SystemAccountRepository } from '../../infrastructure/persistence/repositories/system-account.repository';
import { OutboxRepository } from '../../infrastructure/persistence/repositories/outbox.repository';
import { UnitOfWork } from '../../infrastructure/persistence/unit-of-work/unit-of-work';
import { ContributionRecordAggregate } from '../../domain/aggregates/contribution-record.aggregate';
import { ContributionSourceType } from '../../domain/aggregates/contribution-account.aggregate';
import { ContributionAmount } from '../../domain/value-objects/contribution-amount.vo';
import { DistributionRate } from '../../domain/value-objects/distribution-rate.vo';
import { ContributionRecordSyncedEvent } from '../../domain/events';
import { ContributionRecordSyncedEvent, SystemAccountSyncedEvent } from '../../domain/events';
/**
*
@ -22,6 +23,7 @@ export class BonusClaimService {
private readonly unallocatedContributionRepository: UnallocatedContributionRepository,
private readonly contributionAccountRepository: ContributionAccountRepository,
private readonly contributionRecordRepository: ContributionRecordRepository,
private readonly systemAccountRepository: SystemAccountRepository,
private readonly outboxRepository: OutboxRepository,
private readonly unitOfWork: UnitOfWork,
) {}
@ -135,7 +137,36 @@ export class BonusClaimService {
const pendingIds = pendingRecords.map((r) => r.id);
await this.unallocatedContributionRepository.claimBonusRecords(pendingIds, accountSequence);
// 6. 发布事件到 Kafka通过 Outbox
// 6. 从 HEADQUARTERS 减少算力并删除明细记录
await this.systemAccountRepository.subtractContribution('HEADQUARTERS', null, totalAmount);
for (const pending of pendingRecords) {
await this.systemAccountRepository.deleteContributionRecordsByAdoption(
'HEADQUARTERS',
null,
pending.sourceAdoptionId,
pending.sourceAccountSequence,
);
}
// 7. 发布 HEADQUARTERS 账户更新事件
const headquartersAccount = await this.systemAccountRepository.findByTypeAndRegion('HEADQUARTERS', null);
if (headquartersAccount) {
const hqEvent = new SystemAccountSyncedEvent(
'HEADQUARTERS',
null,
headquartersAccount.name,
headquartersAccount.contributionBalance.value.toString(),
headquartersAccount.createdAt,
);
await this.outboxRepository.save({
aggregateType: SystemAccountSyncedEvent.AGGREGATE_TYPE,
aggregateId: 'HEADQUARTERS',
eventType: SystemAccountSyncedEvent.EVENT_TYPE,
payload: hqEvent.toPayload(),
});
}
// 8. 发布事件到 Kafka通过 Outbox
await this.publishBonusClaimEvents(accountSequence, savedRecords, pendingRecords);
this.logger.log(

View File

@ -165,6 +165,56 @@ export class SystemAccountRepository {
return `${regionCode}账户`;
}
/**
*
*/
async subtractContribution(
accountType: SystemAccountType,
regionCode: string | null,
amount: ContributionAmount,
): Promise<void> {
const existing = await this.client.systemAccount.findFirst({
where: {
accountType,
regionCode: regionCode === null ? { equals: null } : regionCode,
},
});
if (existing) {
await this.client.systemAccount.update({
where: { id: existing.id },
data: {
contributionBalance: { decrement: amount.value },
},
});
}
}
/**
*
*/
async deleteContributionRecordsByAdoption(
accountType: SystemAccountType,
regionCode: string | null,
sourceAdoptionId: bigint,
sourceAccountSequence: string,
): Promise<number> {
const systemAccount = await this.findByTypeAndRegion(accountType, regionCode);
if (!systemAccount) {
return 0;
}
const result = await this.client.systemContributionRecord.deleteMany({
where: {
systemAccountId: systemAccount.id,
sourceAdoptionId,
sourceAccountSequence,
},
});
return result.count;
}
async saveContributionRecord(record: {
accountType: SystemAccountType;
regionCode: string | null;