import { Injectable, Inject } from "@nestjs/common"; import { Logger } from "nestjs-pino"; import { FreebitFacade } from "@bff/integrations/freebit/facades/freebit.facade.js"; import { SimValidationService } from "./sim-validation.service.js"; import { SimUsageStoreService } from "../../sim-usage-store.service.js"; import { extractErrorMessage } from "@bff/core/utils/error.util.js"; import type { SimTopUpHistory, SimUsage, SimTopUpHistoryRequest, } from "@customer-portal/domain/sim"; import { SimScheduleService } from "./sim-schedule.service.js"; @Injectable() export class SimUsageService { constructor( private readonly freebitService: FreebitFacade, private readonly simValidation: SimValidationService, private readonly usageStore: SimUsageStoreService, private readonly simSchedule: SimScheduleService, @Inject(Logger) private readonly logger: Logger ) {} /** * Get SIM data usage for a subscription */ async getSimUsage(userId: string, subscriptionId: number): Promise { try { const { account } = await this.simValidation.validateSimSubscription(userId, subscriptionId); const simUsage = await this.freebitService.getSimUsage(account); // Persist today's usage for monthly charts and cleanup previous months try { await this.usageStore.upsertToday(account, simUsage.todayUsageMb); await this.usageStore.cleanupPreviousMonths(); const stored = await this.usageStore.getLastNDays(account, 30); if (stored.length > 0) { simUsage.recentDaysUsage = stored.map(d => ({ date: d.date, usageKb: Math.round(d.usageMb * 1000), usageMb: d.usageMb, })); } } catch (e) { const sanitizedError = extractErrorMessage(e); this.logger.warn("SIM usage persistence failed (non-fatal)", { account, error: sanitizedError, }); } this.logger.log(`Retrieved SIM usage for subscription ${subscriptionId}`, { userId, subscriptionId, account, todayUsageMb: simUsage.todayUsageMb, }); return simUsage; } catch (error) { const sanitizedError = extractErrorMessage(error); this.logger.error(`Failed to get SIM usage for subscription ${subscriptionId}`, { error: sanitizedError, userId, subscriptionId, }); throw error; } } /** * Get SIM top-up history */ async getSimTopUpHistory( userId: string, subscriptionId: number, request: SimTopUpHistoryRequest ): Promise { try { const { account } = await this.simValidation.validateSimSubscription(userId, subscriptionId); const fromDate = this.simSchedule.ensureYyyyMmDd(request.fromDate, "fromDate"); const toDate = this.simSchedule.ensureYyyyMmDd(request.toDate, "toDate"); const history = await this.freebitService.getSimTopUpHistory(account, fromDate, toDate); this.logger.log(`Retrieved SIM top-up history for subscription ${subscriptionId}`, { userId, subscriptionId, account, totalAdditions: history.totalAdditions, }); return history; } catch (error) { const sanitizedError = extractErrorMessage(error); this.logger.error(`Failed to get SIM top-up history for subscription ${subscriptionId}`, { error: sanitizedError, userId, subscriptionId, }); throw error; } } }