- Rename integration orchestrators to facades: - WhmcsConnectionOrchestratorService → WhmcsConnectionFacade - FreebitOperationsService → FreebitFacade - SalesforceService → SalesforceFacade - Rename module orchestrator: - SimOrchestratorService → SimOrchestrator - Rename aggregators for clarity: - MeStatusService → MeStatusAggregator - UserProfileService → UserProfileAggregator - Move integration facades to dedicated facades/ folders: - whmcs/facades/whmcs.facade.ts - salesforce/facades/salesforce.facade.ts - freebit/facades/freebit.facade.ts This establishes clearer architectural boundaries between: - Facades: unified entry points for integration subsystems - Orchestrators: coordinate workflows across multiple services - Aggregators: read-only data composition from multiple sources Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
107 lines
3.4 KiB
TypeScript
107 lines
3.4 KiB
TypeScript
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<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;
|
|
}
|
|
}
|
|
}
|