-
-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathNOTES.txt
More file actions
607 lines (479 loc) · 24.4 KB
/
Copy pathNOTES.txt
File metadata and controls
607 lines (479 loc) · 24.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
=====================================================
Apimetro — Guía de Base de Datos y Comandos Make
Autor: Hernán Galileo Cabrera Garibaldi
Última actualización: 2026-04
=====================================================
Este archivo documenta todos los comandos del Makefile relacionados con la
base de datos y los entornos Docker: qué hacen, cuándo usarlos y qué
implicaciones tienen sobre los datos y el esquema.
=====================================================
ARQUITECTURA DE ENTORNOS
=====================================================
El proyecto soporta tres entornos independientes. Cada uno tiene:
- Su propio volumen Docker (los datos NO se comparten entre entornos)
- Sus propias credenciales (.env.dev / .env.qa / .env.main)
- Su propia red Docker interna
- Puertos distintos para no colisionar con PostgreSQL local
ENTORNO API (host) DB (host) GIN_MODE AutoMigrate
------- ---------- --------- -------- -----------
DEV :8080 :5433 debug Solo si DB_HOST=localhost
QA :8081 :5434 debug Solo si DB_HOST=localhost
MAIN :8082 :5435 release Desactivado (usa init.sql)
NOTA: El puerto 5432 del host queda libre para tu PostgreSQL local nativo.
=====================================================
EXTENSIONES DE BASE DE DATOS
=====================================================
El archivo db/init/init.sql instala las siguientes extensiones al crear
el contenedor por primera vez:
postgis — Soporte de tipos geométricos (Point, LineString,
MultiPolygon, etc.), funciones espaciales (ST_AsGeoJSON,
ST_DWithin, ST_Intersects, ST_Length, ST_Union) e índices
GiST para búsquedas espaciales eficientes.
postgis_topology — Soporte de topología vectorial (requerida como dependencia
de postgis y para análisis de conectividad futuros en el
esquema plutarco).
IMPORTANTE: Si agregas una nueva extensión a la DB local, ejecuta
'make db-sync' y actualiza este archivo.
=====================================================
ESQUEMAS
=====================================================
public — Esquema principal. Contiene todas las tablas de transporte
actualmente en uso por la API.
plutarco — Esquema para datos geoespaciales del INEGI usados por VFT
(motor de Valor de Flujo de Transporte).
Tablas:
plutarco.agebs — AGEBs urbanas + Censo 2020. 6 estados
de la macrometrópoli (~11,787 polígonos).
plutarco.calles — Red vial CDMX (175,540 segmentos).
plutarco.uso_suelo — Uso de suelo y vegetación (INEGI 1993).
plutarco.curvas_nivel — Isohipsas (INEGI Cartas Topográficas).
plutarco.afluencia_linea — Afluencia mensual por línea (Issue #39).
plutarco.catalogo_homologacion — Mapeo nombre CSV → linea_id.
Cargado por: ETL/DataCharge/LoadAgebs.py, LoadPlutarcoGeo.py,
LoadAfluencia.py (ver sección ETL más abajo).
El rol apimetro_read tiene permisos SELECT sobre este esquema.
=====================================================
TABLAS Y ORDEN DE INSERCIÓN (FK SAFETY)
=====================================================
El orden importa al insertar datos manualmente o al cargar seed.sql.
Respetar este orden evita errores de violación de llave foránea.
ORDEN TABLA DESCRIPCIÓN
----- ----- -----------
1 lineas Líneas de transporte. Sin dependencias FK.
317 registros. Tabla raíz del modelo.
2 ramals Variantes de ruta (IDA/REGRESO/ramales).
FK → lineas.id
693 registros. Contiene geometría
MultiLineString PostGIS (SRID 4326).
3 estacions Estaciones y paradas.
FK → lineas.id
22,878 registros. Contiene geometría
Point PostGIS (SRID 4326).
4 descripcion_lineas Datos históricos y descriptivos de líneas.
FK → lineas.id
0 registros actualmente.
5 descripcion_estacions Datos históricos de estaciones.
FK → estacions.id
0 registros actualmente.
6 historico_operacion Métricas operativas por ramal.
FK → lineas.id, ramals.id
690 registros.
ramal_id tiene restricción UNIQUE.
7 limites_territoriales Polígonos administrativos (alcaldías CDMX
y municipios Área Metropolitana).
Sin FK. 553 registros. 16 MB de geometrías.
TABLAS QUE NO SE INCLUYEN EN DUMPS NI SEEDS:
- estaciones_backup, lineas_backup, ramales_backup → tablas de respaldo manual
- spatial_ref_sys → tabla interna de PostGIS, no manipular
=====================================================
SEGURIDAD — ROL apimetro_read
=====================================================
La API de Go se conecta con el rol 'apimetro_read', que tiene ÚNICAMENTE
permisos de SELECT sobre los esquemas public y plutarco. Este rol es creado
automáticamente por db/init/roles.sh al inicializar el contenedor.
Permisos de apimetro_read:
- CONNECT a la base de datos
- USAGE en esquemas public y plutarco
- SELECT en todas las tablas actuales y futuras (via DEFAULT PRIVILEGES)
- SIN permisos de INSERT, UPDATE, DELETE ni DDL
El usuario administrador (POSTGRES_USER en .env.*) es el único con permisos
completos y solo lo usa Docker internamente para inicializar la DB.
NUNCA expongas las credenciales del administrador en la API.
=====================================================
COMANDOS MAKE — REFERENCIA COMPLETA
=====================================================
------------------------------------------------------
make docs
------------------------------------------------------
QUÉ HACE:
Ejecuta ~/go/bin/swag init para regenerar los archivos de documentación
Swagger en cmd/docs/ (docs.go, swagger.json, swagger.yaml).
CUÁNDO USARLO:
- Después de modificar cualquier anotación @Summary, @Param, @Success, etc.
en los archivos de cmd/pkg/routes/
- Después de agregar o modificar structs en cmd/pkg/models/
- Se ejecuta automáticamente como prerequisito de dev, build y docker-*
IMPLICACIONES:
- Sobreescribe cmd/docs/ completamente. No editar esos archivos a mano.
- No afecta la base de datos ni los contenedores.
------------------------------------------------------
make dev
------------------------------------------------------
QUÉ HACE:
1. Ejecuta 'make docs' (actualiza Swagger)
2. Lanza ~/go/bin/air para correr la API con hot-reload
CUÁNDO USARLO:
Desarrollo local SIN Docker. Requiere que PostgreSQL esté corriendo en
localhost:5432 con la base db_apimetro.
IMPLICACIONES:
- La API corre en http://localhost:8080
- Ejecuta AutoMigrate de GORM (crea/altera tablas si hay cambios en modelos)
- Air reconstruye el binario automáticamente al detectar cambios en .go
------------------------------------------------------
make build
------------------------------------------------------
QUÉ HACE:
1. Ejecuta 'make docs'
2. Compila el binario en bin/apimetro usando go build
CUÁNDO USARLO:
Para compilar un binario local sin Docker (debugging, pruebas de release).
IMPLICACIONES:
- No levanta ningún servidor ni contenedor.
- El binario resultante lee variables de entorno para la conexión a DB.
------------------------------------------------------
make clean
------------------------------------------------------
QUÉ HACE:
Elimina: bin/, tmp/, cmd/docs/
CUÁNDO USARLO:
Para limpiar artefactos de compilación y regenerar desde cero.
IMPLICACIONES:
- NO afecta volúmenes Docker ni datos de la DB.
- Los docs se regenerarán en el siguiente 'make docs' o 'make dev'.
------------------------------------------------------
make docker-dev
------------------------------------------------------
QUÉ HACE:
1. Ejecuta 'make docs'
2. chmod +x db/init/roles.sh
3. docker compose --profile dev --env-file .env.dev up --build
CUÁNDO USARLO:
Para levantar el entorno de desarrollo completo en Docker.
Recomendado cuando no tienes PostgreSQL instalado localmente o quieres
un entorno idéntico al de producción.
PUERTOS:
API → http://localhost:8080
DB → localhost:5433 (conectar con pgAdmin u otro cliente)
IMPLICACIONES:
- Primera ejecución: Docker construye la imagen de la API y crea el
volumen pgdata_dev. PostgreSQL ejecuta init.sql y roles.sh
automáticamente (crea esquema y rol apimetro_read).
- Ejecuciones posteriores: el volumen ya existe, init.sql y roles.sh
NO se vuelven a ejecutar. Los datos persisten entre reinicios.
- La API NO ejecuta AutoMigrate porque DB_HOST=db_dev (no localhost).
- Para cargar datos después de la primera ejecución, usa el proceso
de inyección de seed.sql documentado al final de este archivo.
------------------------------------------------------
make docker-qa
------------------------------------------------------
QUÉ HACE:
Igual que docker-dev pero con el perfil 'qa' y .env.qa
PUERTOS:
API → http://localhost:8081
DB → localhost:5434
IMPLICACIONES:
- Volumen independiente: pgdata_qa. No comparte datos con DEV ni MAIN.
- Ideal para correr pruebas de integración y regresión antes de promover
a producción.
- GIN_MODE=debug para ver logs detallados de las peticiones.
------------------------------------------------------
make docker-main
------------------------------------------------------
QUÉ HACE:
Igual que docker-dev pero con el perfil 'main' y .env.main.
Los contenedores tienen restart: always (se reinician con el sistema).
PUERTOS:
API → http://localhost:8082
DB → localhost:5435
IMPLICACIONES:
- Volumen independiente: pgdata_main. NUNCA sobrescribir con datos de dev.
- GIN_MODE=release: no se imprimen logs de rutas ni requests en consola.
- CAMBIAR LAS CONTRASEÑAS en .env.main antes de usar en producción.
Los valores por defecto son placeholders explícitos.
- Los contenedores de MAIN tienen política restart:always (DEV y QA
usan unless-stopped).
------------------------------------------------------
make docker-down-dev / docker-down-qa / docker-down-main
------------------------------------------------------
QUÉ HACE:
Detiene y elimina los contenedores del entorno especificado.
IMPLICACIONES:
- Los VOLÚMENES de datos persisten (pgdata_dev, pgdata_qa, pgdata_main).
- Para eliminar también los volúmenes: agregar la flag --volumes al
comando docker compose correspondiente (operación destructiva).
------------------------------------------------------
make db-sync
------------------------------------------------------
QUÉ HACE:
Ejecuta pg_dump --schema-only desde la DB local (puerto 5432, usuario
prueba) y sobreescribe db/init/init.sql con el esquema actualizado.
Excluye: estaciones_backup, lineas_backup, ramales_backup, spatial_ref_sys.
CUÁNDO USARLO:
Cuando hagas cambios manuales en la DB local (agregar columnas, crear
nuevas tablas, modificar índices) y quieras que esos cambios queden
reflejados en el init.sql para futuros contenedores nuevos.
IMPLICACIONES:
- SOBREESCRIBE db/init/init.sql sin confirmación.
- El archivo generado es solo DDL (sin datos). Para los datos usa
el proceso de seed.sql documentado abajo.
- REVISAR el archivo generado antes de hacer commit o usar con Docker,
ya que pg_dump puede incluir sentencias específicas de la versión local.
- Los contenedores existentes NO son afectados (el init.sql solo se
ejecuta cuando se crea un volumen nuevo desde cero).
=====================================================
PROCESO DE CARGA DE DATOS (SEED)
=====================================================
El archivo db/init/seed.sql NO está incluido en el repositorio (está en
.gitignore) porque contiene ~34 MB de datos de transporte.
Para regenerarlo desde la DB local y cargarlo en un contenedor:
PASO 1 — Generar seed.sql desde la DB local:
PGPASSWORD=postgres pg_dump \
--data-only --inserts --disable-triggers \
-t lineas -t ramals -t estacions \
-t descripcion_lineas -t descripcion_estacions \
-t historico_operacion -t limites_territoriales \
-h localhost -p 5432 -U prueba db_apimetro \
> db/init/seed.sql
PASO 2 — Asegurarse de que el contenedor objetivo esté healthy:
docker ps --filter "name=apimetro_db_dev"
PASO 3 — Inyectar en el contenedor DEV (usa el usuario administrador):
PGPASSWORD='Dev_Adm1nP4ss!2024' psql \
-h localhost -p 5433 \
-U admin_apimetro -d db_apimetro \
-v ON_ERROR_STOP=1 \
-f db/init/seed.sql
Para QA (puerto 5434):
PGPASSWORD='QA_Adm1nP4ss!2024' psql \
-h localhost -p 5434 \
-U admin_apimetro -d db_apimetro \
-v ON_ERROR_STOP=1 \
-f db/init/seed.sql
PASO 4 — Verificar conteos:
PGPASSWORD='Dev_Adm1nP4ss!2024' psql \
-h localhost -p 5433 -U admin_apimetro -d db_apimetro -t -c "
SELECT relname, n_live_tup
FROM pg_stat_user_tables
WHERE schemaname = 'public'
ORDER BY n_live_tup DESC;"
CONTEOS ESPERADOS (abril 2026):
estacions 22,878
ramals 693
historico_operacion 690
limites_territoriales 553
lineas 317
descripcion_lineas 0
descripcion_estacions 0
NOTA: La flag --disable-triggers en pg_dump genera sentencias
SET session_replication_role = replica; en el seed.sql, lo que
desactiva las FK durante la carga. Esto requiere que el usuario que
inyecta tenga privilegios de superusuario (admin_apimetro los tiene).
NUNCA usar apimetro_read para inyectar datos.
=====================================================
PROCESO DE SEED PLUTARCO
=====================================================
El archivo db/init/seed_plutarco.sql NO está en git (.gitignore).
Contiene los datos de las 4 tablas del esquema plutarco en formato COPY.
Tamaño: ~109 MB. Generado con pg_dump desde la DB DEV.
PARA GENERAR seed_plutarco.sql (desde DB DEV local):
PGPASSWORD='Dev_Adm1nP4ss!2024' pg_dump \
--data-only --schema=plutarco --disable-triggers \
-h localhost -p 5433 \
-U admin_apimetro db_apimetro \
> db/init/seed_plutarco.sql
PARA APLICAR EN UN ENTORNO NUEVO:
PASO 1 — Asegurarse de que init_plutarco.sql ya fue ejecutado:
PGPASSWORD='...' psql -h localhost -p <PUERTO> \
-U admin_apimetro -d db_apimetro \
-f db/init/init_plutarco.sql
PASO 2 — Inyectar los datos:
PGPASSWORD='Dev_Adm1nP4ss!2024' psql \
-h localhost -p 5433 \
-U admin_apimetro -d db_apimetro \
-v ON_ERROR_STOP=1 \
-f db/init/seed_plutarco.sql
CONTEOS ESPERADOS (6 tablas):
calles 175,540
agebs 11,787
uso_suelo 6,879
curvas_nivel 2,661
afluencia_linea (varía según datos cargados)
catalogo_homologacion ~111 (variantes de nombres CSV)
INTEGRIDAD VERIFICADA (2026-06-05):
- 0 geometrías nulas en las 4 tablas
- 0 geometrías inválidas (ST_IsValid)
- 0 registros con SRID != 4326
- 0 atributos críticos nulos
- agebs: todas las entidades en rango (09,15,17,21,22,29)
- calles: 100% cobertura CDMX (cve_ent='09')
DIFERENCIAS VS seed.sql (esquema public):
- seed.sql usa --inserts (compatibilidad). seed_plutarco.sql usa COPY
(más eficiente para 175k+ filas de geometría).
- seed_plutarco.sql NO depende de los archivos fuente (AGEBS/, Censo/,
Vialidades/, Medio_Fisico/). Una vez generado, esos directorios
pueden eliminarse del equipo local sin perder la capacidad de
replicar el entorno.
=====================================================
ETL — CARGA DE DATOS PLUTARCO
=====================================================
Los scripts ETL están en ETL/ y usan ETL/conf.py para la conexión a DB.
conf.py lee variables de entorno con fallback a valores locales.
------------------------------------------------------
Credenciales para conectarse desde máquina local
------------------------------------------------------
Los scripts ETL necesitan el usuario administrador (con permisos de INSERT
sobre el esquema plutarco). Configura estas variables de entorno antes de
correr cualquier script ETL:
export DB_HOST=localhost
export DB_PORT=5433 # DEV (5434=QA, 5435=MAIN)
export DB_NAME=db_apimetro
export DB_USER=admin_apimetro
export DB_PASSWORD='Dev_Adm1nP4ss!2024'
O en una línea para una ejecución puntual:
DB_HOST=localhost DB_PORT=5433 DB_NAME=db_apimetro \
DB_USER=admin_apimetro DB_PASSWORD='Dev_Adm1nP4ss!2024' \
python3 ETL/load_agebs.py
Para conectarte con pgAdmin / DBeaver / psql desde tu máquina local:
Host: localhost
Port: 5433
Database: db_apimetro
User: admin_apimetro
Password: Dev_Adm1nP4ss!2024
NOTA: apimetro_read es de solo lectura — no sirve para ETL.
------------------------------------------------------
ETL/DataCharge/LoadAgebs.py — AGEBs urbanas + Censo 2020
------------------------------------------------------
Estado: COMPLETADO (11,787 AGEBs cargadas)
Fuentes de datos:
Shapefiles: ETL/Data/AGEBS/ (6 estados macrometrópoli)
CSVs Censo 2020: ETL/Data/Censo/ (una carpeta por estado)
Idempotencia: ON CONFLICT (cve_ageb) DO NOTHING
------------------------------------------------------
ETL/DataCharge/LoadAfluencia.py — Afluencia por línea
------------------------------------------------------
Estado: IMPLEMENTADO (Issue #39)
Prerequisitos (ejecutar ANTES del ETL):
1. psql -f db/migrations/v2.0_afluencia.sql ← crea tablas
2. psql -f db/migrations/seed_catalogo_homologacion.sql ← carga catálogo
Fuentes de datos:
ETL/Data/Pesos/
afluencia_diaria_historica.xlsx → Fuente principal (todos los sistemas)
afluencia_desglosada_cb_03_2026.csv → Complemento CBB 2026
afluencia_desglosada_tl_03_2026.csv → Complemento TL 2026
afluencia_desglosada_trolebus_03_2026.csv → Complemento TROLE 2026
afluenciartp_desglosado_03_2026.csv → Complemento RTP 2026
afluencia_desglosada_acumulada_2024_07.csv → NO USAR (global, sin línea)
Resolución de nombres: plutarco.catalogo_homologacion
Mapea nombre_csv heterogéneo → linea_id de public.lineas.
Seed estático en db/migrations/seed_catalogo_homologacion.sql
Idempotencia: ON CONFLICT (linea_id, anio, mes_num) DO NOTHING
=====================================================
MIGRACIONES — db/migrations/
=====================================================
Directorio para upgrades de esquema en entornos existentes.
Los archivos de db/init/ solo se ejecutan en volúmenes nuevos.
Los de db/migrations/ se ejecutan manualmente con psql -f.
ARCHIVO VERSIÓN DESCRIPCIÓN
------- ------- -----------
v2.0_afluencia.sql v2.0 Tablas afluencia_linea y catalogo_homologacion
seed_catalogo_homologacion.sql v2.0 Datos del catálogo de mapeo CSV→linea_id
Ejecutar en orden:
PGPASSWORD='<ADMIN_PASS>' psql \
-h localhost -p 5433 \
-U admin_apimetro -d db_apimetro \
-v ON_ERROR_STOP=1 \
-f db/migrations/v2.0_afluencia.sql
PGPASSWORD='<ADMIN_PASS>' psql \
-h localhost -p 5433 \
-U admin_apimetro -d db_apimetro \
-v ON_ERROR_STOP=1 \
-f db/migrations/seed_catalogo_homologacion.sql
Todos los archivos son idempotentes (IF NOT EXISTS, ON CONFLICT DO NOTHING).
=====================================================
CORRECCIONES DE CALIDAD DE DATOS (HISTORIAL)
=====================================================
Las siguientes correcciones se aplicaron manualmente sobre la DB. Deben
repetirse al construir un volumen nuevo desde cero (después de cargar el seed).
------------------------------------------------------
[2026-06-05] Backfill longitud/latitud en estacions (Issue #35)
------------------------------------------------------
PROBLEMA:
Las 22,878 estaciones tenían longitud=NULL y latitud=NULL. La columna
geom (PostGIS Point SRID 4326) sí estaba poblada. La migración GTFS
que introdujo ambas columnas no incluyó el backfill post-inserción.
El endpoint CRUD /movilidad/:sistema/estacion devolvía "longitud":0,
"latitud":0 en todas las estaciones (bug silencioso de presentación).
El endpoint GeoJSON no estaba afectado (lee directamente desde geom).
SOLUCIÓN APLICADA EN DEV (2026-06-05):
UPDATE public.estacions
SET
longitud = ST_X(ST_Transform(geom::geometry, 4326)),
latitud = ST_Y(ST_Transform(geom::geometry, 4326))
WHERE geom IS NOT NULL;
→ 22,878 filas actualizadas. Rango resultante:
longitud: -99.6950 a -98.9199
latitud: 19.1331 a 19.7624
PARA APLICAR EN PRODUCCIÓN:
docker exec apimetro_db_prod psql -U admin_apimetro -d db_apimetro -c "
UPDATE public.estacions
SET longitud=ST_X(ST_Transform(geom::geometry,4326)),
latitud=ST_Y(ST_Transform(geom::geometry,4326))
WHERE geom IS NOT NULL;"
NOTA PARA FUTUROS SEEDS:
Al regenerar seed.sql desde la DB local con datos correctos, el backfill
quedará embebido en los INSERTs. No será necesario re-ejecutar el UPDATE.
CÓDIGO ELIMINADO:
cmd/pkg/controller/utils/Estacion/FormatterEstacions.go — función
ConvertEstacionToJson() era código muerto (definida pero nunca llamada).
Usaba est.Longitud/est.Latitud para construir GeoJSON, pero el GeoJSON
real se genera en GeoJsonEstacion.go vía ST_AsGeoJSON(geom) directamente.
CONSTRAINT AÑADIDO (misma sesión):
ALTER TABLE public.estacions
ADD CONSTRAINT chk_coords_consistency
CHECK (
(longitud IS NULL AND latitud IS NULL AND geom IS NULL) OR
(longitud IS NOT NULL AND latitud IS NOT NULL AND geom IS NOT NULL)
);
Garantiza que los tres campos de coordenadas sean siempre consistentes.
Cualquier INSERT o UPDATE que deje longitud/latitud/geom en estado mixto
será rechazado por la DB. Ya incluido en db/init/init.sql.
=====================================================
DATOS INCOMPLETOS O DE FUENTE NO OFICIAL
=====================================================
Las siguientes líneas tienen datos parciales o provenientes de
fuentes no oficiales. No son errores del ETL sino limitaciones
conocidas de los datos de origen. Están documentadas en la tabla
descripcion_lineas mediante el script db/init/UPDATE_TROLE_13.sql.
SISTEMA LÍNEAS TIPO DETALLE
------- ------ ---- -------
TROLE 13 DATOS_INCOMPLETOS Sin datos de paradas en la fuente
GTFS (stop_times.txt vacío para TR13).
El trazo geométrico existe (shape TR13_1,
263 vértices, ruta tipo loop). ramals.geom
conserva la geometría completa sin
segmentación interestación. direction_id
ausente en trips.txt; solo existe un sentido
(ramal_num=1) por naturaleza de la ruta loop.
MEXIBÚS Todas FUENTE_NO_OFICIAL Paradas y trazos recolectados por OSMAN MAPS.
(12) No provienen del GTFS oficial de la SEMOVI.
num_estacion no está poblado; las estaciones
se ordenan por fracción geográfica en el trazo.
MEXICABLE Todas FUENTE_NO_OFICIAL Paradas y trazos recolectados por OSMAN MAPS.
(4) No provienen del GTFS oficial de la SEMOVI.
SCRIPT DE DOCUMENTACIÓN:
db/init/UPDATE_TROLE_13.sql — inserta 17 registros en descripcion_lineas
(1 TROLE 13 + 12 MEXIBÚS + 4 MEXICABLE). Ejecutar una sola vez por entorno.
Verificar antes de ejecutar (evitar duplicados):
SELECT dl.tipo, l.sistema, l.num_comercial
FROM descripcion_lineas dl
JOIN lineas l ON l.id = dl.linea_base
WHERE l.sistema IN ('TROLE','MEXIBÚS','MEXICABLE');