diff --git a/apps/api/src/routes/exports/photos.archive.ts b/apps/api/src/routes/exports/photos.archive.ts index e5d22e82..818375ab 100644 --- a/apps/api/src/routes/exports/photos.archive.ts +++ b/apps/api/src/routes/exports/photos.archive.ts @@ -6,7 +6,6 @@ import archiver from 'archiver' import type { Context } from 'hono' import { stream } from 'hono/streaming' import mime from 'mime' -import { Readable } from 'node:stream' import { z } from 'zod' import prisma from '../../prisma.js' import { openFileStream } from '../../services/file/helpers/getFileUrl.js' @@ -119,54 +118,67 @@ export async function veranstaltungPhotoArchive(ctx: Context<{ Variables: Author const zip = archiver('zip') - zip.on('warning', function (err) { - if (err.code === 'ENOENT') { - console.warn(err) - } else { - throw err - } - }) - - zip.on('error', function (err) { - throw err - }) - ctx.status(201) ctx.header('Content-Type', 'application/zip') ctx.header('Content-Disposition', `attachment; filename="${mode === 'flat' ? 'FotosForAutomation' : 'Fotos'}.zip"`) zip.append(`Gesamtzahl Fotos: ${anmeldungen.length}`, { name: `${baseDirectory}/README.txt` }) - for (const { person, unterveranstaltung } of anmeldungen) { - if (!person.photo) { - continue - } + return stream(ctx, async (s) => { + zip.on('data', (chunk) => { + /* eslint-disable @typescript-eslint/no-floating-promises */ + s.write(chunk) + }) - const stream = await openFileStream(person.photo) + for (const { person, unterveranstaltung } of anmeldungen) { + if (!person.photo) { + continue + } - const directory = `${unterveranstaltung.veranstaltung.name}/${unterveranstaltung.gliederung.name}` - const basename = mode === 'group' ? `${person.firstname} ${person.lastname}` : person.id - const extension = mime.getExtension(person.photo.mimetype ?? 'text/plain') + const stream = await openFileStream(person.photo) - zip.append(stream, { - name: - mode === 'group' - ? `${baseDirectory}/${directory}/${basename}.${extension}` - : `Fotos/${person.photo.id}.${extension}`, - date: person.photo.createdAt, - }) - } + stream.on('end', () => { + stream.destroy() + }) - if (mode === 'flat') { - const buffer = buildSheet(anmeldungen, account.person) - zip.append(buffer, { - name: 'Datenzusammenführung.xlsx', - }) - } + const directory = `${unterveranstaltung.veranstaltung.name}/${unterveranstaltung.gliederung.name}` + const basename = mode === 'group' ? `${person.firstname} ${person.lastname}` : person.id + const extension = mime.getExtension(person.photo.mimetype ?? 'text/plain') + + zip.append(stream, { + name: + mode === 'group' + ? `${baseDirectory}/${directory}/${basename}.${extension}` + : `Fotos/${person.photo.id}.${extension}`, + date: person.photo.createdAt, + }) + } - await zip.finalize() + if (mode === 'flat') { + const buffer = buildSheet(anmeldungen, account.person) + zip.append(buffer, { + name: 'Datenzusammenführung.xlsx', + }) + } - return stream(ctx, async (s) => { - await s.pipe(Readable.toWeb(zip)) + /* eslint-disable @typescript-eslint/no-floating-promises */ + zip.finalize() + + await new Promise((resolve, reject) => { + zip.on('warning', function (err) { + if (err.code === 'ENOENT') { + console.warn(err) + } else { + reject(err) + } + }) + + zip.once('end', () => { + resolve() + }) + zip.once('error', (err) => { + reject(err) + }) + }) }) } diff --git a/apps/api/src/routes/exports/teilnehmendenliste.sheet.ts b/apps/api/src/routes/exports/teilnehmendenliste.sheet.ts index f7465cea..6bb909ac 100644 --- a/apps/api/src/routes/exports/teilnehmendenliste.sheet.ts +++ b/apps/api/src/routes/exports/teilnehmendenliste.sheet.ts @@ -24,7 +24,6 @@ export async function veranstaltungTeilnehmendenliste(ctx: Context<{ Variables: unterveranstaltung: { gliederungId: gliederung?.id, }, - status: 'BESTAETIGT', }, select: { id: true, @@ -114,8 +113,7 @@ export async function veranstaltungTeilnehmendenliste(ctx: Context<{ Variables: '#': anmeldung.id, Veranstaltung: anmeldung.unterveranstaltung.veranstaltung.name, - Ausschreibung: - anmeldung.unterveranstaltung.beschreibung?.substring(0, 30) || anmeldung.unterveranstaltung.gliederung.name, + Ausschreibung: anmeldung.unterveranstaltung.gliederung.name, 'Art der Ausschreibung': anmeldung.unterveranstaltung.type, Status: AnmeldungStatusMapping[anmeldung.status].human, diff --git a/apps/api/src/services/unterveranstaltung/unterveranstaltungList.ts b/apps/api/src/services/unterveranstaltung/unterveranstaltungList.ts index 15822465..79423f29 100644 --- a/apps/api/src/services/unterveranstaltung/unterveranstaltungList.ts +++ b/apps/api/src/services/unterveranstaltung/unterveranstaltungList.ts @@ -102,11 +102,7 @@ export const unterveranstaltungListProcedure = defineProtectedQueryProcedure({ }, _count: { select: { - Anmeldung: { - where: { - status: 'BESTAETIGT', - }, - }, + Anmeldung: true, }, }, meldebeginn: true, diff --git a/apps/frontend/src/views/Anmeldung/AnmeldungFormGeneral.vue b/apps/frontend/src/views/Anmeldung/AnmeldungFormGeneral.vue index 20fda7b4..aa371f99 100644 --- a/apps/frontend/src/views/Anmeldung/AnmeldungFormGeneral.vue +++ b/apps/frontend/src/views/Anmeldung/AnmeldungFormGeneral.vue @@ -1,7 +1,7 @@