import { Injectable, Logger } from '@nestjs/common'; import { PromoMetricEventType } from '@dukang/shared-types'; import { PrismaService } from '../../common/prisma/prisma.module'; import { IpGeoService } from '../../common/geo/ip-geo.service'; export type PromoMetricLogInput = { promoCodeId: bigint; eventType: PromoMetricEventType; userId?: bigint; orderId?: bigint; sessionId?: string; clientIp?: string; }; @Injectable() export class PromoMetricLogService { private readonly logger = new Logger(PromoMetricLogService.name); constructor( private readonly prisma: PrismaService, private readonly ipGeoService: IpGeoService, ) {} logEvent(input: PromoMetricLogInput): void { void this.writeEvent(input).catch((err) => { this.logger.debug( `promo metric log failed: ${err instanceof Error ? err.message : err}`, ); }); } private async writeEvent(input: PromoMetricLogInput): Promise { const clientIp = input.clientIp?.trim() || null; const geo = clientIp ? this.ipGeoService.resolve(clientIp) : { province: null, city: null }; await this.prisma.logPromoEvent.create({ data: { promoCodeId: input.promoCodeId, eventType: input.eventType, userId: input.userId ?? null, orderId: input.orderId ?? null, sessionId: input.sessionId?.trim() || null, clientIp, ipProvince: geo.province, ipCity: geo.city, }, }); } }