const { Event, Institution, EventPlace, ContactPerson, EventType } = require('../models'); const { Op } = require('sequelize'); const moment = require('moment'); class EventService { /** * Alle Events abrufen */ async getAllEvents() { try { const events = await Event.findAll({ include: [ { model: Institution, as: 'institution' }, { model: EventPlace, as: 'eventPlace' }, { model: EventType, as: 'eventType' }, { model: ContactPerson, as: 'contactPersons', through: { attributes: [] } } ], order: ['name', 'date', 'time'] }); return events; } catch (error) { console.error('Error fetching all events:', error); throw new Error('EVENTS_FETCH_ERROR'); } } /** * Event anhand ID abrufen */ async getEventById(id) { try { if (!id || isNaN(parseInt(id))) { throw new Error('VALIDATION_ERROR: Ungültige ID'); } const event = await Event.findByPk(id, { include: [ { model: Institution, as: 'institution' }, { model: EventPlace, as: 'eventPlace' }, { model: EventType, as: 'eventType' }, { model: ContactPerson, as: 'contactPersons', through: { attributes: [] } } ] }); if (!event) { throw new Error('EVENT_NOT_FOUND'); } return event; } catch (error) { console.error('Error fetching event by ID:', error); throw new Error('EVENT_FETCH_ERROR'); } } /** * Events filtern */ async filterEvents(filterData) { try { const { id, places, types, display } = filterData; // Basis-Where-Klausel für zukünftige Events const where = { [Op.or]: [ { date: { [Op.or]: [ { [Op.gte]: moment().startOf('day').toDate() }, { [Op.eq]: null } ] } }, { dayOfWeek: { [Op.gte]: 0 } } ] }; const order = [ ['date', 'ASC'], ['time', 'ASC'] ]; // Spezielle Filter if (id === 'all') { return await this._getAllFutureEvents(where, order); } if (id === 'home') { return await this._getHomepageEvents(where, order); } if (!id && !places && !types) { return { events: [], places: [], types: [], contactPersons: [] }; } // Weitere Filter anwenden if (id) { where.id = id; } if (places && places.length > 0) { where.event_place_id = { [Op.in]: places.map(id => parseInt(id)) }; } if (types && types.length > 0) { where.eventTypeId = { [Op.in]: types.map(id => parseInt(id)) }; } const events = await Event.findAll({ where, include: [ { model: Institution, as: 'institution' }, { model: EventPlace, as: 'eventPlace' }, { model: EventType, as: 'eventType' }, { model: ContactPerson, as: 'contactPersons', through: { attributes: [] } } ], order: order, }); // Events basierend auf Display-Feldern filtern const displayFields = display || []; const filteredEvents = this._filterEventFields(events, displayFields); return { events: filteredEvents }; } catch (error) { console.error('Error filtering events:', error); throw new Error('EVENT_FILTER_ERROR'); } } /** * Event erstellen */ async createEvent(eventData) { try { const { contactPersonIds, ...eventDataWithoutContacts } = eventData; // Validierung if (!eventDataWithoutContacts.name) { throw new Error('VALIDATION_ERROR: Event-Name ist erforderlich'); } eventDataWithoutContacts.alsoOnHomepage = eventDataWithoutContacts.alsoOnHomepage ?? 0; const event = await Event.create(eventDataWithoutContacts); if (contactPersonIds && contactPersonIds.length > 0) { await event.setContactPersons(contactPersonIds); } return event; } catch (error) { console.error('Error creating event:', error); throw new Error('EVENT_CREATE_ERROR'); } } /** * Event aktualisieren */ async updateEvent(id, eventData) { try { if (!id || isNaN(parseInt(id))) { throw new Error('VALIDATION_ERROR: Ungültige ID'); } const { contactPersonIds, ...eventDataWithoutContacts } = eventData; const event = await Event.findByPk(id); if (!event) { throw new Error('EVENT_NOT_FOUND'); } await event.update(eventDataWithoutContacts); if (contactPersonIds !== undefined) { await event.setContactPersons(contactPersonIds || []); } return event; } catch (error) { console.error('Error updating event:', error); throw new Error('EVENT_UPDATE_ERROR'); } } /** * Event löschen */ async deleteEvent(id) { try { if (!id || isNaN(parseInt(id))) { throw new Error('VALIDATION_ERROR: Ungültige ID'); } const event = await Event.findByPk(id); if (!event) { throw new Error('EVENT_NOT_FOUND'); } await event.destroy(); return { message: 'Event erfolgreich gelöscht' }; } catch (error) { console.error('Error deleting event:', error); throw new Error('EVENT_DELETE_ERROR'); } } /** * Alle zukünftigen Events abrufen */ async _getAllFutureEvents(where, order) { const events = await Event.findAll({ where, include: [ { model: Institution, as: 'institution' }, { model: EventPlace, as: 'eventPlace' }, { model: EventType, as: 'eventType' }, { model: ContactPerson, as: 'contactPersons', through: { attributes: [] } } ], order: order, logging: console.log }); return { events }; } /** * Homepage Events abrufen */ async _getHomepageEvents(where, order) { const events = await Event.findAll({ where: { alsoOnHomepage: 1, date: { [Op.gte]: moment().startOf('day').toDate() } }, include: [ { model: Institution, as: 'institution' }, { model: EventPlace, as: 'eventPlace' }, { model: EventType, as: 'eventType' }, { model: ContactPerson, as: 'contactPersons', through: { attributes: [] } }, ], order: order, }); return { events }; } /** * Event-Felder basierend auf Display-Feldern filtern */ _filterEventFields(events, displayFields) { return events.map(event => { const filteredEvent = { ...event.toJSON() }; if (!displayFields.includes('name')) delete filteredEvent.name; if (!displayFields.includes('type')) delete filteredEvent.eventType; if (!displayFields.includes('place')) delete filteredEvent.eventPlace; if (!displayFields.includes('description')) delete filteredEvent.description; if (!displayFields.includes('time')) delete filteredEvent.time; if (!displayFields.includes('time')) delete filteredEvent.endTime; if (!displayFields.includes('contactPerson')) delete filteredEvent.contactPersons; if (!displayFields.includes('day')) delete filteredEvent.dayOfWeek; if (!displayFields.includes('institution')) delete filteredEvent.institution; return filteredEvent; }); } } module.exports = new EventService();