Supabase - FactoriaF5-Asturias/project-p5-digital-academy-team3-restaurant-backend GitHub Wiki

Índice Supabase

Qué hace

El enunciado pide que el sistema genere de forma automática un resumen de ventas en PDF y lo guarde en un almacenamiento de objetos en la nube. Usamos Supabase Storage.

Cada noche, a las 00:05 (hora de Madrid), el backend genera el PDF de ventas del día anterior y lo sube al bucket sales-reports como:

daily/sales-report-AAAA-MM-DD.pdf

Es el mismo PDF que se descarga desde GET /api/v1/invoices/report/pdf, con las facturas del día y los totales.

Cómo funciona

Clase Paquete Qué hace
SupabaseStorageProperties storage Lee supabase.url, supabase.service-key y supabase.reports-bucket. La clave no sale nunca en el toString()
SupabaseStorageClient storage Sube un fichero con un POST a {SUPABASE_URL}/storage/v1/object/{bucket}/{ruta} usando RestClient. Si el fichero ya existe lo sobrescribe (x-upsert). Timeouts: 5 s para conectar, 30 s para la respuesta
SalesReportArchiveJob invoices.service Tarea @Scheduled: genera el PDF con SalesReportPdfService y lo sube. Si algo falla, lo escribe en el log y la app sigue funcionando
SalesReportArchiveConfig config Crea las dos clases anteriores y activa @EnableScheduling, solo si SUPABASE_URL tiene valor

No usamos la librería ni la CLI de Supabase: el backend habla con la API REST de Storage por HTTP.

Gracias a la condición de SalesReportArchiveConfig, quien no tenga las variables de Supabase arranca el backend y pasa los tests igual que siempre. La tarea simplemente no existe.

Configuración

1. Variables en el .env

SUPABASE_URL=https://humjxfnaqjxirkknngvf.supabase.co
SUPABASE_SERVICE_KEY=sb_secret_...

Opcionales:

Variable Por defecto Para qué
SUPABASE_REPORTS_BUCKET sales-reports Cambiar el bucket
SALES_REPORT_ARCHIVE_CRON 0 5 0 * * * Cambiar la hora (cron de Spring: segundos, minutos, horas, día, mes, día de la semana)

IMPORTANTE: si rellenas SUPABASE_URL pero dejas vacía SUPABASE_SERVICE_KEY, el backend no arranca. Rellena las dos o ninguna.

En Docker (docker compose --profile app up) estas variables se pasan solas desde el .env. Ver Docker.

2. El bucket

sales-reports, privado y limitado a application/pdf. Ya está creado en el proyecto. Si hubiera que recrearlo: Storage → New bucket, nombre sales-reports, con Public bucket desactivado.

El bucket images (público) es otro, el de las imágenes de producto.

Comprobar que funciona

Al arrancar el backend con las variables puestas no se ve nada especial: la tarea espera a las 00:05.

Subirlo a mano (lo más rápido, y lo que usamos en la demo)

curl -X POST "http://localhost:8080/api/v1/invoices/report/archive?date=2026-10-05"

Sin date sube el de ayer. Respuesta:

{"date":"2026-10-05","path":"daily/sales-report-2026-10-05.pdf"}
Código Significa
200 Subido. Aparece en Storage → sales-reports → daily
400 La fecha no tiene el formato AAAA-MM-DD
502 Supabase ha rechazado la subida (clave mala, bucket inexistente...)
503 Faltan SUPABASE_URL o SUPABASE_SERVICE_KEY en el .env

Solo está abierto con el perfil dev. Con la seguridad de roles será solo para ADMIN.

Probar la tarea programada

Para ver la tarea nocturna funcionando sin esperar, añade temporalmente esta línea al .env y arranca el backend como siempre (VS Code o Docker):

SALES_REPORT_ARCHIVE_CRON=*/15 * * * * *

En el log debe salir:

SalesReportArchiveJob : Resumen de ventas del 2026-10-01 subido a daily/sales-report-2026-10-01.pdf

Y en el panel de Supabase, Storage → sales-reports → daily, aparece el PDF. Después borra esa línea del .env y vuelve a arrancar para dejarlo a las 00:05.

Si falla, en el log sale No se pudo archivar el resumen de ventas del ... con el error debajo.

Limitaciones

  • Solo se sube si el backend está encendido a las 00:05. En local, con el ordenador apagado esa noche, ese día no se sube.
  • No hay reintentos. Si falla una noche, queda en el log y ese día no se sube solo.
  • Si un día no hay ventas, el PDF se sube igual, con el texto "Sin ventas en el periodo".
  • El contenedor de Docker usa TZ=Europe/Madrid para que el "día anterior" sea el de España. Si arrancas el backend fuera de Docker, usa la zona horaria de tu ordenador.