feat: add smoke tests, agent credit ledger, and player cashback page

Introduce admin smoke-test suite with API probes, agent credit transaction history, and player cashback records; fix SmokeTestModule DI and polish admin/player UI assets.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-09 16:05:48 +08:00
parent 9c6c5e51f3
commit d5e7c8edb3
52 changed files with 3357 additions and 67 deletions

View File

@@ -693,6 +693,108 @@ export class AgentsService {
};
}
async listCreditTransactions(params: {
page?: number;
pageSize?: number;
agentId?: bigint;
keyword?: string;
transactionType?: string;
}) {
const page = Math.max(1, params.page ?? 1);
const pageSize = Math.min(100, Math.max(1, params.pageSize ?? 20));
const skip = (page - 1) * pageSize;
const where: Prisma.AgentCreditTransactionWhereInput = {};
if (params.transactionType?.trim()) {
where.transactionType = params.transactionType.trim();
}
const keyword = params.keyword?.trim();
if (keyword) {
const matched = await this.prisma.user.findMany({
where: {
userType: 'AGENT',
deletedAt: null,
username: { contains: keyword, mode: 'insensitive' },
},
select: { id: true },
take: 50,
});
const agentUserIds = matched.map((u) => u.id);
if (!agentUserIds.length) {
return { items: [], total: 0, page, pageSize };
}
if (params.agentId) {
if (!agentUserIds.some((id) => id === params.agentId)) {
return { items: [], total: 0, page, pageSize };
}
where.agentId = params.agentId;
} else {
where.agentId = { in: agentUserIds };
}
} else if (params.agentId) {
where.agentId = params.agentId;
}
const [rows, total] = await Promise.all([
this.prisma.agentCreditTransaction.findMany({
where,
orderBy: { createdAt: 'desc' },
skip,
take: pageSize,
}),
this.prisma.agentCreditTransaction.count({ where }),
]);
const agentIds = [...new Set(rows.map((r) => r.agentId))];
const operatorIds = [
...new Set(rows.map((r) => r.operatorId).filter((id): id is bigint => id != null)),
];
const [agentUsers, operators] = await Promise.all([
agentIds.length
? this.prisma.user.findMany({
where: { id: { in: agentIds } },
select: { id: true, username: true },
})
: [],
operatorIds.length
? this.prisma.user.findMany({
where: { id: { in: operatorIds } },
select: { id: true, username: true },
})
: [],
]);
const agentNameById = new Map(agentUsers.map((u) => [u.id.toString(), u.username]));
const operatorNameById = new Map(operators.map((u) => [u.id.toString(), u.username]));
return {
items: rows.map((row) => ({
id: row.id.toString(),
agentId: row.agentId.toString(),
agentUsername: agentNameById.get(row.agentId.toString()) ?? null,
transactionType: row.transactionType,
amount: row.amount.toString(),
creditBefore: row.creditBefore.toString(),
creditAfter: row.creditAfter.toString(),
referenceType: row.referenceType,
referenceId: row.referenceId,
operatorId: row.operatorId?.toString() ?? null,
operatorUsername: row.operatorId
? (operatorNameById.get(row.operatorId.toString()) ?? null)
: null,
requestId: row.requestId,
remark: row.remark,
createdAt: row.createdAt,
})),
total,
page,
pageSize,
};
}
async updateAgentAdmin(
agentId: bigint,
data: {