Seguimiento de ordenes desde la ingesta

This commit is contained in:
2026-02-11 12:19:16 +01:00
parent 2c9bf9dd93
commit 46ac54f7ab
6 changed files with 52 additions and 6 deletions

View File

@@ -0,0 +1,40 @@
-- Tablas para el seguimiento de las operaciones de SIM sin importar
-- la cmpañia.
CREATE TYPE order_types AS ENUM ('activate','preactivate','cancel','pause','reactivate','unknown');
CREATE TYPE order_status AS ENUM (
'pending', -- Mensaje creado/enviado a RabbitMQ
'running', -- Consumidor ha cogido el mensaje (opcional)
'finished', -- Procesado correctamente
'failed', -- Falló, pero podría reintentarse (Pasar a delay?)
'dlx' -- Falló definitivamente y está en Dead Letter Exchange
);
CREATE TABLE IF NOT EXISTS order_tracking (
order_id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
correlation_id VARCHAR(255) NOT NULL, -- ID compartido con RabbitMQ (message_id)
exchange VARCHAR(100), -- Exchange al que se envia (de momento solo hay 1 principal sin contar delay y dlx)
routing_key VARCHAR(100), -- Routing key del mensaje
payload JSONB, -- Duda si es optimo guardar la copia, es útil en caso de fallo
-- Campos de reintentos?
status order_status NOT NULL DEFAULT 'PENDING',
retry_count INT DEFAULT 0,
error_message TEXT, -- Razón del fallo
-- error_stacktrace TEXT, -- Recomendación, no se hasta que punto es necesario
start_date TIMESTAMP NOT NULL DEFAULT now(),
update_date TIMESTAMP NOT NULL DEFAULT now(),
finished_date TIMESTAMP
)
CREATE TABALE IF NOT EXISTS order_history(
history_id SERIAL PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
order_id UUID REFERENCES queue_operations(operation_id) ON DELETE CASCADE,
previous_status order_status NOT NULL, -- Siempre hay un estado anterior, para casos excepcioneale "unknown"
new_status order_status NOT NULL,
change_reason TEXT,
change_date TIMESTAMP NOT NULL DEFAULT NOW(),
);

View File

@@ -4,11 +4,13 @@ CREATE TYPE status_enum AS ENUM ('noRequestID','noMassID','running','finished','
-- Tabla para gestionar las peticiones de cambio de objenious. -- Tabla para gestionar las peticiones de cambio de objenious.
-- Para una o mas lineas se pueden lanzar operacione que no sabemos -- Para una o mas lineas se pueden lanzar operacione que no sabemos
-- con certeza cuando van a terminar. -- con certeza cuando van a terminar.
-- Estas tablas está fuertemente ligadas al sistema que usa la plataforma
-- de objenioius y no debe unsarse para otra compañia.
CREATE TABLE if not exists objenious_operation ( CREATE TABLE if not exists objenious_operation (
id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
retry_count INT DEFAULT 0, retry_count INT DEFAULT 0, -- No implementado en codigo
max_retry INT DEFAULT 5, max_retry INT DEFAULT 5, -- No implementado en codigo
max_date_retry TIMESTAMP DEFAULT NULL, max_date_retry TIMESTAMP DEFAULT NULL, -- No implementado en codigo
iccids TEXT, iccids TEXT,
request_id TEXT, request_id TEXT,
mass_action_id TEXT, mass_action_id TEXT,

View File

@@ -84,7 +84,7 @@ export class SimController {
throw new Error("Error activando la sim, no se ha especificado la oferta") throw new Error("Error activando la sim, no se ha especificado la oferta")
} }
this.tryUseCase(msg, this.useCases.activate({ const resp = this.tryUseCase(msg, this.useCases.activate({
dueDate: this.genDueDate(DUE_DATE_SECONDS).toISOString(), dueDate: this.genDueDate(DUE_DATE_SECONDS).toISOString(),
customerAccountCode: env.OBJ_CUSTOMER_CODE, customerAccountCode: env.OBJ_CUSTOMER_CODE,
identifier: { identifier: {
@@ -96,6 +96,11 @@ export class SimController {
services: [] services: []
} }
})) }))
// TODO:
// - Crear un registro de operación
// - Si ha salido bien id de operación -> webhook?
// - Si ha salido mal notificar solo cuando se manda a dlx ??
} }
} }

View File

@@ -24,14 +24,12 @@ const iccidWithValidCompany = <Validator<{ iccid: string }>>{
validationFunc: (a: { iccid: string }) => companyFromIccid(a.iccid) != undefined, validationFunc: (a: { iccid: string }) => companyFromIccid(a.iccid) != undefined,
} }
const offerExists = <Validator<{ offer: string }>>{ const offerExists = <Validator<{ offer: string }>>{
field: "offer", field: "offer",
errorMsg: "La oferta introducida no es valida", errorMsg: "La oferta introducida no es valida",
validationFunc: (a: { offer: string }) => offers.has(a.offer), validationFunc: (a: { offer: string }) => offers.has(a.offer),
} }
export const activationValidator = new BodyValidator<{ iccid: string, offer: string }>( export const activationValidator = new BodyValidator<{ iccid: string, offer: string }>(
[ [
iccidRequired, iccidRequired,

View File

@@ -198,3 +198,4 @@ export class CheckObjeniousRequests {
return operationsList return operationsList
} }
} }