diff --git a/deployment/database/base/xx-volcado-objenious.sql b/deployment/database/base/xx-volcado-objenious.sql new file mode 100644 index 0000000..8637c89 --- /dev/null +++ b/deployment/database/base/xx-volcado-objenious.sql @@ -0,0 +1,20 @@ +CREATE table if not exists objenious_lines ( + id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + simId BIGINT UNIQUE, + status TEXT, + iccid TEXT NOT NULL, + msisdn TEXT, + imei TEXT, + imeiChangeDate TIMESTAMPTZ, + offerCode TEXT, + status TEXT, + preactivationDate TIMESTAMPTZ, -- No viene con hora + activationDate TIMESTAMPTZ, + commercialStatus TEXT, + commercialStatusDate TIMESTAMPTZ, + billingStatus TEXT, + billingStatusChangeDate TIMESTAMPTZ, + billingActivationDate TIMESTAMPTZ, + createDate TIMESTAMPTZ, + raw JSONB +) diff --git a/docs/sim-objenious/Appel lines.bru b/docs/sim-objenious/Appel lines.bru index e10670f..afc428d 100644 --- a/docs/sim-objenious/Appel lines.bru +++ b/docs/sim-objenious/Appel lines.bru @@ -5,16 +5,16 @@ meta { } get { - url: https://api-getway.objenious.com/ws/lines?pageSize=10&identifier.identifierType=ICCID&identifier.identifiers=8933201125065160455 + url: https://api-getway.objenious.com/ws/lines?pageSize=1000&simStatus=ACTIVATED body: formUrlEncoded auth: bearer } params:query { - pageSize: 10 - identifier.identifierType: ICCID - identifier.identifiers: 8933201125065160455 - ~simStatus: ACTIVATED + pageSize: 1000 + simStatus: ACTIVATED + ~identifier.identifierType: ICCID + ~identifier.identifiers: 8933201125065160455 } auth:bearer { diff --git a/packages/sim-objenious-cron/config/intranetPostgresConfig.ts b/packages/sim-objenious-cron/config/intranetPostgresConfig.ts new file mode 100644 index 0000000..a9d94ee --- /dev/null +++ b/packages/sim-objenious-cron/config/intranetPostgresConfig.ts @@ -0,0 +1,20 @@ +/** + * Cliente de postgres para la intranet. Se usa solo porque hace falta para el + * volcado de datos, si se usa en mas partes algo estás haciendo mal. + */ + +import { Pool } from 'pg'; +import { PgClient } from 'sim-shared/infrastructure/PgClient.js' +import { env } from './env/index.js'; + +export const pgPoolIntranet = new Pool({ + user: env.POSTGRES_USER, + host: env.POSTGRES_HOST, + database: "intranet", + password: env.POSTGRES_PASSWORD, + port: Number(env.POSTGRES_PORT) || 5432, +}); + +export const postgrClientIntranet = new PgClient({ + pool: pgPoolIntranet +}) diff --git a/packages/sim-objenious-cron/infranstructure/ObjeniousLinesRepository.ts b/packages/sim-objenious-cron/infranstructure/ObjeniousLinesRepository.ts new file mode 100644 index 0000000..3bafa70 --- /dev/null +++ b/packages/sim-objenious-cron/infranstructure/ObjeniousLinesRepository.ts @@ -0,0 +1,73 @@ +import { PoolClient } from "pg"; +import { CreateObjeniousLineDTO } from "sim-shared/domain/objeniousLine.js"; +import { PgClient } from "sim-shared/infrastructure/PgClient.js"; + +export class ObjeniousLinesRepository { + constructor( + private pgClient: PgClient + ) { + } + + public async insertOrUpdate(data: CreateObjeniousLineDTO) { + const query = ` + INSERT INTO objenious_lines ( + simId, iccid, msisdn, imei, imeiChangeDate, + offerCode, status, preactivationDate, activationDate, + commercialStatus, commercialStatusDate, billingStatus, + billingStatusChangeDate, billingActivationDate, createDate, raw + ) VALUES ( + $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16 + ) + ON CONFLICT (simId) + DO UPDATE SET + iccid = EXCLUDED.iccid, + msisdn = EXCLUDED.msisdn, + imei = EXCLUDED.imei, + imeiChangeDate = EXCLUDED.imeiChangeDate, + offerCode = EXCLUDED.offerCode, + status = EXCLUDED.status, + preactivationDate = EXCLUDED.preactivationDate, + activationDate = EXCLUDED.activationDate, + commercialStatus = EXCLUDED.commercialStatus, + commercialStatusDate = EXCLUDED.commercialStatusDate, + billingStatus = EXCLUDED.billingStatus, + billingStatusChangeDate = EXCLUDED.billingStatusChangeDate, + billingActivationDate = EXCLUDED.billingActivationDate, + raw = EXCLUDED.raw + RETURNING id; + `; + + const values = [ + data.simId, + data.iccid, + data.msisdn, + data.imei, + data.imeiChangeDate, + data.offerCode, + data.status, + data.preactivationDate, + data.activationDate, + data.commercialStatus, + data.commercialStatusDate, + data.billingStatus, + data.billingStatusChangeDate, + data.billingActivationDate, + data.createDate || new Date(), // Default a ahora si no viene + JSON.stringify(data.raw) // El driver de pg requiere string o el objeto directo para JSONB + ]; + + let client: PoolClient | undefined = undefined; + try { + client = await this.pgClient.connect(); + const res = await client.query(query, values); + return res.rows[0].id; + } catch (err) { + console.error('Error en la inserción:', err); + throw err; + } finally { + if (client != undefined) { + client.release() + } + } + } +} diff --git a/packages/sim-objenious-cron/tasks/check_objenious_request.ts b/packages/sim-objenious-cron/tasks/check_objenious_request.ts index 49c1f2a..5b85fbe 100644 --- a/packages/sim-objenious-cron/tasks/check_objenious_request.ts +++ b/packages/sim-objenious-cron/tasks/check_objenious_request.ts @@ -54,6 +54,7 @@ export class CheckObjeniousRequests { /** * 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; diff --git a/packages/sim-objenious-cron/tasks/volcado_lineas.ts b/packages/sim-objenious-cron/tasks/volcado_lineas.ts new file mode 100644 index 0000000..1155702 --- /dev/null +++ b/packages/sim-objenious-cron/tasks/volcado_lineas.ts @@ -0,0 +1,68 @@ +import { ObjeniousLine, ObjeniousLineResponse } from "sim-shared/domain/objeniousLine.js"; +import { tryCatch, Result } from "sim-shared/domain/Result.js"; +import { HttpClient } from "sim-shared/infrastructure/HTTPClient.js"; + +const MAX_PAGE_SIZE = 1000 + +export class VolcadoLineas { + constructor( + private readonly httpClient: HttpClient + ) { + } + + /** + * Mover al repo + */ + private async getLinesByStatus(args?: { + pageSize?: number, + pageNumber?: number, + status?: string + }): Promise> { + + const path = "/lines" + const pageSize = args?.pageSize ?? MAX_PAGE_SIZE; + const status = args?.status ?? null; + let currentPage = args?.pageNumber ?? 0; + let totalPages = 1; + let allLines: ObjeniousLine[] = [] + + const loadNextLine = async () => { + const nextPage = await tryCatch(this.httpClient.client.get(path, { + params: { + simStatus: status, + pageSize: pageSize, + pageNumber: currentPage + } + })) + if (nextPage.error != undefined) { + return { + error: nextPage.error.msg.message + } + } + + // Se aumenta para la siguiente ejecucion + currentPage = nextPage.data.pageNumber + 1 + allLines = [...allLines, ...nextPage.data.content] + totalPages = nextPage.data.totalPages + } + + // El inicio se ejecuta siempre + await loadNextLine() + + // Copia para evitar bucles infinitos por error de la api + const maxPages = totalPages + + for (let i = currentPage; i < maxPages; i++) { + await loadNextLine() + } + + return { + data: allLines + } + } + + public async loadLines() { + + } + +} diff --git a/packages/sim-shared/domain/objeniousLine.ts b/packages/sim-shared/domain/objeniousLine.ts new file mode 100644 index 0000000..aa763fb --- /dev/null +++ b/packages/sim-shared/domain/objeniousLine.ts @@ -0,0 +1,115 @@ +export type ObjeniousLineResponse = { + content: ObjeniousLine[], + offset: number, + pageNumber: number, + pageSize: number, + paged: boolean, + totalPages: number, + totalElements: number +} + +export type ObjeniousLine = { + identifier: { + simId: number, + iccid: string, + imsi: string, + msisdn: string, + amsisdn?: string, + imei: string + }, + simCardType: { + code: string, + description: string + }, + device: { + imei: string, + imeiChangeDate: string, //Fecha iso + deviceReference?: string | null, + manufacturer?: string | null, + }, + customerAccount: { + code: string, + label: string, + address: { + address1: string, + address2: string, + address3: string, + zipCode: string, + city: string, + country: string, + state?: string | null + } + }, + offer: { + code: string, + description: string, + }, + party: { + name: string, + code: string, + contractReference: string, + partyType: string, + }, + lineCustomFields: { + custom1: { + label: string | null, + value: string | null + }, + custom2: { + label: string | null, + value: string | null + }, + custom3: { + label: string | null, + value: string | null + }, + custom4: { + label: string | null, + value: string | null + }, + custom5: { + label: string | null, + value: string | null + }, + custom6: { + label: string | null, + value: string | null + } + }, + status: { + status: string, + preactivationDate: string | null, //"2026-03-17", + activationDate: string | null, //"2026-03-17T11:04:11.408+00:00", + commercialStatus: string, //"test", + commercialStatusDate: string, //"2026-03-17T11:41:01.493+00:00", + networkStatus: string, // "ACTIVATED", + billingStatus: string, //"TEST", + billingStatusChangeDate: string | null, // "2026-03-17T11:01:00.276+00:00", + billingActivationDate: string | null //, + createdDate: string | null,//"2026-01-30T01:50:02.060+00:00" + }, + services: string | null +}; + +export type ObjeniousLineDb = { + id: number; + simId?: string; + iccid: string; + msisdn?: string; + imei?: string; + imeiChangeDate?: Date; + offerCode?: string; + status?: string; + preactivationDate?: Date; + activationDate?: Date; + commercialStatus?: string; + commercialStatusDate?: Date; + billingStatus?: string; + billingStatusChangeDate?: Date; + billingActivationDate?: Date; + createDate?: Date; + raw: ObjeniousLine; +} + +// DTO para inserción (omite el ID autogenerado) +export type CreateObjeniousLineDTO = Omit;