# Review package: ae5ec76..3666b9d ## Commits 3666b9d PDF: endpoint stato/download/trigger ## Files changed app/src/routes/api/dvr/[id]/pdf/+server.ts | 66 ++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) ## Diff diff --git a/app/src/routes/api/dvr/[id]/pdf/+server.ts b/app/src/routes/api/dvr/[id]/pdf/+server.ts new file mode 100644 index 0000000..7aadbac --- /dev/null +++ b/app/src/routes/api/dvr/[id]/pdf/+server.ts @@ -0,0 +1,66 @@ +/** + * Endpoint stato / download / trigger per la generazione del PDF di un DVR. + * + * GET ?mode=status → 200 { state, generatoIl } + * GET → stream del PDF da R2 se ready (o stale con ?allowStale=1), altrimenti 409 { state } + * POST → innesca la generazione (se non già in corso); 202 { state: 'generating' } + */ +import { error, json } from '@sveltejs/kit'; +import { db } from '$lib/server/db'; +import { agenzie } from '$lib/server/db/schema'; +import { eq } from 'drizzle-orm'; +import { getPdfStatus, markGenerating } from '$lib/server/pdf/state'; +import { triggerPdfGeneration } from '$lib/server/pdf/dispatch'; +import { getObject } from '$lib/server/r2'; + +export const GET = async ({ params, url }) => { + const id = parseInt(params.id, 10); + if (Number.isNaN(id)) throw error(400, 'ID non valido'); + + const status = await getPdfStatus(id); + + if (url.searchParams.get('mode') === 'status') { + return json({ state: status.state, generatoIl: status.generatoIl }); + } + + // Download: ready sempre ok; stale ok solo con ?allowStale=1 e se esiste un r2Key + const allowStale = url.searchParams.get('allowStale') === '1'; + const canServe = + status.state === 'ready' || (allowStale && status.state === 'stale' && status.r2Key !== null); + + if (!canServe || !status.r2Key) { + return json({ state: status.state }, { status: 409 }); + } + + const [agenzia] = await db + .select({ codiceFisico: agenzie.codiceFisico }) + .from(agenzie) + .where(eq(agenzie.id, id)); + + const obj = await getObject(status.r2Key); + if (!obj) return json({ state: 'missing' }, { status: 409 }); + + const filename = `${agenzia?.codiceFisico ?? 'dvr'}_DVR.pdf`; + return new Response(obj.body, { + headers: { + 'Content-Type': 'application/pdf', + 'Content-Disposition': `attachment; filename="${filename}"` + } + }); +}; + +export const POST = async ({ params }) => { + const id = parseInt(params.id, 10); + if (Number.isNaN(id)) throw error(400, 'ID non valido'); + + const status = await getPdfStatus(id); + + // Niente doppio trigger: se già in corso restituisce 202 senza ri-schedulare + if (status.state === 'generating') { + return json({ state: 'generating' }, { status: 202 }); + } + + await markGenerating(id, status.currentHash); + await triggerPdfGeneration(id); + return json({ state: 'generating' }, { status: 202 }); +};