# Base de datos del sistema de Notificaciones

## Propiedad de los datos

| Conexión | Estructuras | Propósito |
|---|---|---|
| `mysql` | `users`, `personal_access_tokens`, `firebase_device_tokens` | Identidad API, Sanctum y dispositivos FCM |
| `mysql` | `managed_notifications` | Contenido, programación, adjuntos, origen, estado y deduplicación |
| `mysql` | `managed_notification_recipients` | Historial por alumno, grupo congelado, lectura y estado por destinatario |
| `mysql` | `managed_notification_deliveries` | Intentos y resultado por dispositivo |
| `mysql` | `jobs`, `job_batches`, `failed_jobs`, `cache`, `cache_locks` | Queue, jobs únicos, Scheduler, locks y nonces HMAC |
| `mysql` | `notifications`, `cron_notification_logs` | Compatibilidad con notificaciones y cron anteriores |
| `mysql2` | `tblc_usuario`, `tblp_grupo` y tablas académicas/financieras existentes | Alumnos, grupo y fuentes de automatización |
| `mysql2` | `tblc_modulo`, `tblc_modulousuario` | Módulo y asignaciones institucionales |

Los adjuntos se almacenan en el disco configurado; la base conserva únicamente metadatos y ruta interna.

## Configuración

```dotenv
DB_CONNECTION=mysql
NOTIFICATIONS_DATABASE_CONNECTION=mysql
EXTERNAL_AUTH_CONNECTION=mysql2
NOTIFICATIONS_PERMISSION_MODULE_ID=120
```

`120` es solo un ejemplo. Debe elegirse un `IdModulo` libre, distinto de `85`. El mismo valor debe configurarse en el servidor PHP como `IUDY_NOTIFICATIONS_PERMISSION_MODULE_ID`.

El seeder valida que `tblc_modulo`, `tblc_modulousuario` y `tblc_usuario` tengan las columnas usadas por IUDY. Si encuentra una colisión, se detiene sin sobrescribir datos. No se incorpora a `DatabaseSeeder` porque nunca debe asignarse o instalarse implícitamente sobre `mysql2`.

## Preflight seguro

Ejecutar primero contra una réplica o base aislada y comprobar que cada variable apunta a la conexión prevista:

```bash
php artisan about --only=environment
php artisan migrate:status --database=mysql
php artisan migrate:status --database=mysql2 --path=database/migrations/2026_04_07_230000_add_id_usua_api_to_tblc_usuario_on_mysql2.php
```

No usar `php artisan migrate --database=mysql2` sin `--path`: el directorio principal también contiene migraciones de Laravel que no pertenecen a la base institucional.

## Orden de instalación

### 1. Esquema Laravel (`mysql`)

Para una instalación nueva, ejecutar rutas explícitas en orden. Esto evita incluir las migraciones históricas `*_on_mysql2.php` del directorio compartido:

```bash
php artisan migrate --database=mysql --path=database/migrations/0001_01_01_000000_create_users_table.php
php artisan migrate --database=mysql --path=database/migrations/0001_01_01_000001_create_cache_table.php
php artisan migrate --database=mysql --path=database/migrations/0001_01_01_000002_create_jobs_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_04_07_211108_create_personal_access_tokens_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_04_07_220000_create_notifications_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_05_20_000000_create_firebase_device_tokens_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_05_20_010000_create_cron_notification_logs_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_05_20_020000_add_is_admin_to_users_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_10_09_000000_create_managed_notifications_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_10_09_000100_create_managed_notification_recipients_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_10_09_000200_create_managed_notification_deliveries_table.php
php artisan migrate --database=mysql --path=database/migrations/2026_10_09_000300_add_managed_notification_query_indexes.php
```

Las migraciones propias de Notificaciones seleccionan además `NOTIFICATIONS_DATABASE_CONNECTION`, cuyo valor autorizado debe ser `mysql`. Cada ejecución se registra en el repositorio de migraciones de `mysql` por el parámetro `--database=mysql`.

### 2. Vínculo institucional (`mysql2`)

`IdUsuaApi` pertenece a la autenticación externa y dispone de una migración defensiva. Se instala y registra en el repositorio de migraciones de `mysql2` con:

```bash
php artisan migrate --database=mysql2 --path=database/migrations/2026_04_07_230000_add_id_usua_api_to_tblc_usuario_on_mysql2.php
```

La migración no crea `tblc_usuario`; solo agrega `IdUsuaApi` cuando la tabla existe y la columna falta.

### 3. Módulo institucional

Después de escoger el ID y configurar `NOTIFICATIONS_PERMISSION_MODULE_ID`:

```bash
php artisan db:seed --database=mysql2 --class="Database\Seeders\InstitutionalNotificationPermissionSeeder"
```

El comando puede repetirse: conserva el registro existente cuando coincide y nunca agrega filas a `tblc_modulousuario`. La asignación de operadores debe realizarse mediante el mecanismo institucional autorizado. El SQL en `docs/institutional-notifications-permission.sql` queda únicamente como referencia/manual de contingencia.

### 4. Operación

```bash
php artisan schedule:work
php artisan queue:work --queue=notifications,default --tries=3
```

Antes de habilitar automatizaciones, confirmar `CACHE_STORE` compartido entre instancias, el worker de cola, el disco de adjuntos y `NOTIFICATIONS_AUTOMATION_ENABLED`.

## Verificación posterior

- `mysql`: las tablas administradas y sus claves foráneas existen; `managed_notifications.dedupe_key` es único.
- `mysql`: existen índices para despacho `(status, scheduled_at)`, historial/lectura y procesamiento de destinatarios.
- `mysql2`: `tblc_usuario.IdUsuaApi` existe cuando el login global lo requiere.
- `mysql2`: existe exactamente un módulo `Modulo = NOTIFICACIONES` con el ID configurado.
- `mysql2`: solo los operadores autorizados aparecen en `tblc_modulousuario`.
- Scheduler y worker se ejecutan con la cola `notifications`; las pruebas usan FCM simulado.

## Reversión segura

1. Deshabilitar automatizaciones y detener Scheduler/worker.
2. Respaldar tablas y adjuntos antes de cualquier reversión.
3. Para revertir únicamente los índices añadidos, usar `migrate:rollback` sobre la ruta `2026_10_09_000300_add_managed_notification_query_indexes.php`, comprobando antes el lote registrado en `mysql`.
4. No revertir las tablas administradas si contienen historial o adjuntos; una reversión de esas migraciones elimina datos por diseño.
5. El seeder no elimina el módulo. Para retirarlo, eliminar primero sus asignaciones y después el módulo dentro de una transacción institucional expresamente autorizada.
6. No ejecutar un rollback global de `mysql2`: existen migraciones históricas ajenas a Notificaciones que requieren revisión independiente.

