104 lines
3.5 KiB
TypeScript
Raw Normal View History

import { Injectable, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { FreebitOrchestratorService } from "@bff/integrations/freebit/services/freebit-orchestrator.service.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 } from "@customer-portal/domain/sim";
import type { SimTopUpHistoryRequest } from "@customer-portal/domain/sim";
import { SimScheduleService } from "./sim-schedule.service.js";
@Injectable()
export class SimUsageService {
constructor(
private readonly freebitService: FreebitOrchestratorService,
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<SimUsage> {
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<SimTopUpHistory> {
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;
}
}
}