333 lines
12 KiB
TypeScript
333 lines
12 KiB
TypeScript
import { env } from "../config/env/index.js";
|
|
import { OrderRepository } from "sim-shared/infrastructure/OrderRepository.js";
|
|
import axios from "axios";
|
|
import { IOperationsRepository, Objenious, ObjeniousOperation, ObjeniousOperationChange, StatusEnum } from "sim-shared/domain/operationsRepository.port.js";
|
|
import { HttpClient } from "sim-shared/infrastructure/HTTPClient.js";
|
|
import { ObjeniousOperationsRepository } from "sim-shared/infrastructure/ObjeniousOperationRepository.js";
|
|
|
|
export class CheckObjeniousRequests {
|
|
constructor(
|
|
private readonly operationsRepository: ObjeniousOperationsRepository,
|
|
private readonly orderRepository: OrderRepository,
|
|
private readonly httpClient: HttpClient
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* TODO: meter a una funcion a parte task con los 3 pasos
|
|
*/
|
|
public async getPendingOperations() {
|
|
console.log("[i] Inicio revision de peticiones")
|
|
// 1. Se obtienen todas las operaciones pendientes de la BDD
|
|
const pendingOperations = await this.operationsRepository.getPendingOperations()
|
|
|
|
if (pendingOperations.error != undefined) {
|
|
throw new Error("Error obteniendo las tareas pendientes " + pendingOperations.error)
|
|
}
|
|
|
|
if (pendingOperations.data == undefined || pendingOperations.data.length == 0) {
|
|
console.log("[cron] No hay operaciones pendientes de Objenious")
|
|
return;
|
|
}
|
|
|
|
// 2. Clasificación de las tareas pendientes
|
|
// Erroneas => no se les ha dado un request_id, no se pueden comprobar
|
|
const erroneas = pendingOperations.data
|
|
.filter((e) => e.request_id == undefined)
|
|
// Todas las validas
|
|
const operacionesValidas = pendingOperations.data
|
|
.filter((e) => e.request_id != undefined)
|
|
.filter((e) => e.operation != "terminate" && e.operation != "suspend")
|
|
|
|
// Filtrar suspension / terminacion
|
|
|
|
|
|
// Validas sin MassId
|
|
const solicitarMassId = operacionesValidas
|
|
.filter((e) => e.mass_action_id == undefined)
|
|
// Validas con MassId
|
|
const consultarEstado = pendingOperations.data
|
|
.filter(e => e.mass_action_id != undefined)
|
|
// TODO: Validas sin/con massID que lleven mucho tiempo sin actualizarse
|
|
|
|
console.log("[cron] Solicitando mass id para", solicitarMassId.map(e => e.id))
|
|
const newMassActions = await this.getMassIdFromRequest(solicitarMassId)
|
|
const merged = [...newMassActions || [], ...consultarEstado]
|
|
|
|
console.log("[cron] Solicitando status para", merged.map(e => e.id))
|
|
const result = await this.getMassActionsStatus(merged)
|
|
|
|
console.log("[o] Revisión de eventos completa")
|
|
}
|
|
|
|
/**
|
|
* Para una lista de operaciones **con mass_action_id** se comprueba si han tenido alguna actualizacion
|
|
* Devuelve el numero de operaciones comprobadas.
|
|
* TODO: Esto va en un repositorio
|
|
*/
|
|
private async getMassActionsStatus(requestList: ObjeniousOperation[]) {
|
|
if (requestList.length == 0) return 0;
|
|
|
|
const operationsList = structuredClone(requestList)
|
|
const PATH = "/actions/massActions/"
|
|
const updated = []
|
|
|
|
const mass_actions = operationsList
|
|
.filter(e => e.mass_action_id != undefined)
|
|
|
|
// 1. Una peticion por cada accion a comprobar
|
|
// Las peticiones por iccid u otro filtro tardan ~50s
|
|
for (const originalAction of mass_actions) {
|
|
|
|
const req = this.httpClient.client.get<Objenious.ResponseGetMassAction>(PATH + originalAction.mass_action_id, {
|
|
params: <Objenious.ParametersGetMassAction>{
|
|
}
|
|
})
|
|
|
|
let res;
|
|
// 1. Comprobacion de la request.
|
|
try {
|
|
res = await req
|
|
} catch (e) {
|
|
console.error("[cron] Error comprobando el estado de ", originalAction)
|
|
console.error("[cron] Error: ", e)
|
|
return;
|
|
}
|
|
|
|
const { data } = res
|
|
|
|
console.log("[cron] Estado de : ", originalAction.mass_action_id, originalAction.iccids)
|
|
console.log(res.status, data)
|
|
|
|
if (res.status != 200 || data == undefined) {
|
|
console.error("[cron] Error buscando los massActions")
|
|
continue;
|
|
}
|
|
|
|
// 2. Se comprueba si ha habido un cambio de estado
|
|
const { id, status, info } = data
|
|
|
|
const hasStatusChanged = status != originalAction.objenious_status
|
|
if (hasStatusChanged) {
|
|
console.log("[cron] Actualizando", originalAction.id, originalAction.iccids, status)
|
|
/** Status convertido al que se usa en la aplicacion */
|
|
const uorStatus = this.mapStatus(status)
|
|
const updateData: ObjeniousOperationChange = {
|
|
operation_id: originalAction.id!,
|
|
new_objenious_status: status,
|
|
previous_objenious_status: originalAction.objenious_status,
|
|
new_status: uorStatus,
|
|
previous_status: originalAction.status
|
|
}
|
|
|
|
const updatedAction = structuredClone(originalAction)
|
|
|
|
updatedAction.status = uorStatus;
|
|
updatedAction.objenious_status = status;
|
|
updatedAction.last_change_date = new Date().toISOString()
|
|
updatedAction.end_date = originalAction.last_change_date
|
|
|
|
if (uorStatus == "finished") {
|
|
console.log(" ****> Status", uorStatus)
|
|
const targetIccids = originalAction.iccids
|
|
const lineData = await this.getLineData(targetIccids)
|
|
console.log("[i] lineData", lineData.content[0])
|
|
const msisdn = lineData.content[0].identifier.msisdn
|
|
|
|
if (originalAction.correlation_id != undefined) {
|
|
this.orderRepository.finishOrder({ correlation_id: originalAction.correlation_id })
|
|
.then(e => console.log("[o] Finalizada order", e))
|
|
.catch(e => {
|
|
console.error("[x] Error finalizando la order ", e)
|
|
console.error(e)
|
|
})
|
|
}
|
|
|
|
if (originalAction.operation == "activate") {
|
|
this.notifyFinalization({
|
|
...originalAction,
|
|
msisdn
|
|
})
|
|
// TODO la accion no siempre es activacion!
|
|
.then(e => {
|
|
console.log("[o] Notificada la activacion de ", originalAction.iccids)
|
|
})
|
|
.catch(e => {
|
|
console.error("[x] Error enviando la activacion de ", originalAction)
|
|
console.error(e)
|
|
})
|
|
}
|
|
}
|
|
|
|
if (info != undefined) {
|
|
updateData.info = info
|
|
}
|
|
|
|
try {
|
|
console.log("[i] Subiendo un update")
|
|
console.log(updateData)
|
|
await this.operationsRepository.updateOperation(updateData)
|
|
updated.push(originalAction)
|
|
} catch (e) {
|
|
console.error("[x] Error actualizando el estado de ", originalAction, e)
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private mapStatus(objStatus: string) {
|
|
const sanitizedStatus = objStatus.trim().toLowerCase()
|
|
// No tengo el resto porque no aparecen en la documentación
|
|
// asumo que todos los demas sn running y se deben volver a comrobar
|
|
// ! Importante las claves siempre en minuscula, los valores son cammelCase
|
|
const equivalentMap = new Map<string, StatusEnum>([
|
|
["en cours", "running"],
|
|
["terminé", "finished"],
|
|
["annulé", "finished"]
|
|
])
|
|
const res = equivalentMap.get(sanitizedStatus)
|
|
if (res == undefined) return "running"
|
|
return res
|
|
}
|
|
|
|
private async getLineData(iccids: string) {
|
|
const PATH = "/lines"
|
|
|
|
const req = this.httpClient.client.get(PATH, {
|
|
params: {
|
|
pageSize: 100, // no hace fata
|
|
"identifier.identifierType": "ICCID",
|
|
"identifier.identifiers": iccids
|
|
}
|
|
})
|
|
|
|
try {
|
|
const res = await req
|
|
return res.data
|
|
} catch (e) {
|
|
console.error("Error obteniendo datos de la sim")
|
|
throw new Error(String(e))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Refrescar los requests hasta que conseguir una Id de mass action
|
|
* Como no se puede consultar por
|
|
*
|
|
*/
|
|
private async getMassIdFromRequest(requestList: ObjeniousOperation[]) {
|
|
if (requestList.length == 0) return;
|
|
|
|
const PATH = "/actions/requests/"
|
|
const operationsList = structuredClone(requestList)
|
|
|
|
// TODO: El for es gigantesco hay que simplificar partes
|
|
for (const request of operationsList) {
|
|
if (request.id == undefined) continue;
|
|
|
|
const req = this.httpClient.client.get<Objenious.ResponseGetRequestById>(PATH + request.request_id, {
|
|
})
|
|
|
|
let res;
|
|
|
|
// 1. Comprobacion de la request.
|
|
try {
|
|
res = await req
|
|
} catch (e) {
|
|
console.error("[x] Error comprobando el estado de ", request, e)
|
|
continue;
|
|
}
|
|
|
|
// 2. Casos de error o id no generada
|
|
if (res.data.massActionIds.length == 0) {
|
|
// Si no hay es que *puede* que haya un problema o no se ha generado todavia
|
|
const reports = res.data.actionRequestReports
|
|
// Se entiende que no hay report ni id = está a la espera
|
|
if (reports.length == 0) continue;
|
|
|
|
// ! Hay minimo un report -> se considera error y se para
|
|
const updateData: ObjeniousOperationChange = {
|
|
operation_id: request.id,
|
|
new_status: "error",
|
|
error: JSON.stringify(reports[0].actionRequestReportDataDTOs)
|
|
}
|
|
|
|
const updateRes = await this.operationsRepository.updateOperation(updateData)
|
|
if (updateRes.error != undefined) {
|
|
console.error("[x] Error actualizando el estado de la operacion", updateData.error)
|
|
}
|
|
|
|
if (request.correlation_id != undefined) {
|
|
this.orderRepository.errorOrder({
|
|
correlation_id: request.correlation_id,
|
|
status: "failed",
|
|
error: "MassId no obtenida",
|
|
reason: "MassId no obtenida",
|
|
stackTrace: JSON.stringify(reports[0].actionRequestReportDataDTOs)
|
|
}).then(e => {
|
|
if (e.error != undefined) {
|
|
console.error("[x] Error actualizando el estado del Order con correlation_id: ", request.correlation_id)
|
|
console.error(e.error)
|
|
}
|
|
}).catch(e => {
|
|
console.error("[x] Error actualizando el estado del Order con correlation_id: ", request.correlation_id)
|
|
})
|
|
}
|
|
continue;
|
|
}
|
|
|
|
const massActionId = res.data.massActionIds[0]
|
|
// 3. Modificacion del massId si ha habido un cambio
|
|
try {
|
|
if (res.status == 200 && res.data != undefined && massActionId != undefined) {
|
|
const updateData: ObjeniousOperationChange = {
|
|
operation_id: request.id,
|
|
new_status: "running",
|
|
new_mass_action_id: String(massActionId)
|
|
}
|
|
|
|
await this.operationsRepository.updateOperation(updateData)
|
|
//! Se actualiza el registro para futuras operaciones
|
|
request.mass_action_id = String(massActionId)
|
|
}
|
|
} catch (e) {
|
|
console.log("[x] Error actualizando el estado de ", request)
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// 3. Se devuelve la lista de los requests con las actualizaciones
|
|
return operationsList
|
|
}
|
|
|
|
/**
|
|
* Se devuelve la respuesta de una operacion completa de objenious
|
|
* al servicio que manda los mails
|
|
*/
|
|
private async notifyFinalization(operation: ObjeniousOperation & { msisdn: string }) {
|
|
console.log("[i] Enviando activacion a", env.NOTIFICATION_URL)
|
|
console.log("[i] Operation", operation)
|
|
const req = axios.post(env.NOTIFICATION_URL, {
|
|
...operation,
|
|
iccids: [operation.iccids]
|
|
}, {
|
|
headers: {
|
|
"x-apikey-sim-activation": env.SIM_ACTIVATION_API_KEY
|
|
}
|
|
})
|
|
try {
|
|
const res = await req
|
|
if (res.status != 200) {
|
|
console.error("[x] Error enviando el mail de confirmacion para ", operation, " status ", res.status, res.statusText)
|
|
}
|
|
} catch (e) {
|
|
console.error("[x] Error enviando el mail de confirmacion para ", operation)
|
|
console.error(e)
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|