From 7dc25b75d2e3fc83249f00d16c5326ff232ee192 Mon Sep 17 00:00:00 2001 From: hailin Date: Tue, 6 Jan 2026 07:07:27 -0800 Subject: [PATCH] =?UTF-8?q?revert:=20=E5=9B=9E=E6=BB=9A=20settleToBalance?= =?UTF-8?q?=20=E7=9A=84=E7=9B=B4=E6=8E=A5=20Prisma=20=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=EF=BC=8C=E5=87=86=E5=A4=87=E7=94=A8=20Unit=20of=20Work=20?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E9=87=8D=E6=96=B0=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../services/wallet-application.service.ts | 107 +++++------------- 1 file changed, 30 insertions(+), 77 deletions(-) diff --git a/backend/services/wallet-service/src/application/services/wallet-application.service.ts b/backend/services/wallet-service/src/application/services/wallet-application.service.ts index 8d68de25..854d823c 100644 --- a/backend/services/wallet-service/src/application/services/wallet-application.service.ts +++ b/backend/services/wallet-service/src/application/services/wallet-application.service.ts @@ -909,89 +909,42 @@ export class WalletApplicationService { }> { this.logger.log(`Settling ${params.usdtAmount} USDT to balance for ${params.accountSequence}`); - // 生成结算ID - const settlementId = `STL_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - let balanceAfter = 0; - let userId: bigint = BigInt(0); - try { - // 使用事务确保账户余额更新和流水记录的原子性 - await this.prisma.$transaction(async (tx) => { - // 1. 查找钱包 - const walletRecord = await tx.walletAccount.findUnique({ - where: { accountSequence: params.accountSequence }, - }); - if (!walletRecord) { - throw new WalletNotFoundError(`accountSequence: ${params.accountSequence}`); - } + // 1. 查找钱包 + const wallet = await this.walletRepo.findByAccountSequence(params.accountSequence); + if (!wallet) { + throw new WalletNotFoundError(`accountSequence: ${params.accountSequence}`); + } - userId = walletRecord.userId; + const usdtAmount = Money.USDT(params.usdtAmount); + const userId = wallet.userId.value; - // 2. 验证钱包状态是否 ACTIVE - if (walletRecord.status !== 'ACTIVE') { - throw new Error(`Wallet is not active: ${walletRecord.status}`); - } + // 2. 生成结算ID + const settlementId = `STL_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - const Decimal = (await import('decimal.js')).default; - const usdtAmountDecimal = new Decimal(params.usdtAmount); - const currentSettleable = new Decimal(walletRecord.settleableUsdt.toString()); - const currentAvailable = new Decimal(walletRecord.usdtAvailable.toString()); - const currentSettledTotal = new Decimal(walletRecord.settledTotalUsdt.toString()); + // 3. 执行钱包结算 + wallet.settleToBalance(usdtAmount, settlementId); + await this.walletRepo.save(wallet); - // 3. 验证可结算余额足够 - if (currentSettleable.lessThan(usdtAmountDecimal)) { - throw new Error(`Insufficient settleable balance: ${currentSettleable} < ${usdtAmountDecimal}`); - } - - // 4. 计算新余额 - const newSettleable = currentSettleable.minus(usdtAmountDecimal); - const newAvailable = currentAvailable.plus(usdtAmountDecimal); - const newSettledTotal = currentSettledTotal.plus(usdtAmountDecimal); - balanceAfter = newAvailable.toNumber(); - - // 5. 更新钱包账户(在事务内,使用乐观锁) - const currentVersion = walletRecord.version; - const updateResult = await tx.walletAccount.updateMany({ - where: { - accountSequence: params.accountSequence, - version: currentVersion, // 乐观锁:只有版本匹配才更新 - }, - data: { - settleableUsdt: newSettleable.toFixed(8), - usdtAvailable: newAvailable.toFixed(8), - settledTotalUsdt: newSettledTotal.toFixed(8), - version: currentVersion + 1, - updatedAt: new Date(), - }, - }); - - if (updateResult.count === 0) { - throw new Error(`Optimistic lock conflict for wallet ${params.accountSequence}`); - } - - // 6. 创建流水记录(在事务内) - await tx.ledgerEntry.create({ - data: { - accountSequence: params.accountSequence, - userId: walletRecord.userId, - entryType: LedgerEntryType.REWARD_SETTLED, - amount: usdtAmountDecimal.toFixed(8), - assetType: 'USDT', - balanceAfter: newAvailable.toFixed(8), - refOrderId: settlementId, - memo: params.memo || `结算 ${params.usdtAmount} 绿积分到钱包余额`, - payloadJson: { - settlementType: 'SETTLE_TO_BALANCE', - rewardEntryIds: params.rewardEntryIds, - rewardCount: params.rewardEntryIds.length, - breakdown: params.breakdown, - }, - createdAt: new Date(), - }, - }); + // 4. 记录账本流水(含详细来源信息) + const ledgerEntry = LedgerEntry.create({ + accountSequence: wallet.accountSequence, + userId: UserId.create(userId), + entryType: LedgerEntryType.REWARD_SETTLED, + amount: usdtAmount, + balanceAfter: wallet.balances.usdt.available, + refOrderId: settlementId, + memo: params.memo || `结算 ${params.usdtAmount} 绿积分到钱包余额`, + payloadJson: { + settlementType: 'SETTLE_TO_BALANCE', + rewardEntryIds: params.rewardEntryIds, + rewardCount: params.rewardEntryIds.length, + breakdown: params.breakdown, + }, }); + await this.ledgerRepo.save(ledgerEntry); - // 7. 使缓存失效(在事务外,事务成功后执行) + // 5. 使缓存失效 await this.walletCacheService.invalidateWallet(userId); this.logger.log(`Successfully settled ${params.usdtAmount} USDT to balance for ${params.accountSequence}`); @@ -1000,7 +953,7 @@ export class WalletApplicationService { success: true, settlementId, settledAmount: params.usdtAmount, - balanceAfter, + balanceAfter: wallet.balances.usdt.available.value, }; } catch (error) { this.logger.error(`Failed to settle to balance for ${params.accountSequence}: ${error.message}`);