import express, {Request, Response} from 'express'; import * as EventsAdminService from './events.admin.service.js'; import {sendServerError} from '../tickets.errors.js'; export const eventsAdminRouter = express.Router(); /** * @swagger * /tickets/admin/events: * get: * summary: List concerts for the admin event picker * description: Wraps the Calendar module's public-calendar admin listing (includes DRAFT events). * tags: [tickets-admin] * parameters: * - $ref: '#/components/parameters/SessionIdHeader' * - $ref: '#/components/parameters/SessionKeyHeader' * responses: * 200: * description: Success * 401: * description: Unauthorized */ eventsAdminRouter.get('/', async (req: Request, res: Response) => { try { res.status(200).send(await EventsAdminService.listEventsForPicker()); } catch (e: any) { sendServerError(res, e); } }); /** * @swagger * /tickets/admin/events/available: * get: * summary: List public-calendar events not yet added to the ticket shop * description: Source list for the "add a concert" picker - the public calendar holds more than concerts, so events only appear in the ticket shop once explicitly added. * tags: [tickets-admin] * parameters: * - $ref: '#/components/parameters/SessionIdHeader' * - $ref: '#/components/parameters/SessionKeyHeader' * responses: * 200: * description: Success * 401: * description: Unauthorized */ eventsAdminRouter.get('/available', async (req: Request, res: Response) => { try { res.status(200).send(await EventsAdminService.listAvailableEventsToAdd()); } catch (e: any) { sendServerError(res, e); } }); /** * @swagger * /tickets/admin/events/{eventId}/stats: * get: * summary: Get a concert's voucher/capacity stats * tags: [tickets-admin] * parameters: * - $ref: '#/components/parameters/SessionIdHeader' * - $ref: '#/components/parameters/SessionKeyHeader' * - in: path * name: eventId * required: true * schema: * type: integer * responses: * 200: * description: Success * content: * application/json: * schema: * $ref: '#/components/schemas/EventStats' * 401: * description: Unauthorized */ eventsAdminRouter.get('/:eventId/stats', async (req: Request, res: Response) => { try { res.status(200).send(await EventsAdminService.getEventStats(Number(req.params.eventId))); } catch (e: any) { sendServerError(res, e); } }); /** * @swagger * /tickets/admin/events/{eventId}/settings: * put: * summary: Set a concert's voucher settings * description: Upserts capacity (null = uncapped), redemption deadline (null = none), and whether to collect a mailing address. * tags: [tickets-admin] * parameters: * - $ref: '#/components/parameters/SessionIdHeader' * - $ref: '#/components/parameters/SessionKeyHeader' * - in: path * name: eventId * required: true * schema: * type: integer * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * capacity: * type: integer * nullable: true * redemptionDeadline: * type: string * format: date-time * nullable: true * collectAddress: * type: boolean * requireAddress: * type: boolean * description: Only meaningful when collectAddress is true. * responses: * 200: * description: Saved * 401: * description: Unauthorized */ eventsAdminRouter.put('/:eventId/settings', async (req: Request, res: Response) => { try { const {capacity, redemptionDeadline, collectAddress, requireAddress} = req.body || {}; await EventsAdminService.setEventSettings(Number(req.params.eventId), { capacity: capacity ?? null, // The mariadb driver needs an actual Date to serialize a DATETIME // column correctly - a raw ISO string (as arrives over JSON) gets // rejected with "Incorrect datetime value". redemptionDeadline: redemptionDeadline ? new Date(redemptionDeadline) : null, collectAddress: !!collectAddress, requireAddress: !!collectAddress && !!requireAddress }); res.status(200).send({status: 'OK'}); } catch (e: any) { sendServerError(res, e); } }); /** * @swagger * /tickets/admin/events/{eventId}/settings: * delete: * summary: Remove an event from the ticket shop * description: Deletes its settings row, so it drops out of the picker and reappears in the "add" list. Refused with 409 if vouchers already reference the event - existing vouchers/redemptions stay valid either way. * tags: [tickets-admin] * parameters: * - $ref: '#/components/parameters/SessionIdHeader' * - $ref: '#/components/parameters/SessionKeyHeader' * - in: path * name: eventId * required: true * schema: * type: integer * responses: * 200: * description: Removed * 409: * description: Vouchers already reference this event * 401: * description: Unauthorized */ eventsAdminRouter.delete('/:eventId/settings', async (req: Request, res: Response) => { try { const result = await EventsAdminService.removeEvent(Number(req.params.eventId)); if (result === 'HAS_VOUCHERS') { res.status(409).send({status: 'HAS_VOUCHERS', message: 'Für dieses Konzert existieren bereits Gutscheine.'}); return; } res.status(200).send({status: 'OK'}); } catch (e: any) { sendServerError(res, e); } });