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"; export class CheckObjeniousRequests { constructor( private readonly operationsRepository: IOperationsRepository, private readonly orderRepository: OrderRepository, private readonly httpClient: HttpClient ) { } /** * TODO: meter a una funcion a parte task con los 3 pasos */ public async getPendingOperations() { 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) { //Nada pendiente return; } const erroneas = pendingOperations.data .filter((e) => e.request_id == undefined) const operacionesValidas = pendingOperations.data .filter((e) => e.request_id != undefined) const solicitarMassId = operacionesValidas .filter((e) => e.mass_action_id == undefined) const consultarEstado = pendingOperations.data .filter(e => e.mass_action_id != undefined) 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) } private async getMassActionsStatus(requestList: ObjeniousOperation[]) { if (requestList.length == 0) return; 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(PATH + originalAction.mass_action_id, { params: { } }) 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) if (uorStatus != "finished") { console.error("!!! Notificando estado no finished") } const targetIccids = originalAction.iccids const lineData = await this.getLineData(targetIccids) console.log("[i] lineData", lineData.content[0]) const msisdn = lineData.content[0].identifier.msisdn 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([ ["en cours", "running"], ["terminé", "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) for (const request of operationsList) { if (request.id == undefined) continue; const req = this.httpClient.client.get(PATH + request.request_id, { }) let res; // 1. Comprobacion de la request. try { res = await req } catch (e) { console.error("Error comprobando el estado de ", request, e) //todo actualizar el estado para incluir el error continue; } // 2. Modificacion del massId si ha habido un cambio const massActionId = res.data.massActionIds[0] 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("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 }) { const req = axios.post(env.NOTIFICATION_URL, { ...operation, iccids: [operation.iccids] }, { headers: { "x-apikey-sim-activation": env.SIM_ACTIVATION_API_KEY } }) await req } }