diff --git a/backend/services/reward-service/src/application/services/reward-application.service.ts b/backend/services/reward-service/src/application/services/reward-application.service.ts index 4c625bfb..cb8bf89c 100644 --- a/backend/services/reward-service/src/application/services/reward-application.service.ts +++ b/backend/services/reward-service/src/application/services/reward-application.service.ts @@ -122,6 +122,7 @@ export class RewardApplicationService { /** * 用户认种后,将该用户的待领取奖励转为可结算 + * @deprecated 使用 claimPendingRewardsForAccountSequence 代替 */ async claimPendingRewardsForUser(userId: bigint): Promise<{ claimedCount: number; @@ -153,17 +154,55 @@ export class RewardApplicationService { await this.rewardSummaryRepository.save(summary); - // 写入 Outbox 同步到 wallet-service - // [已屏蔽] 前端直接从 reward-service 查询,不再同步到 wallet-service - // if (claimedCount > 0) { - // await this.publishSummaryUpdatesToOutbox([summary]); - // } - this.logger.log(`Claimed ${claimedCount} rewards for user ${userId}, total ${totalUsdtClaimed} USDT`); return { claimedCount, totalUsdtClaimed }; } + /** + * 用户认种后,将该用户的待领取奖励转为可结算(使用 accountSequence) + */ + async claimPendingRewardsForAccountSequence(accountSequence: string): Promise<{ + claimedCount: number; + totalUsdtClaimed: number; + }> { + this.logger.log(`Claiming pending rewards for accountSequence ${accountSequence}`); + + const pendingRewards = await this.rewardLedgerEntryRepository.findPendingByAccountSequence(accountSequence); + if (pendingRewards.length === 0) { + this.logger.log(`No pending rewards found for accountSequence ${accountSequence}`); + return { claimedCount: 0, totalUsdtClaimed: 0 }; + } + + // 从第一条奖励记录获取 userId + const userId = pendingRewards[0].userId; + const summary = await this.rewardSummaryRepository.getOrCreate(userId, accountSequence); + + let claimedCount = 0; + let totalUsdtClaimed = 0; + + for (const reward of pendingRewards) { + if (!reward.isExpiredNow()) { + reward.claim(); + await this.rewardLedgerEntryRepository.save(reward); + + summary.movePendingToSettleable(reward.usdtAmount, reward.hashpowerAmount); + + claimedCount++; + totalUsdtClaimed += reward.usdtAmount.amount; + + await this.eventPublisher.publishAll(reward.domainEvents); + reward.clearDomainEvents(); + } + } + + await this.rewardSummaryRepository.save(summary); + + this.logger.log(`Claimed ${claimedCount} rewards for accountSequence ${accountSequence}, total ${totalUsdtClaimed} USDT`); + + return { claimedCount, totalUsdtClaimed }; + } + /** * 结算可结算收益 */ diff --git a/backend/services/reward-service/src/infrastructure/kafka/event-consumer.controller.ts b/backend/services/reward-service/src/infrastructure/kafka/event-consumer.controller.ts index 74d9568b..8a3af163 100644 --- a/backend/services/reward-service/src/infrastructure/kafka/event-consumer.controller.ts +++ b/backend/services/reward-service/src/infrastructure/kafka/event-consumer.controller.ts @@ -77,7 +77,10 @@ export class EventConsumerController { }); // 2. 检查该用户是否有待领取奖励需要转为可结算 - await this.rewardService.claimPendingRewardsForUser(BigInt(eventData.userId)); + // 使用 accountSequence 查找,因为奖励是按 accountSequence 存储的 + if (eventData.accountSequence) { + await this.rewardService.claimPendingRewardsForAccountSequence(eventData.accountSequence); + } this.logger.log(`Successfully processed planting.order.paid for order ${eventData.orderId}`);