2025-09-25 15:11:28 +09:00
|
|
|
import { Injectable, Inject } from "@nestjs/common";
|
|
|
|
|
import { Logger } from "nestjs-pino";
|
2025-09-25 16:38:21 +09:00
|
|
|
import { FreebitOrchestratorService } from "@bff/integrations/freebit/services/freebit-orchestrator.service";
|
2025-09-25 15:11:28 +09:00
|
|
|
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(
|
2025-09-25 16:38:21 +09:00
|
|
|
private readonly freebitService: FreebitOrchestratorService,
|
2025-09-25 15:11:28 +09:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|