feat: 手动充值、邀请码注册与后台管理增强
新增玩家手动充值全流程(收款方式配置、充值下单/审核、钱包上分), 支持邀请码注册、邀请历史与专属返水率;完善后台代理/玩家管理与响应式操作栏, 并补充前台注册、充值页及多语言错误码。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -287,7 +287,7 @@ export class WalletService {
|
||||
|
||||
let typeWhere: Record<string, unknown> = {};
|
||||
if (typeFilter === 'deposit') {
|
||||
typeWhere = { transactionType: { in: ['MANUAL_DEPOSIT', 'DEPOSIT', 'MANUAL_ADJUST'] } };
|
||||
typeWhere = { transactionType: { in: ['MANUAL_DEPOSIT', 'DEPOSIT', 'MANUAL_ADJUST', 'PLAYER_DEPOSIT'] } };
|
||||
} else if (typeFilter === 'withdraw') {
|
||||
typeWhere = { transactionType: { in: ['MANUAL_WITHDRAW', 'WITHDRAW'] } };
|
||||
} else if (typeFilter === 'bet') {
|
||||
@@ -312,7 +312,7 @@ export class WalletService {
|
||||
private walletTypeCategoryWhere(category?: string): Prisma.WalletTransactionWhereInput {
|
||||
const cat = category?.trim();
|
||||
if (cat === 'deposit') {
|
||||
return { transactionType: { in: ['MANUAL_DEPOSIT', 'DEPOSIT', 'MANUAL_ADJUST'] } };
|
||||
return { transactionType: { in: ['MANUAL_DEPOSIT', 'DEPOSIT', 'MANUAL_ADJUST', 'PLAYER_DEPOSIT'] } };
|
||||
}
|
||||
if (cat === 'withdraw') {
|
||||
return { transactionType: { in: ['MANUAL_WITHDRAW', 'WITHDRAW'] } };
|
||||
@@ -341,6 +341,99 @@ export class WalletService {
|
||||
return {};
|
||||
}
|
||||
|
||||
private static readonly DEPOSIT_RECHARGE_TYPES = new Set([
|
||||
'MANUAL_DEPOSIT',
|
||||
'DEPOSIT',
|
||||
'PLAYER_DEPOSIT',
|
||||
]);
|
||||
|
||||
private paymentMethodDisplayName(pm: {
|
||||
displayName: string | null;
|
||||
bankName: string | null;
|
||||
usdtAddress: string | null;
|
||||
methodType: string;
|
||||
} | null | undefined): string | null {
|
||||
if (!pm) return null;
|
||||
return pm.displayName ?? pm.bankName ?? pm.usdtAddress ?? pm.methodType ?? null;
|
||||
}
|
||||
|
||||
private async resolveDepositMethodsForRows(
|
||||
rows: Array<{ id: bigint; transactionType: string; referenceId: string | null; operatorId: bigint | null }>,
|
||||
) {
|
||||
const rechargeRows = rows.filter((r) => WalletService.DEPOSIT_RECHARGE_TYPES.has(r.transactionType));
|
||||
const result = new Map<
|
||||
string,
|
||||
{ depositMethodKey: string | null; depositMethodName: string | null }
|
||||
>();
|
||||
|
||||
if (!rechargeRows.length) return result;
|
||||
|
||||
const orderNos = [
|
||||
...new Set(
|
||||
rechargeRows
|
||||
.filter((r) => r.transactionType === 'PLAYER_DEPOSIT' && r.referenceId)
|
||||
.map((r) => r.referenceId!),
|
||||
),
|
||||
];
|
||||
const manualOperatorIds = [
|
||||
...new Set(
|
||||
rechargeRows
|
||||
.filter((r) => r.transactionType !== 'PLAYER_DEPOSIT' && r.operatorId)
|
||||
.map((r) => r.operatorId!),
|
||||
),
|
||||
];
|
||||
|
||||
const [orders, operators] = await Promise.all([
|
||||
orderNos.length
|
||||
? this.prisma.depositOrder.findMany({
|
||||
where: { orderNo: { in: orderNos } },
|
||||
include: {
|
||||
paymentMethod: {
|
||||
select: {
|
||||
displayName: true,
|
||||
bankName: true,
|
||||
usdtAddress: true,
|
||||
methodType: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
: [],
|
||||
manualOperatorIds.length
|
||||
? this.prisma.user.findMany({
|
||||
where: { id: { in: manualOperatorIds } },
|
||||
select: { id: true, userType: true },
|
||||
})
|
||||
: [],
|
||||
]);
|
||||
|
||||
const orderByNo = new Map(orders.map((o) => [o.orderNo, o]));
|
||||
const operatorTypeById = new Map(operators.map((o) => [o.id.toString(), o.userType]));
|
||||
|
||||
for (const row of rechargeRows) {
|
||||
const rowKey = row.id.toString();
|
||||
if (row.transactionType === 'PLAYER_DEPOSIT' && row.referenceId) {
|
||||
const order = orderByNo.get(row.referenceId);
|
||||
result.set(rowKey, {
|
||||
depositMethodKey: null,
|
||||
depositMethodName: this.paymentMethodDisplayName(order?.paymentMethod),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
const operatorType = row.operatorId
|
||||
? operatorTypeById.get(row.operatorId.toString())
|
||||
: null;
|
||||
let depositMethodKey = 'MANUAL';
|
||||
if (operatorType === 'ADMIN') depositMethodKey = 'MANUAL_ADMIN';
|
||||
else if (operatorType === 'AGENT') depositMethodKey = 'MANUAL_AGENT';
|
||||
|
||||
result.set(rowKey, { depositMethodKey, depositMethodName: null });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async listWalletTransactionsAdmin(params: {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
@@ -495,11 +588,13 @@ export class WalletService {
|
||||
const playerById = new Map(players.map((p) => [p.id.toString(), p]));
|
||||
const operatorById = new Map(operators.map((u) => [u.id.toString(), u.username]));
|
||||
const parentById = new Map(parentAgents.map((a) => [a.id.toString(), a.username]));
|
||||
const depositMethodByRowId = await this.resolveDepositMethodsForRows(rows);
|
||||
|
||||
return {
|
||||
items: rows.map((row) => {
|
||||
const player = playerById.get(row.userId.toString());
|
||||
const parentId = player?.parentId;
|
||||
const depositMethod = depositMethodByRowId.get(row.id.toString());
|
||||
return {
|
||||
id: row.id.toString(),
|
||||
transactionId: row.transactionId,
|
||||
@@ -516,6 +611,8 @@ export class WalletService {
|
||||
referenceType: row.referenceType,
|
||||
referenceId: row.referenceId,
|
||||
betNo: row.referenceType === 'BET' ? row.referenceId : null,
|
||||
depositMethodKey: depositMethod?.depositMethodKey ?? null,
|
||||
depositMethodName: depositMethod?.depositMethodName ?? null,
|
||||
operatorId: row.operatorId?.toString() ?? null,
|
||||
operatorUsername: row.operatorId
|
||||
? (operatorById.get(row.operatorId.toString()) ?? null)
|
||||
|
||||
Reference in New Issue
Block a user