fix(admin-service): 修复金额显示单位错误
移除错误的 1e8 乘除转换: - 数据库存储的是实际金额 (Decimal(20,8)),不需要缩放 - decimalToBigint → decimalToString: 直接格式化为字符串 - 移除 controller 中不再需要的 formatDecimal 方法 - 更新接口类型: bigint → string (金额相关字段) 影响的接口: - PlantingSummary.totalAmount - PlantingLedgerItem.totalAmount - WalletSummary 所有余额字段 - WalletLedgerItem.amount/balanceAfter - SystemAccountLedger.amount/balanceAfter 🤖 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
1c5fd9eaad
commit
eccc637a02
|
|
@ -217,7 +217,7 @@ export class UserDetailController {
|
|||
summary: {
|
||||
totalOrders: summary?.totalOrders || 0,
|
||||
totalTreeCount: summary?.totalTreeCount || 0,
|
||||
totalAmount: this.formatDecimal(summary?.totalAmount),
|
||||
totalAmount: summary?.totalAmount || '0',
|
||||
effectiveTreeCount: summary?.effectiveTreeCount || 0,
|
||||
pendingTreeCount: summary?.pendingTreeCount || 0,
|
||||
firstPlantingAt: summary?.firstPlantingAt?.toISOString() || null,
|
||||
|
|
@ -227,7 +227,7 @@ export class UserDetailController {
|
|||
orderId: item.orderId.toString(),
|
||||
orderNo: item.orderNo,
|
||||
treeCount: item.treeCount,
|
||||
totalAmount: this.formatDecimal(item.totalAmount),
|
||||
totalAmount: item.totalAmount,
|
||||
status: item.status,
|
||||
selectedProvince: item.selectedProvince,
|
||||
selectedCity: item.selectedCity,
|
||||
|
|
@ -281,32 +281,32 @@ export class UserDetailController {
|
|||
|
||||
return {
|
||||
summary: {
|
||||
usdtAvailable: this.formatDecimal(summary?.usdtAvailable),
|
||||
usdtFrozen: this.formatDecimal(summary?.usdtFrozen),
|
||||
dstAvailable: this.formatDecimal(summary?.dstAvailable),
|
||||
dstFrozen: this.formatDecimal(summary?.dstFrozen),
|
||||
bnbAvailable: this.formatDecimal(summary?.bnbAvailable),
|
||||
bnbFrozen: this.formatDecimal(summary?.bnbFrozen),
|
||||
ogAvailable: this.formatDecimal(summary?.ogAvailable),
|
||||
ogFrozen: this.formatDecimal(summary?.ogFrozen),
|
||||
rwadAvailable: this.formatDecimal(summary?.rwadAvailable),
|
||||
rwadFrozen: this.formatDecimal(summary?.rwadFrozen),
|
||||
hashpower: this.formatDecimal(summary?.hashpower),
|
||||
pendingUsdt: this.formatDecimal(summary?.pendingUsdt),
|
||||
pendingHashpower: this.formatDecimal(summary?.pendingHashpower),
|
||||
settleableUsdt: this.formatDecimal(summary?.settleableUsdt),
|
||||
settleableHashpower: this.formatDecimal(summary?.settleableHashpower),
|
||||
settledTotalUsdt: this.formatDecimal(summary?.settledTotalUsdt),
|
||||
settledTotalHashpower: this.formatDecimal(summary?.settledTotalHashpower),
|
||||
expiredTotalUsdt: this.formatDecimal(summary?.expiredTotalUsdt),
|
||||
expiredTotalHashpower: this.formatDecimal(summary?.expiredTotalHashpower),
|
||||
usdtAvailable: summary?.usdtAvailable || '0',
|
||||
usdtFrozen: summary?.usdtFrozen || '0',
|
||||
dstAvailable: summary?.dstAvailable || '0',
|
||||
dstFrozen: summary?.dstFrozen || '0',
|
||||
bnbAvailable: summary?.bnbAvailable || '0',
|
||||
bnbFrozen: summary?.bnbFrozen || '0',
|
||||
ogAvailable: summary?.ogAvailable || '0',
|
||||
ogFrozen: summary?.ogFrozen || '0',
|
||||
rwadAvailable: summary?.rwadAvailable || '0',
|
||||
rwadFrozen: summary?.rwadFrozen || '0',
|
||||
hashpower: summary?.hashpower || '0',
|
||||
pendingUsdt: summary?.pendingUsdt || '0',
|
||||
pendingHashpower: summary?.pendingHashpower || '0',
|
||||
settleableUsdt: summary?.settleableUsdt || '0',
|
||||
settleableHashpower: summary?.settleableHashpower || '0',
|
||||
settledTotalUsdt: summary?.settledTotalUsdt || '0',
|
||||
settledTotalHashpower: summary?.settledTotalHashpower || '0',
|
||||
expiredTotalUsdt: summary?.expiredTotalUsdt || '0',
|
||||
expiredTotalHashpower: summary?.expiredTotalHashpower || '0',
|
||||
},
|
||||
items: ledger.items.map((item) => ({
|
||||
entryId: item.entryId.toString(),
|
||||
entryType: item.entryType,
|
||||
assetType: item.assetType,
|
||||
amount: this.formatDecimal(item.amount),
|
||||
balanceAfter: item.balanceAfter ? this.formatDecimal(item.balanceAfter) : null,
|
||||
amount: item.amount,
|
||||
balanceAfter: item.balanceAfter,
|
||||
refOrderId: item.refOrderId,
|
||||
refTxHash: item.refTxHash,
|
||||
memo: item.memo,
|
||||
|
|
@ -380,8 +380,8 @@ export class UserDetailController {
|
|||
accountId: ledger.accountId.toString(),
|
||||
accountType: ledger.accountType,
|
||||
entryType: ledger.entryType,
|
||||
amount: this.formatDecimal(ledger.amount),
|
||||
balanceAfter: this.formatDecimal(ledger.balanceAfter),
|
||||
amount: ledger.amount,
|
||||
balanceAfter: ledger.balanceAfter,
|
||||
sourceOrderId: ledger.sourceOrderId?.toString() || null,
|
||||
sourceRewardId: ledger.sourceRewardId?.toString() || null,
|
||||
txHash: ledger.txHash,
|
||||
|
|
@ -408,10 +408,4 @@ export class UserDetailController {
|
|||
}
|
||||
}
|
||||
|
||||
private formatDecimal(value: bigint | null | undefined): string {
|
||||
if (!value) return '0';
|
||||
// bigint 已经乘以 1e8,需要转回小数
|
||||
const num = Number(value) / 1e8;
|
||||
return num.toFixed(8).replace(/\.?0+$/, '');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export interface ReferralNode {
|
|||
export interface PlantingSummary {
|
||||
totalOrders: number;
|
||||
totalTreeCount: number;
|
||||
totalAmount: bigint; // Decimal as bigint for precision
|
||||
totalAmount: string; // 格式化后的金额字符串
|
||||
effectiveTreeCount: number;
|
||||
pendingTreeCount: number;
|
||||
firstPlantingAt: Date | null;
|
||||
|
|
@ -47,7 +47,7 @@ export interface PlantingLedgerItem {
|
|||
orderId: bigint;
|
||||
orderNo: string;
|
||||
treeCount: number;
|
||||
totalAmount: bigint;
|
||||
totalAmount: string; // 格式化后的金额字符串
|
||||
status: string;
|
||||
selectedProvince: string | null;
|
||||
selectedCity: string | null;
|
||||
|
|
@ -70,33 +70,33 @@ export interface PlantingLedgerResult {
|
|||
// ============================================================================
|
||||
|
||||
export interface WalletSummary {
|
||||
usdtAvailable: bigint;
|
||||
usdtFrozen: bigint;
|
||||
dstAvailable: bigint;
|
||||
dstFrozen: bigint;
|
||||
bnbAvailable: bigint;
|
||||
bnbFrozen: bigint;
|
||||
ogAvailable: bigint;
|
||||
ogFrozen: bigint;
|
||||
rwadAvailable: bigint;
|
||||
rwadFrozen: bigint;
|
||||
hashpower: bigint;
|
||||
pendingUsdt: bigint;
|
||||
pendingHashpower: bigint;
|
||||
settleableUsdt: bigint;
|
||||
settleableHashpower: bigint;
|
||||
settledTotalUsdt: bigint;
|
||||
settledTotalHashpower: bigint;
|
||||
expiredTotalUsdt: bigint;
|
||||
expiredTotalHashpower: bigint;
|
||||
usdtAvailable: string;
|
||||
usdtFrozen: string;
|
||||
dstAvailable: string;
|
||||
dstFrozen: string;
|
||||
bnbAvailable: string;
|
||||
bnbFrozen: string;
|
||||
ogAvailable: string;
|
||||
ogFrozen: string;
|
||||
rwadAvailable: string;
|
||||
rwadFrozen: string;
|
||||
hashpower: string;
|
||||
pendingUsdt: string;
|
||||
pendingHashpower: string;
|
||||
settleableUsdt: string;
|
||||
settleableHashpower: string;
|
||||
settledTotalUsdt: string;
|
||||
settledTotalHashpower: string;
|
||||
expiredTotalUsdt: string;
|
||||
expiredTotalHashpower: string;
|
||||
}
|
||||
|
||||
export interface WalletLedgerItem {
|
||||
entryId: bigint;
|
||||
entryType: string;
|
||||
assetType: string;
|
||||
amount: bigint;
|
||||
balanceAfter: bigint | null;
|
||||
amount: string; // 格式化后的金额字符串
|
||||
balanceAfter: string | null; // 格式化后的余额字符串
|
||||
refOrderId: string | null;
|
||||
refTxHash: string | null;
|
||||
memo: string | null;
|
||||
|
|
@ -164,8 +164,8 @@ export interface SystemAccountLedger {
|
|||
accountId: bigint;
|
||||
accountType: string;
|
||||
entryType: string;
|
||||
amount: bigint;
|
||||
balanceAfter: bigint;
|
||||
amount: string; // 格式化后的金额字符串
|
||||
balanceAfter: string; // 格式化后的余额字符串
|
||||
sourceOrderId: bigint | null;
|
||||
sourceRewardId: bigint | null;
|
||||
txHash: string | null;
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
return {
|
||||
totalOrders: orderStats._count,
|
||||
totalTreeCount: orderStats._sum.treeCount || 0,
|
||||
totalAmount: this.decimalToBigint(orderStats._sum.totalAmount),
|
||||
totalAmount: this.decimalToString(orderStats._sum.totalAmount),
|
||||
effectiveTreeCount: position?.effectiveTreeCount || 0,
|
||||
pendingTreeCount: position?.pendingTreeCount || 0,
|
||||
firstPlantingAt: firstOrder?.paidAt || null,
|
||||
|
|
@ -246,7 +246,7 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
orderId: item.id,
|
||||
orderNo: item.orderNo,
|
||||
treeCount: item.treeCount,
|
||||
totalAmount: this.decimalToBigint(item.totalAmount),
|
||||
totalAmount: this.decimalToString(item.totalAmount),
|
||||
status: item.status,
|
||||
selectedProvince: item.selectedProvince,
|
||||
selectedCity: item.selectedCity,
|
||||
|
|
@ -278,25 +278,25 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
if (!wallet) return null;
|
||||
|
||||
return {
|
||||
usdtAvailable: this.decimalToBigint(wallet.usdtAvailable),
|
||||
usdtFrozen: this.decimalToBigint(wallet.usdtFrozen),
|
||||
dstAvailable: this.decimalToBigint(wallet.dstAvailable),
|
||||
dstFrozen: this.decimalToBigint(wallet.dstFrozen),
|
||||
bnbAvailable: this.decimalToBigint(wallet.bnbAvailable),
|
||||
bnbFrozen: this.decimalToBigint(wallet.bnbFrozen),
|
||||
ogAvailable: this.decimalToBigint(wallet.ogAvailable),
|
||||
ogFrozen: this.decimalToBigint(wallet.ogFrozen),
|
||||
rwadAvailable: this.decimalToBigint(wallet.rwadAvailable),
|
||||
rwadFrozen: this.decimalToBigint(wallet.rwadFrozen),
|
||||
hashpower: this.decimalToBigint(wallet.hashpower),
|
||||
pendingUsdt: this.decimalToBigint(wallet.pendingUsdt),
|
||||
pendingHashpower: this.decimalToBigint(wallet.pendingHashpower),
|
||||
settleableUsdt: this.decimalToBigint(wallet.settleableUsdt),
|
||||
settleableHashpower: this.decimalToBigint(wallet.settleableHashpower),
|
||||
settledTotalUsdt: this.decimalToBigint(wallet.settledTotalUsdt),
|
||||
settledTotalHashpower: this.decimalToBigint(wallet.settledTotalHashpower),
|
||||
expiredTotalUsdt: this.decimalToBigint(wallet.expiredTotalUsdt),
|
||||
expiredTotalHashpower: this.decimalToBigint(wallet.expiredTotalHashpower),
|
||||
usdtAvailable: this.decimalToString(wallet.usdtAvailable),
|
||||
usdtFrozen: this.decimalToString(wallet.usdtFrozen),
|
||||
dstAvailable: this.decimalToString(wallet.dstAvailable),
|
||||
dstFrozen: this.decimalToString(wallet.dstFrozen),
|
||||
bnbAvailable: this.decimalToString(wallet.bnbAvailable),
|
||||
bnbFrozen: this.decimalToString(wallet.bnbFrozen),
|
||||
ogAvailable: this.decimalToString(wallet.ogAvailable),
|
||||
ogFrozen: this.decimalToString(wallet.ogFrozen),
|
||||
rwadAvailable: this.decimalToString(wallet.rwadAvailable),
|
||||
rwadFrozen: this.decimalToString(wallet.rwadFrozen),
|
||||
hashpower: this.decimalToString(wallet.hashpower),
|
||||
pendingUsdt: this.decimalToString(wallet.pendingUsdt),
|
||||
pendingHashpower: this.decimalToString(wallet.pendingHashpower),
|
||||
settleableUsdt: this.decimalToString(wallet.settleableUsdt),
|
||||
settleableHashpower: this.decimalToString(wallet.settleableHashpower),
|
||||
settledTotalUsdt: this.decimalToString(wallet.settledTotalUsdt),
|
||||
settledTotalHashpower: this.decimalToString(wallet.settledTotalHashpower),
|
||||
expiredTotalUsdt: this.decimalToString(wallet.expiredTotalUsdt),
|
||||
expiredTotalHashpower: this.decimalToString(wallet.expiredTotalHashpower),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -337,8 +337,8 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
entryId: item.id,
|
||||
entryType: item.entryType,
|
||||
assetType: item.assetType,
|
||||
amount: this.decimalToBigint(item.amount),
|
||||
balanceAfter: item.balanceAfter ? this.decimalToBigint(item.balanceAfter) : null,
|
||||
amount: this.decimalToString(item.amount),
|
||||
balanceAfter: item.balanceAfter ? this.decimalToString(item.balanceAfter) : null,
|
||||
refOrderId: item.refOrderId,
|
||||
refTxHash: item.refTxHash,
|
||||
memo: item.memo,
|
||||
|
|
@ -431,19 +431,13 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
// 辅助方法
|
||||
// ============================================================================
|
||||
|
||||
private decimalToBigint(decimal: Decimal | null | undefined): bigint {
|
||||
if (!decimal) return BigInt(0);
|
||||
// 转换为字符串后解析,保留精度
|
||||
const str = decimal.toString();
|
||||
// 移除小数点,按整数处理
|
||||
const parts = str.split('.');
|
||||
if (parts.length === 1) {
|
||||
return BigInt(parts[0]);
|
||||
}
|
||||
// 有小数部分,乘以 10^小数位数
|
||||
const scale = parts[1].length;
|
||||
const intPart = parts[0] + parts[1];
|
||||
// 返回原始数值(不做缩放,保持 decimal 格式)
|
||||
return BigInt(Math.round(parseFloat(str) * 1e8));
|
||||
/**
|
||||
* 将 Decimal 转为字符串,保留合理精度
|
||||
* 数据库存的是实际金额,直接格式化为最多 8 位小数
|
||||
*/
|
||||
private decimalToString(decimal: Decimal | null | undefined): string {
|
||||
if (!decimal) return '0';
|
||||
// 直接转字符串,去掉尾部多余的 0
|
||||
return decimal.toFixed(8).replace(/\.?0+$/, '');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue