112 lines
3.5 KiB
TypeScript
Raw Normal View History

import { Injectable, Inject } from "@nestjs/common";
import { Logger } from "nestjs-pino";
import { FreebitService } from "@bff/integrations/freebit/freebit.service";
import { SimValidationService } from "./sim-validation.service";
import { SimUsageStoreService } from "../../sim-usage-store.service";
import { getErrorMessage } from "@bff/core/utils/error.util";
import type {
SimUsage,
SimTopUpHistory,
} from "@bff/integrations/freebit/interfaces/freebit.types";
import type { SimTopUpHistoryRequest } from "../types/sim-requests.types";
import { BadRequestException } from "@nestjs/common";
@Injectable()
export class SimUsageService {
constructor(
private readonly freebitService: FreebitService,
private readonly simValidation: SimValidationService,
private readonly usageStore: SimUsageStoreService,
@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 = getErrorMessage(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 = getErrorMessage(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);
// Validate date format
if (!/^\d{8}$/.test(request.fromDate) || !/^\d{8}$/.test(request.toDate)) {
throw new BadRequestException("Dates must be in YYYYMMDD format");
}
const history = await this.freebitService.getSimTopUpHistory(
account,
request.fromDate,
request.toDate
);
this.logger.log(`Retrieved SIM top-up history for subscription ${subscriptionId}`, {
userId,
subscriptionId,
account,
totalAdditions: history.totalAdditions,
});
return history;
} catch (error) {
const sanitizedError = getErrorMessage(error);
this.logger.error(`Failed to get SIM top-up history for subscription ${subscriptionId}`, {
error: sanitizedError,
userId,
subscriptionId,
});
throw error;
}
}
}