Files
sf-sim/packages/sim-consumidor-alai/aplication/SimAlai.usecases.ts

263 lines
8.0 KiB
TypeScript

/**
* 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 { ConsumeMessage } from "amqplib";
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";
import { isOmittedExpression } from "typescript";
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, detail?: 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: detail
}
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<T, R>(
func: (_: T) => Promise<Result<string, R>>,
args: T,
correlation_id?: string | undefined
) {
return async (): Promise<Result<string, R>> => {
// 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)
.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: "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 order = await this.alaiRepository.createOrder()
if (order.error != undefined) {
// Falla el crearse un order (problema de servidor, token, etc)
console.error(order.error)
return order
}
const reserved = await this.alaiRepository.createReserve(order.data.id, iccid)
return reserved
}, 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) {
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 suspension = this.alaiRepository.pauseSubscription(subscription.data!.id)
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
}
// TODO: Controlar que no se encuentre la subscription
const suspension = this.alaiRepository.unPauseSubscription(subscription.data!.id)
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<Result<string, {
sim: AlaiAPI.Sim,
subscription: AlaiAPI.Subscription,
imei: AlaiAPI.GetImeiSubscriptionDTO
}>> {
const sim = await this.alaiRepository.getSimByICCID(iccid)
if (sim.error != undefined) {
return sim
}
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!
}
}
}
}