import { Injectable, Inject } from "@nestjs/common"; import { PrismaService } from "../common/prisma/prisma.service"; import { Logger } from "nestjs-pino"; @Injectable() export class SimUsageStoreService { constructor( private readonly prisma: PrismaService, @Inject(Logger) private readonly logger: Logger ) {} private get store(): { upsert: (args: unknown) => Promise; findMany: (args: unknown) => Promise; deleteMany: (args: unknown) => Promise; } | null { const s = ( this.prisma as { simUsageDaily?: { upsert: (args: unknown) => Promise; findMany: (args: unknown) => Promise; deleteMany: (args: unknown) => Promise; }; } )?.simUsageDaily; return s && typeof s === "object" ? s : null; } private normalizeDate(date?: Date): Date { const d = date ? new Date(date) : new Date(); // strip time to YYYY-MM-DD const iso = d.toISOString().split("T")[0]; return new Date(iso + "T00:00:00.000Z"); } async upsertToday(account: string, usageMb: number, date?: Date): Promise { const day = this.normalizeDate(date); try { const store = this.store; if (!store) { this.logger.debug("SIM usage store not configured; skipping persist"); return; } await store.upsert({ where: { account_date: { account, date: day } }, update: { usageMb }, create: { account, date: day, usageMb }, }); } catch (e: unknown) { const message = e instanceof Error ? e.message : String(e); this.logger.error("Failed to upsert daily usage", { account, error: message }); } } async getLastNDays( account: string, days = 30 ): Promise> { const end = this.normalizeDate(); const start = new Date(end); start.setUTCDate(end.getUTCDate() - (days - 1)); const store = this.store; if (!store) return []; const rows = (await store.findMany({ where: { account, date: { gte: start, lte: end } }, orderBy: { date: "desc" }, })) as Array<{ date: Date; usageMb: number }>; return rows.map(r => ({ date: r.date.toISOString().split("T")[0], usageMb: r.usageMb })); } async cleanupPreviousMonths(): Promise { const now = new Date(); const firstOfMonth = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1)); const store = this.store; if (!store) return 0; const result = (await store.deleteMany({ where: { date: { lt: firstOfMonth } }, })) as { count: number }; return result.count; } }