/** * Documentación de referencia: * https://pelion-help.iot-x.com/nos/en-US/Content/API/APIReference/API%20Reference.htm?tocpath=_____7 * * En nos el correlation_id ya va a ser obligatorio en todos los mensajes * * TODO: * - Control de errores más preciso * */ import { AlaiAPI } from "#domain/AlaiAPI.js"; import { AlaiRepository } from "#infrastructure/AlaiRepository.js"; import { ErrorOrderDTO, FinishOrderDTO, UpdateOrderDTO } from "sim-shared/domain/Order.js"; import { Result } from "sim-shared/domain/Result.js"; import { HttpClient } from "sim-shared/infrastructure/HTTPClient.js"; import { OrderRepository } from "sim-shared/infrastructure/OrderRepository.js"; export class SimAlaiUsecases { constructor( private httpClient: HttpClient, private alaiRepository: AlaiRepository, private orderRepository: OrderRepository ) { } private async setRunning(correlation_id: string) { const updateData: UpdateOrderDTO = { new_status: "running", correlation_id: correlation_id } const order = await this.orderRepository.updateOrder(updateData) return order } private async setFinished(correlation_id: string) { // En NOS el updateOrder se hace con el correlation_id que viene en la cabecera del // mensaje consumido const updateData: FinishOrderDTO = { correlation_id: correlation_id } const order = await this.orderRepository.finishOrder(updateData) return order } private async setFailed(correlation_id: string, reason: string, stackTrace?: string) { // En NOS el updateOrder se hace con el correlation_id que viene en la cabecera del // mensaje consumido const updateData: ErrorOrderDTO = { status: "failed", correlation_id: correlation_id, reason: reason, error: reason, stackTrace: stackTrace } console.log("SET FAILED DATA:", updateData) const order = await this.orderRepository.errorOrder(updateData) console.log("SET FAILED RES:", order) return order } /** * Gestiona el ciclo de vida de una petición. No aplica * a peticiones de lectura (no pasan por la cola y no generan un order) */ public usecaseTemplate( func: (_: T) => Promise>, args: T, correlation_id?: string | undefined ) { return async (): Promise> => { // Operacion pending -> running if (correlation_id != undefined) this.setRunning(correlation_id) .then() .catch(e => console.error("Error actualizando el order", e)) else console.warn("[!] Se ha lanzado una caso de uso sin correlation_id") try { const res = await func(args) if (res.error != undefined) { console.log("Error peticion: ", res, correlation_id) if (correlation_id != undefined) this.setFailed(correlation_id, res.error.msg, res.error.stackTrace) .then(e => console.log("failed", e)) .catch(e => console.error(e)) return res; } else { if (correlation_id != undefined) this.setFinished(correlation_id).then() return res; } } catch (e) { if (correlation_id != undefined) this.setFailed(correlation_id, "Error general de operacion de SIM (NOS) ", String(e)).then() return { error: { msg: "Error general de operacion de SIM (NOS) " + String(e) } } } } } public activate(args: { iccid: string, correlation_id: string | undefined, }) { return this.usecaseTemplate(async (iccid /*iccid*/) => { const sim = await this.alaiRepository.getSimByICCID(iccid) if (sim.error != undefined) { return sim } if (sim.data == undefined) { return { error: { msg: `La sim ${iccid} no se ha encontrado` } } } const subscriptionId = sim.data.subscription!.id if (subscriptionId == undefined) { return { error: { msg: `La sim ${iccid} no tiene un id de subscripción` } } } const activationRes = await this.alaiRepository.activateSubscription(subscriptionId) return activationRes }, args.iccid, args.correlation_id) } public preactivate(args: { iccid: string, correlation_id: string | undefined, externalId: string | undefined // Por compatibilidad }) { const inputargs = { iccid: args.iccid, externalId: args.externalId } return this.usecaseTemplate(async (args) => { const order = await this.alaiRepository.createOrder() if (order.error != undefined) { return order } const orderId = order.data.id const reserve = await this.alaiRepository.createReserve(orderId, args.iccid) if (reserve.error != undefined) { return reserve } const applyOrder = await this.alaiRepository.applyOrder(orderId) if (applyOrder.error != undefined) { // TODO: gestion del error // reusar el orderId return applyOrder } const preactivatedSim = await this.alaiRepository.getSimByICCID(args.iccid) if (preactivatedSim.error != undefined) { return preactivatedSim } // TODO: Controlar sim no encotrada (No deberia pasar) const subscriptionId = preactivatedSim.data!.subscription!.id if (args.externalId) { const externalIdAdded = await this.alaiRepository.changeExternalId(subscriptionId, args.externalId) if (externalIdAdded.error != undefined) { return externalIdAdded } } // En connections acaba buscando el numero. const subscription = await this.alaiRepository.getSubscriptionById(subscriptionId) return subscription }, inputargs, args.correlation_id) } public suspend(args: { iccid: string, correlation_id: string | undefined }) { return this.usecaseTemplate(async (args) => { const subscription = await this.alaiRepository.getSimByICCID(args.iccid) if (subscription.error != undefined) { return subscription } // TODO: Controlar que no se encuentre la subscription const subscriptionid = subscription.data?.subscription?.id const suspension = this.alaiRepository.pauseSubscription(subscriptionid!) return suspension }, args, args.correlation_id) } public reactivate(args: { iccid: string, correlation_id: string | undefined }) { return this.usecaseTemplate(async (args) => { const subscription = await this.alaiRepository.getSimByICCID(args.iccid) if (subscription.error != undefined) { return subscription } const subscriptionid = subscription.data?.subscription?.id // TODO: Controlar que no se encuentre la subscription const suspension = this.alaiRepository.unPauseSubscription(subscriptionid!) return suspension }, args, args.correlation_id) } public terminate(args: { iccid: string, correlation_id: string | undefined }) { return this.usecaseTemplate(async (args) => { const subscription = await this.alaiRepository.getSimByICCID(args.iccid) if (subscription.error != undefined) { return subscription } // TODO: Controlar que no se encuentre la subscription const suspension = this.alaiRepository.terminateSubscription(subscription.data!.id) return suspension }, args, args.correlation_id) } public async selectOne(iccid: string) { const sim = await this.alaiRepository.getSimByICCID(iccid) return sim } /** * Para sacar los datos de una liena hay que sacar sim -> subscripcion -> imei * son 3 llamadas distintas. */ public async selectCompleteSim(iccid: string): Promise> { const sim = await this.alaiRepository.getSimByICCID(iccid) if (sim.error != undefined) { return sim } if (sim.data == undefined) { return { error: { msg: `La sim ${iccid} no se ha encontrado` } } } // En este caso la tarjeta no se ha preactivado, por lo que no tiene subscripcion if (sim.data.subscription == undefined) { return { data: { sim: sim.data, subscription: undefined, imei: undefined } } } const subscriptionId = sim.data.subscription.id const subscription = await this.alaiRepository.getSubscriptionById(subscriptionId) if (subscription.error != undefined) { return subscription } const imei = await this.alaiRepository.getImeiFromSubscription(subscriptionId) if (imei.error != undefined) { return imei } return { data: { sim: sim.data!, subscription: subscription.data!, imei: imei.data! } } } }