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