From 367e34f3a6a92a40b19915f3b494f30df2c17235 Mon Sep 17 00:00:00 2001 From: hailin Date: Sun, 14 Dec 2025 05:58:19 -0800 Subject: [PATCH] =?UTF-8?q?fix(reward):=20=E5=BE=85=E9=A2=86=E5=8F=96?= =?UTF-8?q?=E5=A5=96=E5=8A=B1=E8=BD=AC=E5=8F=AF=E7=BB=93=E7=AE=97=E4=BD=BF?= =?UTF-8?q?=E7=94=A8accountSequence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 claimPendingRewardsForAccountSequence 方法 - event-consumer 改用 accountSequence 查找待领取奖励 - 修复上家认种后待领取奖励不能转为可结算的问题 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../services/reward-application.service.ts | 51 ++++++++++++++++--- .../kafka/event-consumer.controller.ts | 5 +- 2 files changed, 49 insertions(+), 7 deletions(-) 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}`);