fix(transfer): 修复积分股划转到分配账户失败问题
后端: - transfer.service.ts: Error → BadRequestException,业务错误返回HTTP 400而非500 - transfer.controller.ts: Error → UnauthorizedException,正确返回HTTP 401 - 错误信息改为中文:余额不足、账户不存在等提示更明确 前端: - asset_display.dart: 新增 tradingAvailableShares 计算属性(总可用 - 挖矿可用) - trading_page.dart: 划转弹窗显示可用余额(扣除冻结)而非总余额 - trading_page.dart: 划转失败时显示后端具体错误信息而非通用提示 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3cbb874503
commit
8e63547a3e
|
|
@ -1,4 +1,4 @@
|
|||
import { Controller, Get, Post, Param, Query, Body, Req } from '@nestjs/common';
|
||||
import { Controller, Get, Post, Param, Query, Body, Req, UnauthorizedException } from '@nestjs/common';
|
||||
import { ApiTags, ApiOperation, ApiResponse, ApiBearerAuth, ApiQuery } from '@nestjs/swagger';
|
||||
import { IsString } from 'class-validator';
|
||||
import { TransferService } from '../../application/services/transfer.service';
|
||||
|
|
@ -19,7 +19,7 @@ export class TransferController {
|
|||
async transferIn(@Body() dto: TransferDto, @Req() req: any) {
|
||||
const accountSequence = req.user?.accountSequence;
|
||||
if (!accountSequence) {
|
||||
throw new Error('Unauthorized');
|
||||
throw new UnauthorizedException('未登录');
|
||||
}
|
||||
|
||||
return this.transferService.transferIn(accountSequence, dto.amount);
|
||||
|
|
@ -30,7 +30,7 @@ export class TransferController {
|
|||
async transferOut(@Body() dto: TransferDto, @Req() req: any) {
|
||||
const accountSequence = req.user?.accountSequence;
|
||||
if (!accountSequence) {
|
||||
throw new Error('Unauthorized');
|
||||
throw new UnauthorizedException('未登录');
|
||||
}
|
||||
|
||||
return this.transferService.transferOut(accountSequence, dto.amount);
|
||||
|
|
@ -47,7 +47,7 @@ export class TransferController {
|
|||
) {
|
||||
const accountSequence = req.user?.accountSequence;
|
||||
if (!accountSequence) {
|
||||
throw new Error('Unauthorized');
|
||||
throw new UnauthorizedException('未登录');
|
||||
}
|
||||
|
||||
return this.transferService.getTransferHistory(accountSequence, page ?? 1, pageSize ?? 50);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { Injectable, Logger, BadRequestException } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { TradingAccountRepository } from '../../infrastructure/persistence/repositories/trading-account.repository';
|
||||
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
|
||||
|
|
@ -27,7 +27,7 @@ export class TransferService {
|
|||
const transferAmount = new Money(amount);
|
||||
|
||||
if (transferAmount.value.lessThan(this.minTransferAmount)) {
|
||||
throw new Error(`Minimum transfer amount is ${this.minTransferAmount}`);
|
||||
throw new BadRequestException(`最低划转数量为 ${this.minTransferAmount}`);
|
||||
}
|
||||
|
||||
const transferNo = this.generateTransferNo();
|
||||
|
|
@ -48,7 +48,7 @@ export class TransferService {
|
|||
const response = await this.callMiningServiceTransferOut(accountSequence, amount, transferNo);
|
||||
|
||||
if (!response.success) {
|
||||
throw new Error(response.message || 'Mining service transfer failed');
|
||||
throw new BadRequestException(response.message || '挖矿服务划转失败');
|
||||
}
|
||||
|
||||
// 增加交易账户余额
|
||||
|
|
@ -94,16 +94,16 @@ export class TransferService {
|
|||
const transferAmount = new Money(amount);
|
||||
|
||||
if (transferAmount.value.lessThan(this.minTransferAmount)) {
|
||||
throw new Error(`Minimum transfer amount is ${this.minTransferAmount}`);
|
||||
throw new BadRequestException(`最低划转数量为 ${this.minTransferAmount}`);
|
||||
}
|
||||
|
||||
const account = await this.accountRepository.findByAccountSequence(accountSequence);
|
||||
if (!account) {
|
||||
throw new Error('Trading account not found');
|
||||
throw new BadRequestException('交易账户不存在');
|
||||
}
|
||||
|
||||
if (account.availableShares.isLessThan(transferAmount)) {
|
||||
throw new Error('Insufficient available shares');
|
||||
throw new BadRequestException('可用积分股不足(部分积分股可能已被 C2C 订单冻结)');
|
||||
}
|
||||
|
||||
const transferNo = this.generateTransferNo();
|
||||
|
|
@ -131,7 +131,7 @@ export class TransferService {
|
|||
// 回滚交易账户余额
|
||||
account.transferSharesIn(transferAmount, `${transferNo}_rollback`);
|
||||
await this.accountRepository.save(account);
|
||||
throw new Error(response.message || 'Mining service transfer failed');
|
||||
throw new BadRequestException(response.message || '挖矿服务划转失败');
|
||||
}
|
||||
|
||||
// 更新划转记录
|
||||
|
|
|
|||
|
|
@ -67,6 +67,14 @@ class AssetDisplay extends Equatable {
|
|||
required this.totalSold,
|
||||
});
|
||||
|
||||
/// 交易账户可用积分股(扣除冻结部分)= 总可用积分股 - 挖矿账户可用积分股
|
||||
String get tradingAvailableShares {
|
||||
final totalAvailable = double.tryParse(availableShares) ?? 0;
|
||||
final miningAvailable = double.tryParse(miningShareBalance) ?? 0;
|
||||
final result = totalAvailable - miningAvailable;
|
||||
return result < 0 ? '0' : result.toStringAsFixed(8);
|
||||
}
|
||||
|
||||
/// 总积分股余额 = 可用 + 冻结
|
||||
String get totalShareBalance {
|
||||
final available = double.tryParse(availableShares) ?? 0;
|
||||
|
|
|
|||
|
|
@ -402,8 +402,10 @@ class _TradingPageState extends ConsumerState<TradingPage> {
|
|||
|
||||
// 挖矿账户积分股(可划转卖出)
|
||||
final miningShareBalance = asset?.miningShareBalance ?? '0';
|
||||
// 交易账户积分股(可直接卖出)
|
||||
// 交易账户积分股总余额(含冻结,用于显示)
|
||||
final tradingShareBalance = asset?.tradingShareBalance ?? '0';
|
||||
// 交易账户可用积分股(扣除冻结,用于划转)
|
||||
final tradingAvailableShares = asset?.tradingAvailableShares ?? '0';
|
||||
// 可用积分股(总计:挖矿 + 交易)
|
||||
final availableShares = asset?.availableShares ?? '0';
|
||||
// 可用积分值(现金)
|
||||
|
|
@ -612,7 +614,7 @@ class _TradingPageState extends ConsumerState<TradingPage> {
|
|||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: GestureDetector(
|
||||
onTap: () => _showTransferDialog(miningShareBalance, tradingShareBalance),
|
||||
onTap: () => _showTransferDialog(miningShareBalance, tradingAvailableShares),
|
||||
child: const Text(
|
||||
'划转',
|
||||
style: TextStyle(
|
||||
|
|
@ -1626,9 +1628,10 @@ class _TransferBottomSheetState extends ConsumerState<_TransferBottomSheet> {
|
|||
),
|
||||
);
|
||||
} else {
|
||||
final errorMsg = ref.read(tradingNotifierProvider).error ?? '划转失败,请稍后重试';
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('划转失败,请稍后重试'),
|
||||
SnackBar(
|
||||
content: Text(errorMsg),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in New Issue