From 1583ae539e06384281e636d4c88b843d1895bd75 Mon Sep 17 00:00:00 2001 From: Alvar San Martin Date: Thu, 19 Feb 2026 17:24:47 +0100 Subject: [PATCH] Organizadas las migraciones para el despliegue --- deployment/database/base/01-ordenes-sim.sql | 63 ---- deployment/database/base/03-versions.sql | 3 +- deployment/database/esquema_final_v2.0.0.sql | 292 ++++++++++++++++++ deployment/database/init.sql | 66 +--- .../database/migrations/1.0.0_orders.sql | 67 ++++ .../{1.0.0_utc.sql => 1.0.1_utc.sql} | 13 +- .../database/migrations/1.0.2_timezones.sql | 30 ++ package.json | 3 +- ...erRepoository.ts => SimOrderRepository.ts} | 0 9 files changed, 400 insertions(+), 137 deletions(-) create mode 100644 deployment/database/esquema_final_v2.0.0.sql create mode 100644 deployment/database/migrations/1.0.0_orders.sql rename deployment/database/migrations/{1.0.0_utc.sql => 1.0.1_utc.sql} (68%) create mode 100644 deployment/database/migrations/1.0.2_timezones.sql rename packages/sim-shared/infrastructure/{SimOrderRepoository.ts => SimOrderRepository.ts} (100%) diff --git a/deployment/database/base/01-ordenes-sim.sql b/deployment/database/base/01-ordenes-sim.sql index 43d5098..e69de29 100644 --- a/deployment/database/base/01-ordenes-sim.sql +++ b/deployment/database/base/01-ordenes-sim.sql @@ -1,63 +0,0 @@ --- 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 ( - 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 - order_type order_types NOT NULL DEFAULT 'unknown', - - 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, - - start_date TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'), - update_date TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'), - finish_date TIMESTAMP -); - --- Busqueda según id de rabbit -CREATE INDEX IF NOT EXISTS idx_order_correlation - ON order_tracking(correlation_id); --- Ordenenes que todavia no han finalizado -CREATE INDEX IF NOT EXISTS pending_orders - ON order_tracking(start_date) - WHERE order_tracking.finish_date IS NULL; - -CREATE TABLE IF NOT EXISTS order_history( - id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, - order_id BIGINT NOT NULL, - 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() at time zone 'utc'), - - CONSTRAINT fk_order_id - FOREIGN KEY(order_id) - REFERENCES order_tracking(id) - ON DELETE CASCADE -); - --- fk de order -CREATE INDEX IF NOT EXISTS idx_order_id - ON order_history(order_id); - --- busquedas por fecha -CREATE INDEX IF NOT EXISTS idx_order_change_date - ON order_history(change_date); - diff --git a/deployment/database/base/03-versions.sql b/deployment/database/base/03-versions.sql index a88f2cc..978f021 100644 --- a/deployment/database/base/03-versions.sql +++ b/deployment/database/base/03-versions.sql @@ -1,5 +1,6 @@ CREATE TABLE IF NOT EXISTS db_versions ( - version TEXT PRIMARY KEY, -- version semantica x.x.x + id BIGINT BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + version TEXT, -- version semantica x.x.x notes TEXT, creation_date TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'), stable BOOLEAN DEFAULT FALSE -- Si la version ha sido testada y se puede desplegar diff --git a/deployment/database/esquema_final_v2.0.0.sql b/deployment/database/esquema_final_v2.0.0.sql new file mode 100644 index 0000000..2f441bc --- /dev/null +++ b/deployment/database/esquema_final_v2.0.0.sql @@ -0,0 +1,292 @@ +-- +-- PostgreSQL database dump +-- + +\restrict 8rNdhulAsfz5yOkZrPZ5f3riDYVBHnFPTcb2MraxKbPVyPsdTm81R2jsJppwk7u + +-- Dumped from database version 16.11 (Ubuntu 16.11-0ubuntu0.24.04.1) +-- Dumped by pg_dump version 16.11 (Ubuntu 16.11-0ubuntu0.24.04.1) + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: order_status; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.order_status AS ENUM ( + 'pending', + 'running', + 'finished', + 'failed', + 'dlx' +); + + +-- +-- Name: order_types; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.order_types AS ENUM ( + 'activate', + 'preactivate', + 'cancel', + 'pause', + 'reactivate', + 'unknown' +); + + +-- +-- Name: status_enum; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.status_enum AS ENUM ( + 'noRequestID', + 'noMassID', + 'running', + 'finished', + 'error', + 'other' +); + + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- Name: objenious_operation; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.objenious_operation ( + id bigint NOT NULL, + retry_count integer DEFAULT 0, + max_retry integer DEFAULT 5, + max_date_retry timestamp without time zone, + iccids text, + request_id text, + mass_action_id text, + operation text NOT NULL, + start_date timestamp with time zone DEFAULT now() NOT NULL, + last_change_date timestamp with time zone DEFAULT now() NOT NULL, + end_date timestamp with time zone, + error text, + status public.status_enum, + objenious_status text +); + + +-- +-- Name: objenious_operation_change; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.objenious_operation_change ( + id bigint NOT NULL, + operation_id bigint, + creation_date timestamp with time zone DEFAULT now() NOT NULL, + error text, + new_status public.status_enum, + previous_status public.status_enum, + new_objenious_status text, + previous_objenious_status text, + new_request_id text, + new_mass_action_id text +); + + +-- +-- Name: objenious_operation_change_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +ALTER TABLE public.objenious_operation_change ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( + SEQUENCE NAME public.objenious_operation_change_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: objenious_operation_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +ALTER TABLE public.objenious_operation ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( + SEQUENCE NAME public.objenious_operation_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: order_history; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.order_history ( + id bigint NOT NULL, + order_id bigint NOT NULL, + previous_status public.order_status NOT NULL, + new_status public.order_status NOT NULL, + change_reason text, + change_date timestamp with time zone DEFAULT now() NOT NULL +); + + +-- +-- Name: order_history_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +ALTER TABLE public.order_history ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( + SEQUENCE NAME public.order_history_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: order_tracking; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.order_tracking ( + id bigint NOT NULL, + correlation_id character varying(255) NOT NULL, + exchange character varying(100), + routing_key character varying(100), + order_type public.order_types DEFAULT 'unknown'::public.order_types NOT NULL, + payload jsonb, + status public.order_status DEFAULT 'pending'::public.order_status NOT NULL, + retry_count integer DEFAULT 0, + error_message text, + error_stacktrace text, + start_date timestamp with time zone DEFAULT now() NOT NULL, + update_date timestamp with time zone DEFAULT now() NOT NULL, + finish_date timestamp with time zone +); + + +-- +-- Name: order_tracking_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +ALTER TABLE public.order_tracking ALTER COLUMN id ADD GENERATED ALWAYS AS IDENTITY ( + SEQUENCE NAME public.order_tracking_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: objenious_operation_change objenious_operation_change_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.objenious_operation_change + ADD CONSTRAINT objenious_operation_change_pkey PRIMARY KEY (id); + + +-- +-- Name: objenious_operation objenious_operation_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.objenious_operation + ADD CONSTRAINT objenious_operation_pkey PRIMARY KEY (id); + + +-- +-- Name: order_history order_history_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.order_history + ADD CONSTRAINT order_history_pkey PRIMARY KEY (id); + + +-- +-- Name: order_tracking order_tracking_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.order_tracking + ADD CONSTRAINT order_tracking_pkey PRIMARY KEY (id); + + +-- +-- Name: idx_order_change_date; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_order_change_date ON public.order_history USING btree (change_date); + + +-- +-- Name: idx_order_correlation; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_order_correlation ON public.order_tracking USING btree (correlation_id); + + +-- +-- Name: idx_order_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX idx_order_id ON public.order_history USING btree (order_id); + + +-- +-- Name: operation_change; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX operation_change ON public.objenious_operation_change USING btree (operation_id); + + +-- +-- Name: pending_operations; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX pending_operations ON public.objenious_operation USING btree (start_date) WHERE (end_date IS NULL); + + +-- +-- Name: pending_orders; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX pending_orders ON public.order_tracking USING btree (start_date) WHERE (finish_date IS NULL); + + +-- +-- Name: objenious_operation_change fk_operation_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.objenious_operation_change + ADD CONSTRAINT fk_operation_id FOREIGN KEY (operation_id) REFERENCES public.objenious_operation(id); + + +-- +-- Name: order_history fk_order_id; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.order_history + ADD CONSTRAINT fk_order_id FOREIGN KEY (order_id) REFERENCES public.order_tracking(id) ON DELETE CASCADE; + + +-- +-- PostgreSQL database dump complete +-- + +\unrestrict 8rNdhulAsfz5yOkZrPZ5f3riDYVBHnFPTcb2MraxKbPVyPsdTm81R2jsJppwk7u + diff --git a/deployment/database/init.sql b/deployment/database/init.sql index 04ed2d2..bb0eb5b 100644 --- a/deployment/database/init.sql +++ b/deployment/database/init.sql @@ -1,66 +1,3 @@ --- 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 ( - 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 - order_type order_types NOT NULL DEFAULT 'unknown', - - 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, - - start_date TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'), - update_date TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'), - finish_date TIMESTAMP -); - --- Busqueda según id de rabbit -CREATE INDEX IF NOT EXISTS idx_order_correlation - ON order_tracking(correlation_id); --- Ordenenes que todavia no han finalizado -CREATE INDEX IF NOT EXISTS pending_orders - ON order_tracking(start_date) - WHERE order_tracking.finish_date IS NULL; - -CREATE TABLE IF NOT EXISTS order_history( - id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, - order_id BIGINT NOT NULL, - 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() at time zone 'utc'), - - CONSTRAINT fk_order_id - FOREIGN KEY(order_id) - REFERENCES order_tracking(id) - ON DELETE CASCADE -); - --- fk de order -CREATE INDEX IF NOT EXISTS idx_order_id - ON order_history(order_id); - --- busquedas por fecha -CREATE INDEX IF NOT EXISTS idx_order_change_date - ON order_history(change_date); - CREATE TYPE status_enum AS ENUM ('noRequestID','noMassID','running','finished','error','other'); @@ -110,7 +47,8 @@ CREATE TABLE if not exists objenious_operation_change ( CREATE INDEX operation_change ON objenious_operation_change(operation_id); CREATE TABLE IF NOT EXISTS db_versions ( - version TEXT PRIMARY KEY, -- version semantica x.x.x + id BIGINT BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + version TEXT, -- version semantica x.x.x notes TEXT, creation_date TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'), stable BOOLEAN DEFAULT FALSE -- Si la version ha sido testada y se puede desplegar diff --git a/deployment/database/migrations/1.0.0_orders.sql b/deployment/database/migrations/1.0.0_orders.sql new file mode 100644 index 0000000..912710a --- /dev/null +++ b/deployment/database/migrations/1.0.0_orders.sql @@ -0,0 +1,67 @@ + +-- Tablas para el seguimiento de las operaciones de SIM sin importar +-- la cmpañia. +DO $$ BEGIN + 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 + ); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +CREATE TABLE IF NOT EXISTS order_tracking ( + 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 + order_type order_types NOT NULL DEFAULT 'unknown', + + 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, + + start_date TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'), + update_date TIMESTAMP NOT NULL DEFAULT (now() at time zone 'utc'), + finish_date TIMESTAMP +); + +-- Busqueda según id de rabbit +CREATE INDEX IF NOT EXISTS idx_order_correlation + ON order_tracking(correlation_id); +-- Ordenenes que todavia no han finalizado +CREATE INDEX IF NOT EXISTS pending_orders + ON order_tracking(start_date) + WHERE order_tracking.finish_date IS NULL; + +CREATE TABLE IF NOT EXISTS order_history( + id BIGINT PRIMARY KEY GENERATED ALWAYS AS IDENTITY, + order_id BIGINT NOT NULL, + 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() at time zone 'utc'), + + CONSTRAINT fk_order_id + FOREIGN KEY(order_id) + REFERENCES order_tracking(id) + ON DELETE CASCADE +); + +-- fk de order +CREATE INDEX IF NOT EXISTS idx_order_id + ON order_history(order_id); + +-- busquedas por fecha +CREATE INDEX IF NOT EXISTS idx_order_change_date + ON order_history(change_date); + diff --git a/deployment/database/migrations/1.0.0_utc.sql b/deployment/database/migrations/1.0.1_utc.sql similarity index 68% rename from deployment/database/migrations/1.0.0_utc.sql rename to deployment/database/migrations/1.0.1_utc.sql index 2b62cb4..380b611 100644 --- a/deployment/database/migrations/1.0.0_utc.sql +++ b/deployment/database/migrations/1.0.1_utc.sql @@ -1,3 +1,6 @@ +/* +* Fechas modificadas para que todas sean en base a 'UTC' +* */ ALTER TABLE objenious_operation ALTER COLUMN start_date SET DEFAULT (now() at time zone 'utc'), ALTER COLUMN last_change_date SET DEFAULT (now() at time zone 'utc'); @@ -5,11 +8,5 @@ ALTER TABLE objenious_operation ALTER TABLE objenious_operation_change ALTER COLUMN creation_date SET DEFAULT (now() at time zone 'utc'); -INSERT INTO db_versions ( - version, - notes -) -VALUES ( - '1.0.0', - 'Fechas modificadas para que todas sean en base a UTC' -); + + diff --git a/deployment/database/migrations/1.0.2_timezones.sql b/deployment/database/migrations/1.0.2_timezones.sql new file mode 100644 index 0000000..3f2d68b --- /dev/null +++ b/deployment/database/migrations/1.0.2_timezones.sql @@ -0,0 +1,30 @@ + +/* +* Fechas modificadas para que se puedan hacer query en base a la zona horaria objetivo +* SELECT col_date at time zone 'cet' -- devuleve la fecha en esa zona +* SELECT col_date -- devuleve la fecha en UTC con el offset de la zona horaria +* +* */ + +ALTER TABLE objenious_operation + ALTER COLUMN start_date SET DATA TYPE TIMESTAMP WITH TIME ZONE, + ALTER COLUMN start_date SET DEFAULT now(), + ALTER COLUMN last_change_date SET DATA TYPE TIMESTAMP WITH TIME ZONE, + ALTER COLUMN last_change_date SET DEFAULT now(), + ALTER COLUMN end_date SET DATA TYPE TIMESTAMP WITH TIME ZONE; + +ALTER TABLE objenious_operation_change + ALTER COLUMN creation_date SET DATA TYPE TIMESTAMP WITH TIME ZONE, + ALTER COLUMN creation_date SET DEFAULT now(); + +ALTER TABLE order_tracking + ALTER COLUMN start_date SET DATA TYPE TIMESTAMP WITH TIME ZONE, + ALTER COLUMN start_date SET DEFAULT now(), + ALTER COLUMN update_date SET DATA TYPE TIMESTAMP WITH TIME ZONE, + ALTER COLUMN update_date SET DEFAULT now(), + ALTER COLUMN finish_date SET DATA TYPE TIMESTAMP WITH TIME ZONE; + +ALTER TABLE order_history + ALTER COLUMN change_date SET DATA TYPE TIMESTAMP WITH TIME ZONE, + ALTER COLUMN change_date SET DEFAULT now(); + diff --git a/package.json b/package.json index fb0a23e..073ab7e 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "lint": "eslint .", "lint:fix": "eslint --fix .", "format": "prettier --write .", - "format:check": "prettier --check ." + "format:check": "prettier --check .", + "migrate": "db-migrate -e .env -m deployment/database/migrations -t 99.0.0" }, "dependencies": { "@tsconfig/node22": "^22.0.5", diff --git a/packages/sim-shared/infrastructure/SimOrderRepoository.ts b/packages/sim-shared/infrastructure/SimOrderRepository.ts similarity index 100% rename from packages/sim-shared/infrastructure/SimOrderRepoository.ts rename to packages/sim-shared/infrastructure/SimOrderRepository.ts