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:
parent
ad82e3ee44
commit
d20ff9e9b5
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
// 如果是 accountSequence,userId 参数设为 '0'(会被忽略,通过 accountSequence 查找)
|
||||
// 如果是纯 userId,accountSequence 参数设为 userId(会通过 userId 查找)
|
||||
const query = new GetMyWalletQuery(
|
||||
isAccountSequence ? userId : userId, // accountSequence
|
||||
isAccountSequence ? '0' : userId, // userId (如果是 accountSequence 则忽略)
|
||||
);
|
||||
const wallet = await this.walletService.getMyWallet(query);
|
||||
return {
|
||||
userId,
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue