fix: 修复 wallet-service 支持 accountSequence 格式及订单状态机

1. wallet-service/internal-wallet.controller.ts:
   - getBalance: 支持 accountSequence (D开头) 和 userId (纯数字) 两种格式

2. wallet-service/wallet-application.service.ts:
   - freezeForPlanting: 修复 BigInt 转换错误,优先按 accountSequence 查找钱包
   - confirmPlantingDeduction: 同上
   - unfreezeForPlanting: 同上
   - getMyWallet: 支持 userId='0' 的情况(仅通过 accountSequence 查询)

3. planting-service/planting-order.aggregate.ts:
   - schedulePoolInjection: 状态检查从 FUND_ALLOCATED 改为 PAID
   - 原因: 资金分配已移至 reward-service 异步处理

修复问题: "Cannot convert D25121300006 to a BigInt"

🤖 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 2025-12-12 22:35:18 -08:00
parent ad82e3ee44
commit d20ff9e9b5
3 changed files with 50 additions and 31 deletions

View File

@ -262,9 +262,10 @@ export class PlantingOrder {
/**
*
* reward-service
*/
schedulePoolInjection(batchId: bigint, scheduledTime: Date): void {
this.ensureStatus(PlantingOrderStatus.FUND_ALLOCATED);
this.ensureStatus(PlantingOrderStatus.PAID);
this._poolInjectionBatchId = batchId;
this._poolInjectionScheduledTime = scheduledTime;

View File

@ -29,8 +29,14 @@ export class InternalWalletController {
@ApiParam({ name: 'userId', description: '用户ID或accountSequence' })
@ApiResponse({ status: 200, description: '余额信息' })
async getBalance(@Param('userId') userId: string) {
// 优先使用 accountSequence如果相同则使用 userId
const query = new GetMyWalletQuery(userId, userId);
// 判断是 accountSequence (以 D 开头) 还是 userId (纯数字)
const isAccountSequence = userId.startsWith('D');
// 如果是 accountSequenceuserId 参数设为 '0'(会被忽略,通过 accountSequence 查找)
// 如果是纯 userIdaccountSequence 参数设为 userId会通过 userId 查找)
const query = new GetMyWalletQuery(
isAccountSequence ? userId : userId, // accountSequence
isAccountSequence ? '0' : userId, // userId (如果是 accountSequence 则忽略)
);
const wallet = await this.walletService.getMyWallet(query);
return {
userId,

View File

@ -196,7 +196,6 @@ export class WalletApplicationService {
this.logger.log(`[freezeForPlanting] amount: ${command.amount}`);
this.logger.log(`[freezeForPlanting] orderId: ${command.orderId}`);
const userId = BigInt(command.userId);
const amount = Money.USDT(command.amount);
this.logger.log(`[freezeForPlanting] 解析后 amount.value: ${amount.value}`);
@ -216,7 +215,11 @@ export class WalletApplicationService {
// 优先按 accountSequence 查找,如果未找到则按 userId 查找
let wallet = await this.walletRepo.findByAccountSequence(command.userId);
if (!wallet) {
wallet = await this.walletRepo.findByUserId(userId);
// 尝试将 userId 转换为 BigInt如果不是 accountSequence 格式)
const isAccountSequence = command.userId.startsWith('D');
if (!isAccountSequence) {
wallet = await this.walletRepo.findByUserId(BigInt(command.userId));
}
}
if (!wallet) {
this.logger.error(`[freezeForPlanting] 钱包不存在: userId/accountSequence=${command.userId}`);
@ -249,7 +252,7 @@ export class WalletApplicationService {
// 记录冻结流水
const ledgerEntry = LedgerEntry.create({
accountSequence: wallet.accountSequence,
userId: UserId.create(userId),
userId: wallet.userId,
entryType: LedgerEntryType.PLANT_FREEZE,
amount: Money.signed(-command.amount, 'USDT'), // Negative: 可用余额减少
balanceAfter: wallet.balances.usdt.available,
@ -259,7 +262,7 @@ export class WalletApplicationService {
await this.ledgerRepo.save(ledgerEntry);
this.logger.log(`[freezeForPlanting] 流水已记录`);
await this.walletCacheService.invalidateWallet(userId);
await this.walletCacheService.invalidateWallet(wallet.userId.value);
this.logger.log(`[freezeForPlanting] 成功冻结 ${command.amount} USDT for order ${command.orderId}`);
return { success: true, frozenAmount: command.amount };
@ -270,8 +273,6 @@ export class WalletApplicationService {
*
*/
async confirmPlantingDeduction(command: ConfirmPlantingDeductionCommand): Promise<boolean> {
const userId = BigInt(command.userId);
// 查找冻结记录,获取冻结金额
const existingEntries = await this.ledgerRepo.findByRefOrderId(command.orderId);
@ -300,7 +301,11 @@ export class WalletApplicationService {
// 优先按 accountSequence 查找,如果未找到则按 userId 查找
let wallet = await this.walletRepo.findByAccountSequence(command.userId);
if (!wallet) {
wallet = await this.walletRepo.findByUserId(userId);
// 尝试将 userId 转换为 BigInt如果不是 accountSequence 格式)
const isAccountSequence = command.userId.startsWith('D');
if (!isAccountSequence) {
wallet = await this.walletRepo.findByUserId(BigInt(command.userId));
}
}
if (!wallet) {
throw new WalletNotFoundError(`userId/accountSequence: ${command.userId}`);
@ -313,7 +318,7 @@ export class WalletApplicationService {
// 记录扣款流水
const ledgerEntry = LedgerEntry.create({
accountSequence: wallet.accountSequence,
userId: UserId.create(userId),
userId: wallet.userId,
entryType: LedgerEntryType.PLANT_PAYMENT,
amount: Money.signed(-frozenAmount.value, 'USDT'),
balanceAfter: wallet.balances.usdt.available,
@ -322,7 +327,7 @@ export class WalletApplicationService {
});
await this.ledgerRepo.save(ledgerEntry);
await this.walletCacheService.invalidateWallet(userId);
await this.walletCacheService.invalidateWallet(wallet.userId.value);
this.logger.log(`Confirmed deduction ${frozenAmount.value} USDT for order ${command.orderId}`);
return true;
@ -333,8 +338,6 @@ export class WalletApplicationService {
*
*/
async unfreezeForPlanting(command: UnfreezeForPlantingCommand): Promise<boolean> {
const userId = BigInt(command.userId);
// 查找相关流水
const existingEntries = await this.ledgerRepo.findByRefOrderId(command.orderId);
@ -378,7 +381,11 @@ export class WalletApplicationService {
// 优先按 accountSequence 查找,如果未找到则按 userId 查找
let wallet = await this.walletRepo.findByAccountSequence(command.userId);
if (!wallet) {
wallet = await this.walletRepo.findByUserId(userId);
// 尝试将 userId 转换为 BigInt如果不是 accountSequence 格式)
const isAccountSequence = command.userId.startsWith('D');
if (!isAccountSequence) {
wallet = await this.walletRepo.findByUserId(BigInt(command.userId));
}
}
if (!wallet) {
throw new WalletNotFoundError(`userId/accountSequence: ${command.userId}`);
@ -391,7 +398,7 @@ export class WalletApplicationService {
// 记录解冻流水
const ledgerEntry = LedgerEntry.create({
accountSequence: wallet.accountSequence,
userId: UserId.create(userId),
userId: wallet.userId,
entryType: LedgerEntryType.PLANT_UNFREEZE,
amount: frozenAmount, // Positive: 可用余额增加
balanceAfter: wallet.balances.usdt.available,
@ -400,7 +407,7 @@ export class WalletApplicationService {
});
await this.ledgerRepo.save(ledgerEntry);
await this.walletCacheService.invalidateWallet(userId);
await this.walletCacheService.invalidateWallet(wallet.userId.value);
this.logger.log(`Unfrozen ${frozenAmount.value} USDT for order ${command.orderId}`);
return true;
@ -915,23 +922,28 @@ export class WalletApplicationService {
async getMyWallet(query: GetMyWalletQuery): Promise<WalletDTO> {
const accountSequence = query.accountSequence;
const userId = BigInt(query.userId);
// userId 可能是 '0' (当仅通过 accountSequence 查询时),此时跳过缓存和 BigInt 转换
const userIdStr = query.userId;
const hasValidUserId = userIdStr && userIdStr !== '0' && !userIdStr.startsWith('D');
const userId = hasValidUserId ? BigInt(userIdStr) : BigInt(0);
// Try to get from cache first
const cached = await this.walletCacheService.getWallet(userId);
if (cached) {
this.logger.debug(`Returning cached wallet for user: ${userId}`);
return {
walletId: cached.walletId,
userId: cached.userId,
balances: cached.balances,
hashpower: cached.hashpower,
rewards: cached.rewards,
status: cached.status,
};
// Try to get from cache first (only if we have a valid userId)
if (hasValidUserId) {
const cached = await this.walletCacheService.getWallet(userId);
if (cached) {
this.logger.debug(`Returning cached wallet for user: ${userId}`);
return {
walletId: cached.walletId,
userId: cached.userId,
balances: cached.balances,
hashpower: cached.hashpower,
rewards: cached.rewards,
status: cached.status,
};
}
}
// Cache miss - fetch from database (by accountSequence)
// Cache miss or no valid userId - fetch from database (by accountSequence)
const wallet = await this.walletRepo.getOrCreate(accountSequence, userId);
const walletDTO: WalletDTO = {