fix(wallet-service): 统一奖励分配到 settleable_usdt,与 reward-service 保持一致

问题原因:
wallet-service 对不同类型奖励的分配方式不一致:
- SHARE_RIGHT: 正确使用 addSettleableReward() → settleable_usdt
- CITY_TEAM_RIGHT/COMMUNITY_RIGHT: 错误使用 addAvailableBalance() → usdt_available

这导致 reward-service 记录的 SETTLEABLE 奖励总额与 wallet-service 的
settleable_usdt 字段不匹配。用户 D25122700024 的案例中:
- reward-service: 3条奖励共 4464 USDT (SHARE_RIGHT 3600 + CITY_TEAM_RIGHT 288 + COMMUNITY_RIGHT 576)
- wallet-service: settleable_usdt = 3600 (仅 SHARE_RIGHT)
差额 864 USDT 被错误地放入了 usdt_available

修复内容:
1. allocateCommunityRight: 改用 addSettleableReward() 替代 addAvailableBalance()
2. allocateToRegionAccount: 改用 addSettleableReward() 替代 addAvailableBalance()
3. 流水类型统一使用 REWARD_TO_SETTLEABLE 替代 SYSTEM_ALLOCATION
4. 日志和备注更新以反映新的分配方式

设计原则:
- reward-service 是奖励的权威来源
- wallet-service 应跟随 reward-service 的设计
- 所有奖励都应进入 settleable_usdt,用户主动结算后才转入 usdt_available

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-06 03:49:31 -08:00
parent ec71121907
commit 573e58c89b
1 changed files with 15 additions and 11 deletions

View File

@ -1198,19 +1198,21 @@ export class WalletApplicationService {
}
const amount = Money.USDT(allocation.amount);
wallet.addAvailableBalance(amount);
// 所有奖励都应该进入可结算余额 (settleable_usdt),与 reward-service 保持一致
// 用户需要主动点击"结算"才能将 settleable_usdt 转入 usdt_available
wallet.addSettleableReward(amount, Hashpower.create(0));
await this.walletRepo.save(wallet);
// 记录流水
// 记录流水 - 使用 REWARD_TO_SETTLEABLE 类型,与 SHARE_RIGHT 保持一致
const ledgerEntry = LedgerEntry.create({
accountSequence: wallet.accountSequence,
userId: wallet.userId,
entryType: LedgerEntryType.SYSTEM_ALLOCATION,
entryType: LedgerEntryType.REWARD_TO_SETTLEABLE,
amount,
refOrderId: orderId,
memo: isUserAccount
? `${allocation.allocationType} - community authorization allocation`
: `${allocation.allocationType} - headquarters community allocation`,
? `${allocation.allocationType} - community authorization allocation (settleable)`
: `${allocation.allocationType} - headquarters community allocation (settleable)`,
payloadJson: {
allocationType: allocation.allocationType,
metadata: allocation.metadata,
@ -1221,7 +1223,7 @@ export class WalletApplicationService {
await this.walletCacheService.invalidateWallet(wallet.userId.value);
this.logger.debug(
`Allocated ${allocation.amount} USDT to ${isUserAccount ? 'community user' : 'headquarters'} ${wallet.accountSequence} for ${allocation.allocationType}`,
`Allocated ${allocation.amount} USDT to ${isUserAccount ? 'community user' : 'headquarters'} ${wallet.accountSequence} for ${allocation.allocationType} (settleable)`,
);
}
@ -1260,17 +1262,19 @@ export class WalletApplicationService {
}
const amount = Money.USDT(allocation.amount);
wallet.addAvailableBalance(amount);
// 所有奖励都应该进入可结算余额 (settleable_usdt),与 reward-service 保持一致
// 用户需要主动点击"结算"才能将 settleable_usdt 转入 usdt_available
wallet.addSettleableReward(amount, Hashpower.create(0));
await this.walletRepo.save(wallet);
// 记录流水
// 记录流水 - 使用 REWARD_TO_SETTLEABLE 类型,与 SHARE_RIGHT 保持一致
const ledgerEntry = LedgerEntry.create({
accountSequence: wallet.accountSequence,
userId: wallet.userId,
entryType: LedgerEntryType.SYSTEM_ALLOCATION,
entryType: LedgerEntryType.REWARD_TO_SETTLEABLE,
amount,
refOrderId: orderId,
memo: `${allocation.allocationType} - region account allocation`,
memo: `${allocation.allocationType} - region account allocation (settleable)`,
payloadJson: {
allocationType: allocation.allocationType,
metadata: allocation.metadata,
@ -1281,7 +1285,7 @@ export class WalletApplicationService {
await this.walletCacheService.invalidateWallet(wallet.userId.value);
this.logger.debug(
`Allocated ${allocation.amount} USDT to region account ${targetId} for ${allocation.allocationType} (direct)`,
`Allocated ${allocation.amount} USDT to region account ${targetId} for ${allocation.allocationType} (settleable)`,
);
}