Orders en todas las etapas

This commit is contained in:
2026-02-27 11:16:45 +01:00
parent 8ca3d095e6
commit 04a6e50b7a
10 changed files with 79 additions and 92 deletions

View File

@@ -0,0 +1,7 @@
/**
* En la tabla de orders de objenious no hay forma de saber a a que mensaje está Solicitando
* cada operación.
*/
ALTER TABLE objenious_operation
ADD COLUMN correlation_id TEXT;

View File

@@ -161,6 +161,7 @@ export class SimUseCases {
if (resp.status == 200) {
console.log("Sim preactivada con exito", resp.data)
const operation: ObjeniousOperation = {
correlation_id: preActivateData.correlation_id,
operation: "preActivate",
iccids: String(preActivateData.identifier.identifiers),
status: "noMassID",
@@ -220,91 +221,26 @@ export class SimUseCases {
}
}
// Metodo nuevo
public suspend(suspendData: ActionData): () => Promise<Result<string, boolean>> {
const OPERATION_URL = "/actions/suspendLine"
return this.generateUseCase({
correlation_id: suspendData.correlation_id,
operationPayload: suspendData,
url: OPERATION_URL,
iccid: suspendData.identifier.identifiers,
iccid: suspendData.identifier.identifiers[0], //
operation: "suspend"
})
return async () => {
const req = this.httpClient.client.post(OPERATION_URL, {
...suspendData
})
try {
const response = await req
if (response.status == 200) {
console.log("[o] Sim pausada/suspendida con exito", response.data)
const operation: ObjeniousOperation = {
operation: "susupend",
iccids: String(suspendData.identifier.identifiers),
status: "noMassID",
request_id: response.data.requestId
}
this.logOperation(operation).then().catch(e => console.error(e))
return <Result<string, boolean>>{
error: undefined,
data: true
}
} else {
// muy mejorable el control de errores
return {
error: String(response.status),
data: undefined
}
}
} catch (error) {
console.error("[Pausa Use case] Error pausa")
return {
error: "Error general pausando/suspendiendo la sim" + suspendData.identifier,
data: undefined
}
}
}
}
public terminate(terminationData: ActionData): () => Promise<Result<string, boolean>> {
const OPERATION_URL = "/actions/terminateLine"
return async () => {
const req = this.httpClient.client.post(OPERATION_URL, {
...terminationData
})
try {
const response = await req
if (response.status == 200) {
console.log("[o] Sim solicitud de cancelacion con exito", response.data)
const operation: ObjeniousOperation = {
operation: "terminate",
iccids: String(terminationData.identifier.identifiers),
status: "noMassID",
request_id: response.data.requestId
}
return <Result<string, boolean>>{
error: undefined,
data: true
}
} else {
return {
error: String(response.status),
data: undefined
}
}
} catch (error) {
console.error("[x ] Error en la solicitud de terminacion", error)
return <Result<string, boolean>>{
error: "Error cancelando/terminate la sim" + terminationData.identifier,
data: undefined
}
}
}
return this.generateUseCase({
correlation_id: terminationData.correlation_id,
operationPayload: terminationData,
url: OPERATION_URL,
iccid: terminationData.identifier.identifiers[0], //
operation: "suspend"
})
}

View File

@@ -4,7 +4,7 @@ export type ActionData = {
dueDate: string, // isodate
filter?: {} // no se si hace falta
identifier: {
identifiers: string
identifiers: string[]
identifierType: "IMSI" | "MSISDN" | "REFERENCE" | "ICCID" | "IMEI"
}
}

View File

@@ -7,6 +7,7 @@ import { PgClient } from "sim-shared/infrastructure/PgClient.js"
import { SimUseCases } from "./aplication/Sim.usecases.js"
import { SimController } from "./aplication/Sim.controller.js"
import { SimRouter } from "./aplication/Sim.router.js"
import { OrderRepository } from "sim-shared/infrastructure/OrderRepository.js"
async function startWorker() {
const rmqClient = await startRMQClient()
@@ -18,12 +19,14 @@ async function startWorker() {
await pgClient.checkDatabaseConnection()
const operationRepository = new ObjeniousOperationsRepository(pgClient)
const orderRepository = new OrderRepository(pgClient)
const simActivationController = new SimController(
rmqClient,
new SimUseCases({
httpClient: httpClient,
operationRepository: operationRepository
operationRepository: operationRepository,
orderRepository: orderRepository
})
)
const simRouter = new SimRouter(simActivationController, rmqClient)

View File

@@ -7,5 +7,6 @@ OBJ_KID=xNfbMiyL1ORXGP8lElhcv8nVaG3EJKye4Lc1YoN3I1E
OBJ_BASE_URL=https://api-getway.objenious.com/ws
# OBJ_BASE_URL=https://api-getway.objenious.com/ws/test
NOTIFICATION_URL="https://sf-sim-activation.savefamilygps.net/send-activation-mail"
# NOTIFICATION_URL="https://sf-sim-activation.savefamilygps.net/send-activation-mail"
NOTIFICATION_URL="localhost"
SIM_ACTIVATION_API_KEY=9e48c4ac-1ab0-4397-b3f3-6c239200dfe6

View File

@@ -4,6 +4,7 @@ import { PgClient } from "sim-shared/infrastructure/PgClient.js"
import { httpInstance } from "./config/httpClient.config.js"
import { CheckObjeniousRequests } from "./tasks/check_objenious_request.js"
import { ObjeniousOperationsRepository } from "sim-shared/infrastructure/ObjeniousOperationRepository.js"
import { OrderRepository } from "sim-shared/infrastructure/OrderRepository.js"
async function startCron() {
const commonSettings = {
@@ -16,13 +17,16 @@ async function startCron() {
await pgClient.checkDatabaseConnection()
await pgClient.checkDatabaseConnection()
const operationRepository = new ObjeniousOperationsRepository(pgClient)
const orderRepository = new OrderRepository(pgClient)
const objTask = new CheckObjeniousRequests(
operationRepository,
httpClient
orderRepository,
httpClient,
)
await objTask.getPendingOperations()
const interval = setInterval(async () => {
console.log("Updating...")
await objTask.getPendingOperations()

View File

@@ -16,43 +16,47 @@ export class CheckObjeniousRequests {
* TODO: meter a una funcion a parte task con los 3 pasos
*/
public async getPendingOperations() {
// 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) {
//Nada pendiente
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)
// 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)
}
/**
* Para una lista de operaciones **con mass_action_id** se comprueba si han tenido alguna actualizacion
* Devuelve el numero de operaciones comprobadas.
*/
private async getMassActionsStatus(requestList: ObjeniousOperation[]) {
if (requestList.length == 0) return;
if (requestList.length == 0) return 0;
const operationsList = structuredClone(requestList)
const PATH = "/actions/massActions/"
@@ -123,6 +127,14 @@ export class CheckObjeniousRequests {
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)
})
}
this.notifyFinalization({
...originalAction,
msisdn

View File

@@ -72,3 +72,14 @@ export type UpdateOrderDTO =
new_status: OrderStatus,
reason?: string
}
export type FinishOrderDTO =
(
{ id: number, correlation_id?: never } |
{ id?: never, correlation_id: string }
)
&
{
reason?: string
}

View File

@@ -10,6 +10,8 @@ export interface IOperationsRepository {
export type ObjeniousOperation = {
id?: number;
/** Uuid del mensaje asociado a la operacion */
correlation_id?: string;
operation: string;
retry_count?: number;
max_retry?: number;

View File

@@ -2,7 +2,7 @@
* TODO: Usar
*/
import { PoolClient, QueryResult, QueryResultRow } from "pg";
import { CreateOrderDTO, OrderTracking, UpdateOrderDTO } from "../domain/Order.js";
import { CreateOrderDTO, FinishOrderDTO, OrderTracking, UpdateOrderDTO } from "../domain/Order.js";
import { Result } from "../domain/Result.js";
import { PgClient } from "./PgClient.js";
import assert from "node:assert";
@@ -177,7 +177,7 @@ export class OrderRepository {
const client = await this.pgClient.connect();
await client.query('BEGIN');
const idType = ('id' in args) ? "correlation_id" : "id"
const idType = ('id' in args) ? "id" : "correlation_id"
const idValue = (args.id != undefined) ? args.id : args.correlation_id
// 1. Se consulta la order de base
@@ -262,18 +262,29 @@ export class OrderRepository {
}
public async finishOrder(args: { id: number, reason?: string }) {
public async finishOrder(args: FinishOrderDTO) {
const client = await this.pgClient.connect();
assert((args.id != undefined) != (args.correlation_id != undefined))
await client.query('BEGIN');
const idType = ('id' in args) ? "id" : "correlation_id"
const idValue = (args.id != undefined) ? args.id : args.correlation_id
// 1. Se consulta la order de base
const qCurrentOrder = `
SELECT * FROM order_tracking
WHERE id = $1
WHERE ${idType} = $1
`
const vCurrentOrder = [args.id]
const vCurrentOrder = [idValue]
const currentOrderResult = await this.getFirst(client.query<OrderTracking<any>>(qCurrentOrder, vCurrentOrder))
const orderId = currentOrderResult.data?.id
if (orderId == undefined) {
return {
error: "El order a actualizar no existe " + idType + ": " + idValue
}
}
if (currentOrderResult.error != undefined) {
await client.query("ROLLBACK")
@@ -293,7 +304,7 @@ export class OrderRepository {
WHERE id = $1
RETURNING id, status, update_date;
`
const vOrderTracking = [args.id]
const vOrderTracking = [orderId]
const updatedOrderResult = await this.getFirst(
client.query<{ id: number, status: string, update_date: string }>(uOrderTracking, vOrderTracking)
)