feat(system-accounts): add ledger detail API for all system accounts
新增所有系统账户的分类账明细查询功能: - wallet-service: 添加 getSystemAccountLedger 和 getAllSystemAccountsLedger 方法 - wallet-service: 添加 /statistics/system-account-ledger 和 /statistics/all-system-accounts-ledger API - reporting-service: 添加 /all-ledger 端点透传分类账数据 🤖 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
56f2fd206d
commit
229dff1a9d
|
|
@ -78,4 +78,24 @@ export class SystemAccountReportController {
|
|||
this.logger.log(`[getExpiredRewards] 请求过期收益统计, startDate=${startDate}, endDate=${endDate}`);
|
||||
return this.systemAccountReportService.getExpiredRewardsSummary({ startDate, endDate });
|
||||
}
|
||||
|
||||
// [2026-01-05] 新增:所有系统账户分类账明细
|
||||
@Get('all-ledger')
|
||||
@ApiOperation({ summary: '获取所有系统账户的分类账明细' })
|
||||
@ApiQuery({ name: 'pageSize', required: false, description: '每个账户显示的条数,默认50' })
|
||||
@ApiQuery({ name: 'startDate', required: false, description: '开始日期 (YYYY-MM-DD)' })
|
||||
@ApiQuery({ name: 'endDate', required: false, description: '结束日期 (YYYY-MM-DD)' })
|
||||
@ApiResponse({ status: 200, description: '所有系统账户的分类账明细' })
|
||||
async getAllSystemAccountsLedger(
|
||||
@Query('pageSize') pageSize?: string,
|
||||
@Query('startDate') startDate?: string,
|
||||
@Query('endDate') endDate?: string,
|
||||
) {
|
||||
this.logger.log(`[getAllSystemAccountsLedger] 请求所有系统账户分类账, pageSize=${pageSize}, startDate=${startDate}, endDate=${endDate}`);
|
||||
return this.systemAccountReportService.getAllSystemAccountsLedger({
|
||||
pageSize: pageSize ? parseInt(pageSize, 10) : undefined,
|
||||
startDate,
|
||||
endDate,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
* 回滚方式:删除此文件,并从 application.module.ts 中移除注册
|
||||
*/
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { WalletServiceClient, OfflineSettlementSummary, AllSystemAccountsResponse } from '../../infrastructure/external/wallet-service/wallet-service.client';
|
||||
import { WalletServiceClient, OfflineSettlementSummary, AllSystemAccountsResponse, AllSystemAccountsLedgerResponse } from '../../infrastructure/external/wallet-service/wallet-service.client';
|
||||
import { RewardServiceClient, ExpiredRewardsSummary } from '../../infrastructure/external/reward-service/reward-service.client';
|
||||
|
||||
/**
|
||||
|
|
@ -184,6 +184,22 @@ export class SystemAccountReportApplicationService {
|
|||
return this.rewardServiceClient.getExpiredRewardsSummary(params);
|
||||
}
|
||||
|
||||
// [2026-01-05] 新增:获取所有系统账户的分类账明细
|
||||
/**
|
||||
* 获取所有系统账户的分类账明细
|
||||
* 返回每个系统账户的交易流水
|
||||
*/
|
||||
async getAllSystemAccountsLedger(params?: {
|
||||
pageSize?: number;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}): Promise<AllSystemAccountsLedgerResponse> {
|
||||
this.logger.log('[getAllSystemAccountsLedger] 开始获取所有系统账户分类账...');
|
||||
const result = await this.walletServiceClient.getAllSystemAccountsLedger(params);
|
||||
this.logger.log(`[getAllSystemAccountsLedger] 完成: 固定=${result.fixedAccountsLedger.length}, 省=${result.provinceAccountsLedger.length}, 市=${result.cityAccountsLedger.length}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组装固定账户数据
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -56,6 +56,44 @@ export interface AllSystemAccountsResponse {
|
|||
}>;
|
||||
}
|
||||
|
||||
// [2026-01-05] 新增:分类账条目类型
|
||||
export interface LedgerEntryDTO {
|
||||
id: string;
|
||||
entryType: string;
|
||||
amount: number;
|
||||
assetType: string;
|
||||
balanceAfter: number | null;
|
||||
refOrderId: string | null;
|
||||
refTxHash: string | null;
|
||||
memo: string | null;
|
||||
allocationType: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
// [2026-01-05] 新增:所有系统账户分类账响应类型
|
||||
export interface AllSystemAccountsLedgerResponse {
|
||||
fixedAccountsLedger: Array<{
|
||||
accountSequence: string;
|
||||
accountType: string;
|
||||
ledger: LedgerEntryDTO[];
|
||||
total: number;
|
||||
}>;
|
||||
provinceAccountsLedger: Array<{
|
||||
accountSequence: string;
|
||||
regionCode: string;
|
||||
regionName: string;
|
||||
ledger: LedgerEntryDTO[];
|
||||
total: number;
|
||||
}>;
|
||||
cityAccountsLedger: Array<{
|
||||
accountSequence: string;
|
||||
regionCode: string;
|
||||
regionName: string;
|
||||
ledger: LedgerEntryDTO[];
|
||||
total: number;
|
||||
}>;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class WalletServiceClient {
|
||||
private readonly logger = new Logger(WalletServiceClient.name);
|
||||
|
|
@ -148,4 +186,38 @@ export class WalletServiceClient {
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
// [2026-01-05] 新增:获取所有系统账户的分类账明细
|
||||
/**
|
||||
* 获取所有系统账户的分类账明细
|
||||
* 返回每个系统账户的交易流水
|
||||
*/
|
||||
async getAllSystemAccountsLedger(params?: {
|
||||
pageSize?: number;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}): Promise<AllSystemAccountsLedgerResponse> {
|
||||
try {
|
||||
const queryParams = new URLSearchParams();
|
||||
if (params?.pageSize) queryParams.append('pageSize', params.pageSize.toString());
|
||||
if (params?.startDate) queryParams.append('startDate', params.startDate);
|
||||
if (params?.endDate) queryParams.append('endDate', params.endDate);
|
||||
|
||||
const url = `${this.baseUrl}/api/v1/wallets/statistics/all-system-accounts-ledger?${queryParams.toString()}`;
|
||||
this.logger.debug(`[getAllSystemAccountsLedger] 请求: ${url}`);
|
||||
|
||||
const response = await firstValueFrom(
|
||||
this.httpService.get<{ success: boolean; data: AllSystemAccountsLedgerResponse }>(url),
|
||||
);
|
||||
|
||||
return response.data.data;
|
||||
} catch (error) {
|
||||
this.logger.error(`[getAllSystemAccountsLedger] 失败: ${error.message}`);
|
||||
return {
|
||||
fixedAccountsLedger: [],
|
||||
provinceAccountsLedger: [],
|
||||
cityAccountsLedger: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
} from '@/application/commands';
|
||||
import { Public } from '@/shared/decorators';
|
||||
import { FiatWithdrawalStatus } from '@/domain/value-objects/fiat-withdrawal-status.enum';
|
||||
import { LedgerEntryType } from '@/domain/value-objects';
|
||||
|
||||
/**
|
||||
* 内部API控制器 - 供其他微服务调用
|
||||
|
|
@ -399,4 +400,67 @@ export class InternalWalletController {
|
|||
this.logger.log(`系统账户查询结果: 固定=${result.fixedAccounts.length}, 省=${result.provinceAccounts.length}, 市=${result.cityAccounts.length}`);
|
||||
return result;
|
||||
}
|
||||
|
||||
// [2026-01-05] 新增:单个系统账户分类账查询
|
||||
@Get('statistics/system-account-ledger')
|
||||
@Public()
|
||||
@ApiOperation({ summary: '获取单个系统账户分类账(内部API)' })
|
||||
@ApiQuery({ name: 'accountSequence', required: true, description: '账户序列号' })
|
||||
@ApiQuery({ name: 'page', required: false, description: '页码,默认1' })
|
||||
@ApiQuery({ name: 'pageSize', required: false, description: '每页条数,默认20' })
|
||||
@ApiQuery({ name: 'entryType', required: false, description: '流水类型筛选' })
|
||||
@ApiQuery({ name: 'startDate', required: false, description: '开始日期' })
|
||||
@ApiQuery({ name: 'endDate', required: false, description: '结束日期' })
|
||||
@ApiResponse({ status: 200, description: '分类账明细列表' })
|
||||
async getSystemAccountLedger(
|
||||
@Query('accountSequence') accountSequence: string,
|
||||
@Query('page') page?: string,
|
||||
@Query('pageSize') pageSize?: string,
|
||||
@Query('entryType') entryType?: string,
|
||||
@Query('startDate') startDate?: string,
|
||||
@Query('endDate') endDate?: string,
|
||||
) {
|
||||
this.logger.log(`========== statistics/system-account-ledger 请求 ==========`);
|
||||
this.logger.log(`accountSequence=${accountSequence}, page=${page}, pageSize=${pageSize}`);
|
||||
|
||||
const result = await this.walletService.getSystemAccountLedger({
|
||||
accountSequence,
|
||||
page: page ? parseInt(page, 10) : 1,
|
||||
pageSize: pageSize ? parseInt(pageSize, 10) : 20,
|
||||
entryType: entryType as LedgerEntryType | undefined,
|
||||
startDate: startDate ? new Date(startDate) : undefined,
|
||||
endDate: endDate ? new Date(endDate) : undefined,
|
||||
});
|
||||
|
||||
this.logger.log(`系统账户分类账查询结果: ${result.total} 条记录`);
|
||||
return result;
|
||||
}
|
||||
|
||||
// [2026-01-05] 新增:所有系统账户分类账查询
|
||||
@Get('statistics/all-system-accounts-ledger')
|
||||
@Public()
|
||||
@ApiOperation({ summary: '获取所有系统账户的分类账明细(内部API) - 用于系统账户报表' })
|
||||
@ApiQuery({ name: 'pageSize', required: false, description: '每个账户显示的条数,默认50' })
|
||||
@ApiQuery({ name: 'startDate', required: false, description: '开始日期' })
|
||||
@ApiQuery({ name: 'endDate', required: false, description: '结束日期' })
|
||||
@ApiResponse({ status: 200, description: '所有系统账户的分类账明细' })
|
||||
async getAllSystemAccountsLedger(
|
||||
@Query('pageSize') pageSize?: string,
|
||||
@Query('startDate') startDate?: string,
|
||||
@Query('endDate') endDate?: string,
|
||||
) {
|
||||
this.logger.log(`========== statistics/all-system-accounts-ledger 请求 ==========`);
|
||||
|
||||
const result = await this.walletService.getAllSystemAccountsLedger({
|
||||
pageSize: pageSize ? parseInt(pageSize, 10) : 50,
|
||||
startDate: startDate ? new Date(startDate) : undefined,
|
||||
endDate: endDate ? new Date(endDate) : undefined,
|
||||
});
|
||||
|
||||
const totalLedgers = result.fixedAccountsLedger.reduce((sum, a) => sum + a.total, 0) +
|
||||
result.provinceAccountsLedger.reduce((sum, a) => sum + a.total, 0) +
|
||||
result.cityAccountsLedger.reduce((sum, a) => sum + a.total, 0);
|
||||
this.logger.log(`所有系统账户分类账查询完成: 固定=${result.fixedAccountsLedger.length}, 省=${result.provinceAccountsLedger.length}, 市=${result.cityAccountsLedger.length}, 总流水=${totalLedgers}`);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1856,6 +1856,180 @@ export class WalletApplicationService {
|
|||
};
|
||||
}
|
||||
|
||||
// [2026-01-05] 新增:系统账户分类账查询
|
||||
/**
|
||||
* 获取单个系统账户分类账(按 accountSequence 查询)
|
||||
*/
|
||||
async getSystemAccountLedger(params: {
|
||||
accountSequence: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
entryType?: LedgerEntryType;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
}): Promise<PaginatedLedgerDTO> {
|
||||
const result = await this.ledgerRepo.findByAccountSequence(
|
||||
params.accountSequence,
|
||||
{
|
||||
entryType: params.entryType,
|
||||
startDate: params.startDate,
|
||||
endDate: params.endDate,
|
||||
},
|
||||
{
|
||||
page: params.page ?? 1,
|
||||
pageSize: params.pageSize ?? 20,
|
||||
},
|
||||
);
|
||||
|
||||
return {
|
||||
data: result.data.map(entry => ({
|
||||
id: entry.id.toString(),
|
||||
entryType: entry.entryType,
|
||||
amount: entry.amount.value,
|
||||
assetType: entry.assetType,
|
||||
balanceAfter: entry.balanceAfter?.value ?? null,
|
||||
refOrderId: entry.refOrderId,
|
||||
refTxHash: entry.refTxHash,
|
||||
memo: entry.memo,
|
||||
allocationType: (entry.payloadJson as Record<string, unknown>)?.allocationType as string ?? null,
|
||||
createdAt: entry.createdAt.toISOString(),
|
||||
})),
|
||||
total: result.total,
|
||||
page: result.page,
|
||||
pageSize: result.pageSize,
|
||||
totalPages: result.totalPages,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有系统账户的分类账明细
|
||||
* 返回每个系统账户的最近流水记录
|
||||
*/
|
||||
async getAllSystemAccountsLedger(params?: {
|
||||
pageSize?: number;
|
||||
startDate?: Date;
|
||||
endDate?: Date;
|
||||
}): Promise<{
|
||||
fixedAccountsLedger: Array<{
|
||||
accountSequence: string;
|
||||
accountType: string;
|
||||
ledger: LedgerEntryDTO[];
|
||||
total: number;
|
||||
}>;
|
||||
provinceAccountsLedger: Array<{
|
||||
accountSequence: string;
|
||||
regionCode: string;
|
||||
regionName: string;
|
||||
ledger: LedgerEntryDTO[];
|
||||
total: number;
|
||||
}>;
|
||||
cityAccountsLedger: Array<{
|
||||
accountSequence: string;
|
||||
regionCode: string;
|
||||
regionName: string;
|
||||
ledger: LedgerEntryDTO[];
|
||||
total: number;
|
||||
}>;
|
||||
}> {
|
||||
const pageSize = params?.pageSize ?? 50; // 每个账户默认显示最近50条
|
||||
|
||||
// 1. 获取所有系统账户
|
||||
const allAccounts = await this.getAllSystemAccounts();
|
||||
|
||||
// 2. 并行获取所有账户的分类账
|
||||
const [fixedLedgers, provinceLedgers, cityLedgers] = await Promise.all([
|
||||
// 固定账户
|
||||
Promise.all(
|
||||
allAccounts.fixedAccounts.map(async account => {
|
||||
const ledgerResult = await this.ledgerRepo.findByAccountSequence(
|
||||
account.accountSequence,
|
||||
{ startDate: params?.startDate, endDate: params?.endDate },
|
||||
{ page: 1, pageSize },
|
||||
);
|
||||
return {
|
||||
accountSequence: account.accountSequence,
|
||||
accountType: account.accountType,
|
||||
ledger: ledgerResult.data.map(entry => ({
|
||||
id: entry.id.toString(),
|
||||
entryType: entry.entryType,
|
||||
amount: entry.amount.value,
|
||||
assetType: entry.assetType,
|
||||
balanceAfter: entry.balanceAfter?.value ?? null,
|
||||
refOrderId: entry.refOrderId,
|
||||
refTxHash: entry.refTxHash,
|
||||
memo: entry.memo,
|
||||
allocationType: (entry.payloadJson as Record<string, unknown>)?.allocationType as string ?? null,
|
||||
createdAt: entry.createdAt.toISOString(),
|
||||
})),
|
||||
total: ledgerResult.total,
|
||||
};
|
||||
}),
|
||||
),
|
||||
// 省账户
|
||||
Promise.all(
|
||||
allAccounts.provinceAccounts.map(async account => {
|
||||
const ledgerResult = await this.ledgerRepo.findByAccountSequence(
|
||||
account.accountSequence,
|
||||
{ startDate: params?.startDate, endDate: params?.endDate },
|
||||
{ page: 1, pageSize },
|
||||
);
|
||||
return {
|
||||
accountSequence: account.accountSequence,
|
||||
regionCode: account.regionCode,
|
||||
regionName: account.regionName,
|
||||
ledger: ledgerResult.data.map(entry => ({
|
||||
id: entry.id.toString(),
|
||||
entryType: entry.entryType,
|
||||
amount: entry.amount.value,
|
||||
assetType: entry.assetType,
|
||||
balanceAfter: entry.balanceAfter?.value ?? null,
|
||||
refOrderId: entry.refOrderId,
|
||||
refTxHash: entry.refTxHash,
|
||||
memo: entry.memo,
|
||||
allocationType: (entry.payloadJson as Record<string, unknown>)?.allocationType as string ?? null,
|
||||
createdAt: entry.createdAt.toISOString(),
|
||||
})),
|
||||
total: ledgerResult.total,
|
||||
};
|
||||
}),
|
||||
),
|
||||
// 市账户
|
||||
Promise.all(
|
||||
allAccounts.cityAccounts.map(async account => {
|
||||
const ledgerResult = await this.ledgerRepo.findByAccountSequence(
|
||||
account.accountSequence,
|
||||
{ startDate: params?.startDate, endDate: params?.endDate },
|
||||
{ page: 1, pageSize },
|
||||
);
|
||||
return {
|
||||
accountSequence: account.accountSequence,
|
||||
regionCode: account.regionCode,
|
||||
regionName: account.regionName,
|
||||
ledger: ledgerResult.data.map(entry => ({
|
||||
id: entry.id.toString(),
|
||||
entryType: entry.entryType,
|
||||
amount: entry.amount.value,
|
||||
assetType: entry.assetType,
|
||||
balanceAfter: entry.balanceAfter?.value ?? null,
|
||||
refOrderId: entry.refOrderId,
|
||||
refTxHash: entry.refTxHash,
|
||||
memo: entry.memo,
|
||||
allocationType: (entry.payloadJson as Record<string, unknown>)?.allocationType as string ?? null,
|
||||
createdAt: entry.createdAt.toISOString(),
|
||||
})),
|
||||
total: ledgerResult.total,
|
||||
};
|
||||
}),
|
||||
),
|
||||
]);
|
||||
|
||||
return {
|
||||
fixedAccountsLedger: fixedLedgers,
|
||||
provinceAccountsLedger: provinceLedgers,
|
||||
cityAccountsLedger: cityLedgers,
|
||||
};
|
||||
}
|
||||
|
||||
// =============== Pending Rewards ===============
|
||||
|
||||
/**
|
||||
|
|
@ -2953,43 +3127,43 @@ export class WalletApplicationService {
|
|||
createdAt: wallet.createdAt.toISOString(),
|
||||
}));
|
||||
}
|
||||
|
||||
// =============== 系统账户报表统计 API - 增强版 ===============
|
||||
// [2026-01-05] 新增:获取所有系统账户列表(固定+区域)
|
||||
// 回滚方式:删除以下方法
|
||||
|
||||
async getAllSystemAccounts(): Promise<{
|
||||
fixedAccounts: Array<{ accountSequence: string; accountType: string; usdtBalance: string; totalReceived: string; totalTransferred: string; status: string; createdAt: string }>;
|
||||
provinceAccounts: Array<{ accountSequence: string; regionCode: string; regionName: string; usdtBalance: string; totalReceived: string; status: string }>;
|
||||
cityAccounts: Array<{ accountSequence: string; regionCode: string; regionName: string; usdtBalance: string; totalReceived: string; status: string }>;
|
||||
}> {
|
||||
this.logger.log('[getAllSystemAccounts] 查询所有系统账户...');
|
||||
const wallets = await this.prisma.walletAccount.findMany({
|
||||
where: { OR: [{ accountSequence: { startsWith: 'S' } }, { accountSequence: { startsWith: '9' } }, { accountSequence: { startsWith: '8' } }] },
|
||||
select: { accountSequence: true, usdtAvailable: true, status: true, createdAt: true },
|
||||
});
|
||||
const accountSeqs = wallets.map(w => w.accountSequence);
|
||||
const receivedStats2 = await this.prisma.ledgerEntry.groupBy({ by: ['accountSequence'], where: { accountSequence: { in: accountSeqs }, amount: { gt: 0 } }, _sum: { amount: true } });
|
||||
const transferredStats = await this.prisma.ledgerEntry.groupBy({ by: ['accountSequence'], where: { accountSequence: { in: accountSeqs }, amount: { lt: 0 } }, _sum: { amount: true } });
|
||||
const receivedMap2 = new Map(receivedStats2.map(s => [s.accountSequence, s._sum.amount]));
|
||||
const transferredMap = new Map(transferredStats.map(s => [s.accountSequence, s._sum.amount]));
|
||||
const fixedAccountTypes: Record<string, string> = { 'S0000000001': 'COST_ACCOUNT', 'S0000000002': 'OPERATION_ACCOUNT', 'S0000000003': 'HQ_COMMUNITY', 'S0000000004': 'RWAD_POOL_PENDING', 'S0000000005': 'PLATFORM_FEE' };
|
||||
const fixedAccounts: Array<{ accountSequence: string; accountType: string; usdtBalance: string; totalReceived: string; totalTransferred: string; status: string; createdAt: string }> = [];
|
||||
const provinceAccounts: Array<{ accountSequence: string; regionCode: string; regionName: string; usdtBalance: string; totalReceived: string; status: string }> = [];
|
||||
const cityAccounts: Array<{ accountSequence: string; regionCode: string; regionName: string; usdtBalance: string; totalReceived: string; status: string }> = [];
|
||||
for (const wallet of wallets) {
|
||||
const seq = wallet.accountSequence;
|
||||
const received = Number(receivedMap2.get(seq) || 0);
|
||||
const transferred = Math.abs(Number(transferredMap.get(seq) || 0));
|
||||
if (seq.startsWith('S')) {
|
||||
fixedAccounts.push({ accountSequence: seq, accountType: fixedAccountTypes[seq] || 'UNKNOWN', usdtBalance: String(wallet.usdtAvailable), totalReceived: String(received), totalTransferred: String(transferred), status: wallet.status, createdAt: wallet.createdAt.toISOString() });
|
||||
} else if (seq.startsWith('9')) {
|
||||
provinceAccounts.push({ accountSequence: seq, regionCode: seq.substring(1), regionName: '省区域 ' + seq.substring(1), usdtBalance: String(wallet.usdtAvailable), totalReceived: String(received), status: wallet.status });
|
||||
} else if (seq.startsWith('8')) {
|
||||
cityAccounts.push({ accountSequence: seq, regionCode: seq.substring(1), regionName: '市区域 ' + seq.substring(1), usdtBalance: String(wallet.usdtAvailable), totalReceived: String(received), status: wallet.status });
|
||||
}
|
||||
}
|
||||
this.logger.log('[getAllSystemAccounts] 固定: ' + fixedAccounts.length + ', 省: ' + provinceAccounts.length + ', 市: ' + cityAccounts.length);
|
||||
return { fixedAccounts, provinceAccounts, cityAccounts };
|
||||
}
|
||||
}
|
||||
|
||||
// =============== 系统账户报表统计 API - 增强版 ===============
|
||||
// [2026-01-05] 新增:获取所有系统账户列表(固定+区域)
|
||||
// 回滚方式:删除以下方法
|
||||
|
||||
async getAllSystemAccounts(): Promise<{
|
||||
fixedAccounts: Array<{ accountSequence: string; accountType: string; usdtBalance: string; totalReceived: string; totalTransferred: string; status: string; createdAt: string }>;
|
||||
provinceAccounts: Array<{ accountSequence: string; regionCode: string; regionName: string; usdtBalance: string; totalReceived: string; status: string }>;
|
||||
cityAccounts: Array<{ accountSequence: string; regionCode: string; regionName: string; usdtBalance: string; totalReceived: string; status: string }>;
|
||||
}> {
|
||||
this.logger.log('[getAllSystemAccounts] 查询所有系统账户...');
|
||||
const wallets = await this.prisma.walletAccount.findMany({
|
||||
where: { OR: [{ accountSequence: { startsWith: 'S' } }, { accountSequence: { startsWith: '9' } }, { accountSequence: { startsWith: '8' } }] },
|
||||
select: { accountSequence: true, usdtAvailable: true, status: true, createdAt: true },
|
||||
});
|
||||
const accountSeqs = wallets.map(w => w.accountSequence);
|
||||
const receivedStats2 = await this.prisma.ledgerEntry.groupBy({ by: ['accountSequence'], where: { accountSequence: { in: accountSeqs }, amount: { gt: 0 } }, _sum: { amount: true } });
|
||||
const transferredStats = await this.prisma.ledgerEntry.groupBy({ by: ['accountSequence'], where: { accountSequence: { in: accountSeqs }, amount: { lt: 0 } }, _sum: { amount: true } });
|
||||
const receivedMap2 = new Map(receivedStats2.map(s => [s.accountSequence, s._sum.amount]));
|
||||
const transferredMap = new Map(transferredStats.map(s => [s.accountSequence, s._sum.amount]));
|
||||
const fixedAccountTypes: Record<string, string> = { 'S0000000001': 'COST_ACCOUNT', 'S0000000002': 'OPERATION_ACCOUNT', 'S0000000003': 'HQ_COMMUNITY', 'S0000000004': 'RWAD_POOL_PENDING', 'S0000000005': 'PLATFORM_FEE' };
|
||||
const fixedAccounts: Array<{ accountSequence: string; accountType: string; usdtBalance: string; totalReceived: string; totalTransferred: string; status: string; createdAt: string }> = [];
|
||||
const provinceAccounts: Array<{ accountSequence: string; regionCode: string; regionName: string; usdtBalance: string; totalReceived: string; status: string }> = [];
|
||||
const cityAccounts: Array<{ accountSequence: string; regionCode: string; regionName: string; usdtBalance: string; totalReceived: string; status: string }> = [];
|
||||
for (const wallet of wallets) {
|
||||
const seq = wallet.accountSequence;
|
||||
const received = Number(receivedMap2.get(seq) || 0);
|
||||
const transferred = Math.abs(Number(transferredMap.get(seq) || 0));
|
||||
if (seq.startsWith('S')) {
|
||||
fixedAccounts.push({ accountSequence: seq, accountType: fixedAccountTypes[seq] || 'UNKNOWN', usdtBalance: String(wallet.usdtAvailable), totalReceived: String(received), totalTransferred: String(transferred), status: wallet.status, createdAt: wallet.createdAt.toISOString() });
|
||||
} else if (seq.startsWith('9')) {
|
||||
provinceAccounts.push({ accountSequence: seq, regionCode: seq.substring(1), regionName: '省区域 ' + seq.substring(1), usdtBalance: String(wallet.usdtAvailable), totalReceived: String(received), status: wallet.status });
|
||||
} else if (seq.startsWith('8')) {
|
||||
cityAccounts.push({ accountSequence: seq, regionCode: seq.substring(1), regionName: '市区域 ' + seq.substring(1), usdtBalance: String(wallet.usdtAvailable), totalReceived: String(received), status: wallet.status });
|
||||
}
|
||||
}
|
||||
this.logger.log('[getAllSystemAccounts] 固定: ' + fixedAccounts.length + ', 省: ' + provinceAccounts.length + ', 市: ' + cityAccounts.length);
|
||||
return { fixedAccounts, provinceAccounts, cityAccounts };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue