Fix passenger startup and clean tracked generated files

This commit is contained in:
abiandev
2026-03-31 15:14:12 +02:00
parent c1b9fe666b
commit 5385841a62
5908 changed files with 15305 additions and 872091 deletions
+154
View File
@@ -1,3 +1,15 @@
# tablas que tenemos que actualizar en la base de datos de producción
c_cambios_estado
c_cambios_estado_eliminados
c_viajes_puntos
c_viajes_puntos_tracking
c_viajes_incidencias
v_viajes_incidencias
trg_c_viajes_puntos_tracking_au
trg_c_cambios_estado_bd
# Node Gestión API Firebase Admin
Este proyecto incluye un script de prueba para enviar notificaciones con Firebase Admin SDK.
@@ -64,3 +76,145 @@ También puedes usar el script de npm:
```
npm run notify:test -- --token "<FCM_DEVICE_TOKEN>" --dry-run
```
## Fotos de estado de viaje (almacenamiento temporal dual)
Para `POST /api/trips/:id/status`, las fotos pueden guardarse en local y replicarse por SFTP en paralelo.
- `TRIP_STATUS_UPLOAD_DIR` (opcional): base local.
Default: `uploads/trips/status` dentro del proyecto.
- `TRIP_STATUS_PHOTO_STORAGE_MODE` (opcional): `local` o `dual`.
Default: `local`.
- `TRIP_STATUS_SFTP_HOST`: host SFTP remoto.
- `TRIP_STATUS_SFTP_PORT` (opcional): puerto SFTP.
Default: `22`.
- `TRIP_STATUS_SFTP_USERNAME`: usuario SFTP.
- `TRIP_STATUS_SFTP_PASSWORD`: password SFTP.
- `TRIP_STATUS_SFTP_REMOTE_BASE_DIR`: directorio base remoto.
Ejemplo de modo temporal dual:
```bash
TRIP_STATUS_PHOTO_STORAGE_MODE=dual
TRIP_STATUS_SFTP_HOST=194.164.175.51
TRIP_STATUS_SFTP_PORT=22
TRIP_STATUS_SFTP_USERNAME=ssh_fotos_estado
TRIP_STATUS_SFTP_PASSWORD=********
TRIP_STATUS_SFTP_REMOTE_BASE_DIR=/var/www/vhosts/gestion.abianservice.com/httpdocs/produccion/app/fotos_estado_react_native
```
## API: Crear incidencia de viaje
Endpoint: `POST /api/trips/:tripId/incidencias`
Auth: `Bearer <JWT>` obligatorio.
### Request JSON
```json
{
"incidencia": "Retraso por tráfico",
"notificar": 0,
"notificar_cr": 0
}
```
Notas:
- `incidencia` es obligatoria (string, `trim`, no vacía).
- `notificar`/`notificar_cr` se ignoran; backend fuerza `ind_aviso_cli=1` y `ind_aviso_cr=1`.
### Responses
- `201`:
- `{ "success": true, "message": "correcto" }`
- `{ "success": true, "message": "correcto", "warning": "email_failed" }` (si falla SMTP, sin revertir insert)
- `400`: payload inválido (`tripId` inválido o `incidencia` vacía)
- `401`: no autenticado
- `403`: usuario autenticado sin acceso al viaje
- `404`: viaje no existe
- `500`: error interno
### cURL
```bash
curl -X POST "http://127.0.0.1:3001/api/trips/248230/incidencias" \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{
"incidencia": "Cliente no localizable en punto de recogida",
"notificar": 0,
"notificar_cr": 0
}'
```
## API: Estado automático de viaje (auditoría)
Endpoint: `POST /api/trips/:id/auto-status`
Auth: `Bearer <JWT>` obligatorio.
### Request JSON
```json
{
"id_estado": 5,
"id_punto": 8123,
"observaciones": "Estado actualizado automáticamente",
"ind_fallido": 0,
"latitud": "40.416775",
"longitud": "-3.703790",
"fecha_y_hora": "2026-02-17 12:34:56"
}
```
Notas:
- `id_estado` es obligatorio.
- `id_punto` es opcional.
- Si se envía `id_punto`, `id_estado` solo puede ser `3`, `4` o `5`.
- Sin `id_punto`, se permite cualquier estado válido en `t_viaje_estados`.
- `fecha_y_hora` es opcional: si no es válida se usa hora servidor.
- No se soportan fotos (`fotos_concat`/multipart).
- Este endpoint no actualiza `c_viajes.id_estado`.
- Siempre inserta en `c_cambios_estado` con `actualizado_automaticamente=1`.
- Si hay `id_punto`, también actualiza `c_viajes_puntos` con `actualizado_automaticamente=1` para disparar `trg_c_viajes_puntos_tracking_au`.
### Responses
- `200`: estado automático registrado
- `400`: payload inválido
- `401`: no autenticado
- `403`: usuario autenticado sin acceso al viaje
- `404`: viaje o punto no existe
- `422`: `id_punto` enviado con `id_estado` fuera de `3/4/5`
- `500`: error interno
## Driver license seguro (backend)
Este backend soporta carga y acceso seguro de carnet de conducir:
- `POST /api/update_driver_license` (alias: `POST /api/upload_driver_license`)
- No usar `POST /update_profile_photo` para carnet: esa ruta es solo para `foto_perfil` y ahora rechaza payloads de `driver_license`.
- `GET /api/secure/driver-license/side/:side?dni=...&id_proveedor=...` (`side`: `front|back`)
- `GET /api/secure/driver-license/:publicId` (compatibilidad)
- `DELETE /api/secure/driver-license/:publicId` (borrado lógico)
### Variables de entorno nuevas
- `DRIVER_LICENSE_ENCRYPTION_KEY` (obligatoria): clave AES-256-GCM de 32 bytes (`hex` de 64 chars o `base64`, opcional prefijo `base64:`).
- `DRIVER_LICENSE_KEY_VERSION` (opcional, default `v1`).
- `DRIVER_LICENSE_STORAGE_DIR` (opcional, default `./secure_storage/driver-license`).
- `DRIVER_LICENSE_RETENTION_DAYS` (opcional, default `365`).
- `DRIVER_LICENSE_PURGE_BATCH_SIZE` (opcional, default `100`).
### Migración SQL
Aplicar:
```
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" < src/sql/migrations/20260216_driver_license_security.sql
mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASSWORD" "$DB_NAME" < src/sql/migrations/20260216_driver_license_sides.sql
```
### Purga física por retención
```
npm run purge:driver-licenses
```