162 lines
5.4 KiB
TypeScript
162 lines
5.4 KiB
TypeScript
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
import { Prisma } from '@prisma/client';
|
|
import {
|
|
eventNamesForPartnerLogCategory,
|
|
resolvePartnerLogCategory,
|
|
} from '@dukang/shared-types';
|
|
import { PrismaService } from '../../common/prisma/prisma.module';
|
|
import { serializeBigInt } from '../../common/decorators/current-user.decorator';
|
|
import type { AdminPartnerLogsQueryDto } from './dto/admin-query.dto';
|
|
|
|
@Injectable()
|
|
export class AdminPartnerLogsService {
|
|
constructor(private readonly prisma: PrismaService) {}
|
|
|
|
async list(query: AdminPartnerLogsQueryDto) {
|
|
const page = query.page ?? 1;
|
|
const pageSize = query.pageSize ?? 20;
|
|
const partnerAccountIds = await this.resolvePartnerAccountIds(query);
|
|
if (partnerAccountIds && partnerAccountIds.length === 0) {
|
|
return { items: [], total: 0, page, pageSize };
|
|
}
|
|
|
|
const where = this.buildWhere(query, partnerAccountIds);
|
|
const [rows, total] = await Promise.all([
|
|
this.prisma.logPartnerAnalytics.findMany({
|
|
where,
|
|
orderBy: { createdAt: 'desc' },
|
|
skip: (page - 1) * pageSize,
|
|
take: pageSize,
|
|
}),
|
|
this.prisma.logPartnerAnalytics.count({ where }),
|
|
]);
|
|
|
|
const items = await this.enrichRows(rows);
|
|
return serializeBigInt({ items, total, page, pageSize });
|
|
}
|
|
|
|
async detail(id: string) {
|
|
const row = await this.prisma.logPartnerAnalytics.findUnique({ where: { id: BigInt(id) } });
|
|
if (!row) throw new NotFoundException('日志不存在');
|
|
const [item] = await this.enrichRows([row]);
|
|
return serializeBigInt(item);
|
|
}
|
|
|
|
private buildWhere(
|
|
query: AdminPartnerLogsQueryDto,
|
|
partnerAccountIds?: bigint[],
|
|
): Prisma.LogPartnerAnalyticsWhereInput {
|
|
const where: Prisma.LogPartnerAnalyticsWhereInput = {};
|
|
if (partnerAccountIds) where.partnerAccountId = { in: partnerAccountIds };
|
|
if (query.partnerAccountId) where.partnerAccountId = BigInt(query.partnerAccountId);
|
|
const categoryEvents = query.eventName
|
|
? [query.eventName]
|
|
: query.category
|
|
? eventNamesForPartnerLogCategory(query.category)
|
|
: undefined;
|
|
if (categoryEvents?.length) where.eventName = { in: categoryEvents };
|
|
if (query.from || query.to) {
|
|
where.createdAt = {
|
|
...(query.from ? { gte: new Date(query.from) } : {}),
|
|
...(query.to ? { lte: new Date(query.to) } : {}),
|
|
};
|
|
}
|
|
return where;
|
|
}
|
|
|
|
private async expandPrimaryWithChildren(primaryIds: bigint[]): Promise<bigint[]> {
|
|
if (!primaryIds.length) return [];
|
|
const children = await this.prisma.partnerAccount.findMany({
|
|
where: { parentAccountId: { in: primaryIds } },
|
|
select: { id: true },
|
|
});
|
|
return [...primaryIds, ...children.map((c) => c.id)];
|
|
}
|
|
|
|
private async resolvePartnerAccountIds(
|
|
query: AdminPartnerLogsQueryDto,
|
|
): Promise<bigint[] | undefined> {
|
|
if (query.partnerAccountId) return [BigInt(query.partnerAccountId)];
|
|
if (query.partnerId) {
|
|
return this.expandPrimaryWithChildren([BigInt(query.partnerId)]);
|
|
}
|
|
|
|
if (query.phone) {
|
|
const accounts = await this.prisma.partnerAccount.findMany({
|
|
where: { phone: { contains: query.phone } },
|
|
select: { id: true },
|
|
take: 200,
|
|
});
|
|
return accounts.map((a) => a.id);
|
|
}
|
|
|
|
if (query.companyName) {
|
|
const primaries = await this.prisma.partnerAccount.findMany({
|
|
where: { isPrimary: 1, companyName: { contains: query.companyName } },
|
|
select: { id: true },
|
|
take: 100,
|
|
});
|
|
return this.expandPrimaryWithChildren(primaries.map((a) => a.id));
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
private async enrichRows(
|
|
rows: Array<{
|
|
id: bigint;
|
|
partnerAccountId: bigint;
|
|
eventName: string;
|
|
clientApp: string | null;
|
|
refType: string | null;
|
|
refId: bigint | null;
|
|
extraJson: unknown;
|
|
createdAt: Date;
|
|
}>,
|
|
) {
|
|
const accountIds = [...new Set(rows.map((r) => r.partnerAccountId))];
|
|
const accounts = accountIds.length
|
|
? await this.prisma.partnerAccount.findMany({
|
|
where: { id: { in: accountIds } },
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
phone: true,
|
|
companyName: true,
|
|
isPrimary: true,
|
|
parentAccountId: true,
|
|
staffRole: true,
|
|
parent: { select: { id: true, companyName: true } },
|
|
},
|
|
})
|
|
: [];
|
|
|
|
const accountMap = new Map(accounts.map((a) => [a.id.toString(), a] as const));
|
|
|
|
return rows.map((row) => {
|
|
const account = accountMap.get(row.partnerAccountId.toString());
|
|
const isSubAccount = !!account?.parentAccountId;
|
|
const primaryId = isSubAccount
|
|
? account?.parent?.id?.toString() ?? null
|
|
: account?.id.toString() ?? null;
|
|
return {
|
|
id: row.id.toString(),
|
|
partnerId: primaryId ?? row.partnerAccountId.toString(),
|
|
partnerAccountId: row.partnerAccountId.toString(),
|
|
accountName: account?.name ?? null,
|
|
accountPhone: account?.phone ?? null,
|
|
companyName: isSubAccount ? null : account?.companyName ?? null,
|
|
isSubAccount,
|
|
staffRole: account?.staffRole ?? null,
|
|
category: resolvePartnerLogCategory(row.eventName),
|
|
eventName: row.eventName,
|
|
clientApp: row.clientApp,
|
|
refType: row.refType,
|
|
refId: row.refId?.toString() ?? null,
|
|
extraJson: (row.extraJson as Record<string, unknown> | null) ?? null,
|
|
createdAt: row.createdAt,
|
|
};
|
|
});
|
|
}
|
|
}
|