import { Injectable, Inject, BadRequestException } from "@nestjs/common"; import { Logger } from "nestjs-pino"; import { FreebitOrchestratorService } from "@bff/integrations/freebit/services/freebit-orchestrator.service"; import { SimValidationService } from "./sim-validation.service"; import { SimNotificationService } from "./sim-notification.service"; import { getErrorMessage } from "@bff/core/utils/error.util"; import type { SimCancelRequest } from "@customer-portal/domain/sim"; @Injectable() export class SimCancellationService { constructor( private readonly freebitService: FreebitOrchestratorService, private readonly simValidation: SimValidationService, private readonly simNotification: SimNotificationService, @Inject(Logger) private readonly logger: Logger ) {} /** * Cancel SIM service */ async cancelSim( userId: string, subscriptionId: number, request: SimCancelRequest = {} ): Promise { try { const { account } = await this.simValidation.validateSimSubscription(userId, subscriptionId); // Determine run date (PA02-04 requires runDate); default to 1st of next month let runDate = request.scheduledAt; if (runDate && !/^\d{8}$/.test(runDate)) { throw new BadRequestException("Scheduled date must be in YYYYMMDD format"); } if (!runDate) { const nextMonth = new Date(); nextMonth.setMonth(nextMonth.getMonth() + 1); nextMonth.setDate(1); const y = nextMonth.getFullYear(); const m = String(nextMonth.getMonth() + 1).padStart(2, "0"); const d = String(nextMonth.getDate()).padStart(2, "0"); runDate = `${y}${m}${d}`; } await this.freebitService.cancelSim(account, runDate); this.logger.log(`Successfully cancelled SIM for subscription ${subscriptionId}`, { userId, subscriptionId, account, runDate, }); await this.simNotification.notifySimAction("Cancel SIM", "SUCCESS", { userId, subscriptionId, account, runDate, }); } catch (error) { const sanitizedError = getErrorMessage(error); this.logger.error(`Failed to cancel SIM for subscription ${subscriptionId}`, { error: sanitizedError, userId, subscriptionId, }); await this.simNotification.notifySimAction("Cancel SIM", "ERROR", { userId, subscriptionId, error: sanitizedError, }); throw error; } } }