Adzacam commited on
Commit
79c0eb4
·
1 Parent(s): d7b4e65

feat: integrate automatic database migration execution on application startup

Browse files
Files changed (2) hide show
  1. app.py +8 -0
  2. migrate.py +122 -0
app.py CHANGED
@@ -94,6 +94,14 @@ app = FastAPI(
94
  version="1.0.0"
95
  )
96
 
 
 
 
 
 
 
 
 
97
  # CORS: sólo permite peticiones desde el frontend registrado
98
  _ALLOWED_ORIGINS = [
99
  origin.strip()
 
94
  version="1.0.0"
95
  )
96
 
97
+ from migrate import run_migrations
98
+ @app.on_event("startup")
99
+ def on_startup():
100
+ try:
101
+ run_migrations()
102
+ except Exception as e:
103
+ logger.error(f"Error executing startup migrations: {e}")
104
+
105
  # CORS: sólo permite peticiones desde el frontend registrado
106
  _ALLOWED_ORIGINS = [
107
  origin.strip()
migrate.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ from sqlalchemy import text
4
+ from database import engine
5
+
6
+ def run_migrations():
7
+ print("Connecting to database...")
8
+ with engine.connect() as conn:
9
+ trans = conn.begin()
10
+ try:
11
+ # 1. Add estado_academico column to fact_rendimiento_academico
12
+ print("Adding column estado_academico to fact_rendimiento_academico...")
13
+ conn.execute(text("""
14
+ ALTER TABLE public.fact_rendimiento_academico
15
+ ADD COLUMN IF NOT EXISTS estado_academico VARCHAR(50);
16
+ """))
17
+
18
+ # 2. De-duplicate fact_marketing
19
+ print("De-duplicating public.fact_marketing...")
20
+ conn.execute(text("""
21
+ DELETE FROM public.fact_marketing a USING public.fact_marketing b
22
+ WHERE a.id_hecho_mkt < b.id_hecho_mkt
23
+ AND a.id_modulo = b.id_modulo
24
+ AND a.id_tiempo = b.id_tiempo;
25
+ """))
26
+
27
+ # Add constraint if not exists
28
+ print("Adding constraint uq_fact_marketing_modulo_tiempo...")
29
+ conn.execute(text("""
30
+ ALTER TABLE public.fact_marketing
31
+ DROP CONSTRAINT IF EXISTS unique_modulo_tiempo;
32
+ """))
33
+ conn.execute(text("""
34
+ ALTER TABLE public.fact_marketing
35
+ DROP CONSTRAINT IF EXISTS uq_fact_marketing_modulo_tiempo;
36
+ """))
37
+ conn.execute(text("""
38
+ ALTER TABLE public.fact_marketing
39
+ ADD CONSTRAINT uq_fact_marketing_modulo_tiempo UNIQUE (id_modulo, id_tiempo);
40
+ """))
41
+
42
+ # 3. De-duplicate fact_rentabilidad (public.fact_rentabilidad)
43
+ print("De-duplicating public.fact_rentabilidad...")
44
+ conn.execute(text("""
45
+ DELETE FROM public.fact_rentabilidad a USING public.fact_rentabilidad b
46
+ WHERE a.id_hecho_rent < b.id_hecho_rent
47
+ AND a.id_categoria = b.id_categoria
48
+ AND a.id_tiempo = b.id_tiempo;
49
+ """))
50
+ print("Adding constraint uq_fact_rentabilidad_categoria_tiempo...")
51
+ conn.execute(text("""
52
+ ALTER TABLE public.fact_rentabilidad
53
+ DROP CONSTRAINT IF EXISTS uq_fact_rentabilidad_categoria_tiempo;
54
+ """))
55
+ conn.execute(text("""
56
+ ALTER TABLE public.fact_rentabilidad
57
+ ADD CONSTRAINT uq_fact_rentabilidad_categoria_tiempo UNIQUE (id_categoria, id_tiempo);
58
+ """))
59
+
60
+ # 4. De-duplicate fact_rendimiento_academico
61
+ print("De-duplicating public.fact_rendimiento_academico...")
62
+ conn.execute(text("""
63
+ DELETE FROM public.fact_rendimiento_academico a USING public.fact_rendimiento_academico b
64
+ WHERE a.id_hecho_aca < b.id_hecho_aca
65
+ AND a.id_estudiante = b.id_estudiante
66
+ AND a.id_modulo = b.id_modulo;
67
+ """))
68
+ print("Adding constraint uq_fact_rendimiento_estudiante_modulo...")
69
+ conn.execute(text("""
70
+ ALTER TABLE public.fact_rendimiento_academico
71
+ DROP CONSTRAINT IF EXISTS uq_fact_rendimiento_estudiante_modulo;
72
+ """))
73
+ conn.execute(text("""
74
+ ALTER TABLE public.fact_rendimiento_academico
75
+ ADD CONSTRAINT uq_fact_rendimiento_estudiante_modulo UNIQUE (id_estudiante, id_modulo);
76
+ """))
77
+
78
+ # 5. De-duplicate fact_situacion_financiera
79
+ print("De-duplicating public.fact_situacion_financiera...")
80
+ conn.execute(text("""
81
+ DELETE FROM public.fact_situacion_financiera a USING public.fact_situacion_financiera b
82
+ WHERE a.id_hecho_fin < b.id_hecho_fin
83
+ AND a.id_estudiante = b.id_estudiante
84
+ AND a.id_tiempo = b.id_tiempo;
85
+ """))
86
+ print("Adding constraint uq_fact_situacion_financiera_estudiante_tiempo...")
87
+ conn.execute(text("""
88
+ ALTER TABLE public.fact_situacion_financiera
89
+ DROP CONSTRAINT IF EXISTS uq_fact_situacion_financiera_estudiante_tiempo;
90
+ """))
91
+ conn.execute(text("""
92
+ ALTER TABLE public.fact_situacion_financiera
93
+ ADD CONSTRAINT uq_fact_situacion_financiera_estudiante_tiempo UNIQUE (id_estudiante, id_tiempo);
94
+ """))
95
+
96
+ # 6. De-duplicate fact_cobranzas_proyectadas
97
+ print("De-duplicating public.fact_cobranzas_proyectadas...")
98
+ conn.execute(text("""
99
+ DELETE FROM public.fact_cobranzas_proyectadas a USING public.fact_cobranzas_proyectadas b
100
+ WHERE a.id_hecho_cobro < b.id_hecho_cobro
101
+ AND a.id_estudiante = b.id_estudiante
102
+ AND a.id_tiempo = b.id_tiempo;
103
+ """))
104
+ print("Adding constraint uq_fact_cobranzas_proyectadas_estudiante_tiempo...")
105
+ conn.execute(text("""
106
+ ALTER TABLE public.fact_cobranzas_proyectadas
107
+ DROP CONSTRAINT IF EXISTS uq_fact_cobranzas_proyectadas_estudiante_tiempo;
108
+ """))
109
+ conn.execute(text("""
110
+ ALTER TABLE public.fact_cobranzas_proyectadas
111
+ ADD CONSTRAINT uq_fact_cobranzas_proyectadas_estudiante_tiempo UNIQUE (id_estudiante, id_tiempo);
112
+ """))
113
+
114
+ trans.commit()
115
+ print("Migrations successfully applied!")
116
+ except Exception as e:
117
+ trans.rollback()
118
+ print(f"Error during migration: {e}")
119
+ sys.exit(1)
120
+
121
+ if __name__ == "__main__":
122
+ run_migrations()