import { Body, Controller, Get, Param, Patch, Post, Query, Req, Res, UseGuards, } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { Response } from 'express'; import { WahlService } from './wahl.service'; import { ZuteilungService } from './zuteilung.service'; import { CreateWahlDto } from './dto/create-wahl.dto'; import { UpdateWahlDto } from './dto/update-wahl.dto'; import { CreateWorkshopDto } from './dto/create-workshop.dto'; import { SubmitTeilnehmerDto } from './dto/submit-teilnehmer.dto'; import { CreateForceZuteilungDto } from './dto/create-force-zuteilung.dto'; import { Roles } from '../common/roles.decorator'; import { RolesGuard } from '../common/roles.guard'; import { Role } from '../common/role.enum'; import { GuestAuthenticatedRequest } from '../auth/authenticated-request'; @Controller('wahl') export class WahlController { constructor( private readonly wahl: WahlService, private readonly zuteilung: ZuteilungService, ) {} /// Wahl-/Workshop-/Force-Zuteilung-Verwaltung ist ausschließlich Sache des /// Leitungsteams (global über alle KCs, siehe RolesGuard). @Post() @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) createWahl(@Body() dto: CreateWahlDto) { return this.wahl.createWahl(dto.kcId, dto.name, dto.datumsSchluessel, dto.teil); } @Get() @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) listWahlen(@Query('kcId') kcId: string) { return this.wahl.listWahlen(kcId); } @Patch(':wahlId') @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) updateWahl(@Param('wahlId') wahlId: string, @Body() dto: UpdateWahlDto) { return this.wahl.updateWahl(wahlId, { isOpen: dto.isOpen }); } @Get(':wahlId/teilnehmer') @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) listTeilnehmer(@Param('wahlId') wahlId: string) { return this.wahl.listTeilnehmer(wahlId); } @Post(':wahlId/workshops') @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) createWorkshop(@Param('wahlId') wahlId: string, @Body() dto: CreateWorkshopDto) { return this.wahl.createWorkshop(wahlId, dto.name, dto.kapazitaet, dto.minTeilnehmer); } @Get(':wahlId/workshops') @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) listWorkshops(@Param('wahlId') wahlId: string) { return this.wahl.listWorkshops(wahlId); } @Post(':wahlId/force-zuteilung') @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) createForceZuteilung( @Param('wahlId') wahlId: string, @Body() dto: CreateForceZuteilungDto, ) { return this.wahl.createForceZuteilung(wahlId, dto.teilnehmerId, dto.workshopId); } /// Everything a guest needs to fill in the Wahl: open Wahlen for their KC, /// each with its workshops and the guest's own current priorities (if any). @Get('guest/overview') @UseGuards(AuthGuard('guest')) guestOverview(@Req() req: GuestAuthenticatedRequest) { const guest = req.user!; return this.wahl.guestOverview(guest.kcId, guest.guestId); } /// The guest's own assignment result per Wahl they took part in. @Get('guest/results') @UseGuards(AuthGuard('guest')) guestResults(@Req() req: GuestAuthenticatedRequest) { const guest = req.user!; return this.wahl.guestResults(guest.kcId, guest.guestId); } /// Guests submit their own workshop preferences (guest JWT, not Authentik). @Post(':wahlId/teilnehmer') @UseGuards(AuthGuard('guest')) submitTeilnehmer( @Param('wahlId') wahlId: string, @Body() dto: SubmitTeilnehmerDto, @Req() req: GuestAuthenticatedRequest, ) { const guest = req.user!; return this.wahl.submitTeilnehmer(wahlId, guest.guestId, guest.kcId, dto.prioritaeten); } @Post(':wahlId/zuteilung/run') @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) runZuteilung(@Param('wahlId') wahlId: string) { return this.zuteilung.run(wahlId); } @Get(':wahlId/zuteilung') @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) getZuteilung(@Param('wahlId') wahlId: string) { return this.zuteilung.getResults(wahlId); } @Get(':wahlId/zuteilung/csv') @UseGuards(AuthGuard(['authentik', 'team']), RolesGuard) @Roles(Role.LEITUNGSTEAM) async exportCsv(@Param('wahlId') wahlId: string, @Res() res: Response) { const csv = await this.zuteilung.exportCsv(wahlId); res.setHeader('Content-Type', 'text/csv; charset=utf-8'); res.setHeader('Content-Disposition', `attachment; filename="zuteilung-${wahlId}.csv"`); res.send(csv); } }