const { isAPIKeyUser } = require("../../middlewares/accessValidator"); const routes = require("express").Router(); const SchemaValidator = require("../../middlewares/schemaValidator"); const FieldMiddleware = require("../../middlewares/fields"); const authController = require("../auth/auth.controller"); const eventController = require("./event.controller"); const eventInscriptionController = require("./events_inscriptions.controller"); const eventReservationController = require("./events_reservations.controller"); const eventValidation = require("./event.validations"); const { cacheSuccesses } = require("../../middlewares/cache"); const SortMiddleware = require("../../middlewares/sort"); const entityController = require("../entities/entity.controller"); const generalInvalidFields = [ "userId", "createdAt", "updatedAt", "assistants", "confirmed", "allow_multiple", "overflow_eventId", "state", "confirmed", "multiple_limit", "marketing_list", "state", "contact_person", "contact_email", "createdAt", "updatedAt", "gmt", "url_streaming", "url_poll", "url_registration", "featured", "virtual", "allow_questions", "assistanceType", "assistanceTypeText", "sold_out", "allow_overflow", "typeId", "venueId", "locationId", ]; const eventDetailsFields = [ "id", "name", "description", "stateCode", "stateText", "campaign_text", "init_date", "end_date", ]; /** * @api {get} /web/events Obtener Eventos Disponibles * @apiName GetAvailableEvents * @apiGroup Eventos * @apiVersion 4.0.0 * @apiDescription Este endpoint devuelve una lista de eventos disponibles, incluyendo su estado de aforo. * * @apiSuccess {Object[]} events Lista de eventos disponibles. * @apiSuccess {String} events.id Identificador único del evento. * @apiSuccess {String} events.name Nombre del evento. * @apiSuccess {Object} events.location Ubicación del evento. * @apiSuccess {String} events.location.country País donde se realiza el evento. * @apiSuccess {String} events.location.city Ciudad donde se realiza el evento. * @apiSuccess {String} events.location.country_code Código del país del evento. * * @apiSuccessExample {json} Ejemplo de Respuesta: * [ * { * "id": "03f70b2d-53c5-11ed-9b36-000c29a89113", * "name": "Madrid 2022 - 16ª Edición", * "location": { * "country": "España", * "city": "Madrid", * "country_code": "ES" * }, * }, * { * "id": "b518e0f7-b2d1-11ed-9477-000c29e7c50f", * "name": "Sevilla 2023 - 22ª Edición", * "location": { * "country": "España", * "city": "Sevilla", * "country_code": "ES" * }, * } * ] */ routes.get( "/web/events/", isAPIKeyUser, FieldMiddleware.middleware({ validFields: ["id", "name"], }), (req, res, next) => { const scopes = ["defaultScope", "withOpenInscriptions"]; res.locals.v4 = {removeFields : ["partners", "speakers", "details", "multimedias", "type"]}; return eventController.find({ scopes })(req,res,next); } ); /** * @api {get} /api/v4/web/events/:eventId Obtener Datos del Evento * @apiName GetEventDetails * @apiGroup Eventos * @apiVersion 4.0.0 * @apiDescription Este endpoint devuelve los detalles de un evento específico. * * @apiParam {String} eventId Identificador único del evento. * * @apiSuccess {String} stateCode Código del estado del evento. * @apiSuccess {String} stateText Descripción del estado del evento. * @apiSuccess {String} assistanceType Tipos de asistencia disponibles (ej. "onsite, online"). * @apiSuccess {String} assistanceTypeText Descripción de los tipos de asistencia. * @apiSuccess {String} id Identificador único del evento. * @apiSuccess {String} name Nombre del evento. * @apiSuccess {String} description Descripción del evento. * @apiSuccess {String} campaign_text Texto de campaña (si aplica). * @apiSuccess {String} init_date Fecha y hora de inicio del evento (ISO 8601). * @apiSuccess {String} end_date Fecha y hora de finalización del evento (ISO 8601). * @apiSuccess {String} init_available_date Fecha de inicio de disponibilidad (ISO 8601). * @apiSuccess {String} end_available_date Fecha de fin de disponibilidad (ISO 8601). * @apiSuccess {Number} gmt Diferencia horaria en GMT. * @apiSuccess {Boolean} sold_out Indica si el evento está agotado. * @apiSuccess {Boolean} allow_overflow Indica si se permite el desbordamiento de asistentes. * @apiSuccess {String} typeId Identificador del tipo de evento. * @apiSuccess {String} venueId Identificador del lugar del evento. * @apiSuccess {String} locationId Identificador de la ubicación. * @apiSuccess {String} url_streaming URL para el streaming en vivo del evento. * @apiSuccess {String} url_poll URL para encuestas (si aplica). * @apiSuccess {String} url_registration URL para el registro (si aplica). * @apiSuccess {Boolean} featured Indica si el evento es destacado. * @apiSuccess {Boolean} virtual Indica si el evento es virtual. * @apiSuccess {Boolean} allow_questions Indica si se permiten preguntas durante el evento. * @apiSuccess {Number} assistants Número de asistentes. * @apiSuccess {Object} type Tipo del evento. * @apiSuccess {String} type.name Nombre del tipo de evento. * @apiSuccess {String} type.title Título del tipo de evento. * @apiSuccess {Object} location Ubicación del evento. * @apiSuccess {String} location.country País donde se realiza el evento. * @apiSuccess {String} location.city Ciudad donde se realiza el evento. * @apiSuccess {String} location.country_code Código del país del evento. * @apiSuccess {Object[]} multimedias Lista de recursos multimedia asociados con el evento. * @apiSuccess {Object[]} details Lista de detalles adicionales del evento. * @apiSuccess {Object[]} speakers Lista de oradores del evento. * @apiSuccess {Object[]} partners Lista de socios del evento. * * @apiSuccessExample {json} Ejemplo de Respuesta: * { * "stateCode": "registrations_open", * "stateText": "Inscripciones abiertas", * "assistanceType": "onsite, online", * "assistanceTypeText": "evento presencial y online", * "id": "03f70b2d-53c5-11ed-9b36-000c29a89113", * "name": "Madrid 2022 - 16ª Edición", * "description": "Palacio Municipal de Congresos de Madrid, Campo de las Naciones, Avenida de la Capital de España s/n\n\nENTREGA PREMIO ALGO+Q1 CANCIÓN", * "campaign_text": "", * "init_date": "2024-08-29T00:00:00.000Z", * "end_date": "2024-12-01T14:30:00.000Z", * "init_available_date": "2023-06-14T17:05:00.000Z", * "end_available_date": "2025-10-30T23:30:00.000Z", * "gmt": 1, * "sold_out": false, * "allow_overflow": false, * "typeId": "0", * "venueId": "43bae260-c0a4-4d1f-8060-e6f54b839d26", * "locationId": "9f1cc156-c8ad-11e9-b18d-000c295f0f58", * "url_streaming": "https://www.loquedeverdadimporta.org/directo/madrid/", * "url_poll": null, * "url_registration": null, * "featured": true, * "virtual": true, * "allow_questions": true, * "assistants": 2000, * "type": { * "name": "conference", * "title": "Congreso LQDVI" * }, * "location": { * "country": "España", * "city": "Madrid", * "country_code": "ES" * }, * "multimedias": [], * "details": [], * "speakers": [], * "partners": [] * } */ routes.get( "/web/events/:id", isAPIKeyUser, FieldMiddleware.middleware({ validFields: eventDetailsFields, //invalidFields: generalInvalidFields, }), (req, res, next) => { const scopes = ["defaultScope"]; res.locals.v4 = {removeFields : ["partners", "speakers", "details", "multimedias", "type"]}; return eventController.findOne({ scopes })(req, res, next); } ); /** * @api {get} /api/v4/web/events/:id/check_capacity Verificar Capacidad del Evento * @apiName CheckEventCapacity * @apiGroup Eventos * @apiVersion 1.0.0 * @apiDescription Determina si hay aforo suficiente para el tamaño de grupo que se ha indicado. * * @apiParam {String} id ID único del evento. * * @apiSuccess {String} eventId ID único del evento. * @apiSuccess {Number} group_size Tamaño del grupo para el cual se verifica el aforo. * @apiSuccess {Boolean} allow Indica si el aforo es suficiente para el grupo. * @apiSuccess {Number} assistants Número total de asistentes permitidos. * @apiSuccess {Number} confirmed Número de asistentes confirmados. * @apiSuccess {Boolean} sold_out Indica si el evento está completamente lleno. * @apiSuccess {Number} assistants_overflow Número de asistentes que sobrepasan el aforo. * @apiSuccess {Number} confirmed_overflow Número de confirmados que sobrepasan el aforo. * @apiSuccess {Boolean} sold_out_overflow Indica si se permite la asistencia en exceso. * @apiSuccess {Boolean} allow_overflow Indica si el exceso de asistentes está permitido. * * @apiSuccessExample {json} Ejemplo de Respuesta: * HTTP/1.1 200 OK * { * "eventId": "03f70b2d-53c5-11ed-9b36-000c29a89113", * "group_size": 1, * "allow": true, * "assistants": 2000, * "confirmed": 325, * "sold_out": false, * "assistants_overflow": 0, * "confirmed_overflow": 0, * "sold_out_overflow": 1, * "allow_overflow": false * } */ routes.get("/web/events/:id/check_capacity", isAPIKeyUser, eventController.checkCapacity); /** * @api {get} /api/v4/web/events/:eventId/reservations/:encodedCode Verificar Código de Invitación * @apiName CheckInvitationCode * @apiGroup Eventos * @apiVersion 4.0.0 * @apiDescription Este endpoint verifica si un código de invitación es aplicable a un evento concreto. El código de invitación está codificado en Base64. * * @apiParam {String} eventId Identificador único del evento. * @apiParam {String} encodedCode Código de invitación codificado en Base64. Ejemplo, el código "MD22-4939" se codifica como "TUQyMi00OTM5" * * @apiSuccess {Boolean} applicable Indica si el código de invitación es aplicable (true) o no (false). * * @apiSuccessExample {json} Ejemplo de Respuesta Exitosa: * HTTP/1.1 200 OK * true * * @apiSuccessExample {json} Ejemplo de Respuesta Fallida: * HTTP/1.1 200 OK * false */ routes.get( "/web/events/:id/reservations/:encodedInvitationCode", isAPIKeyUser, eventReservationController.checkReservationCode ); /** * @api {post} /api/v4/web/events/:eventId/inscriptions/ Dar de Alta una Inscripción * @apiName CreateEventInscription * @apiGroup Inscriptions * @apiVersion 1.0.0 * @apiDescription Este endpoint permite registrar una inscripción a un evento específico. * * @apiParam {String} eventId Identificador único del evento. * * @apiBody {String} code Código opcional para la inscripción. * @apiBody {String} email Email del participante, debe ser válido. * @apiBody {String} name Nombre del participante. * @apiBody {String} [surname] Apellido del participante (opcional). * * * @apiSuccess {String} stateText Estado de la inscripción. * @apiSuccess {String} id Identificador único de la inscripción. * @apiSuccess {String} eventId Identificador único del evento. * @apiSuccess {Date} date Fecha de la inscripción. * @apiSuccess {String} userId Identificador único del usuario. * @apiSuccess {String} type Tipo de asistencia. * @apiSuccess {String} code_ticket Código del ticket generado. * @apiSuccess {String} source Fuente de la inscripción (ej. "app"). * @apiSuccess {Boolean} validated Estado de validación de la inscripción. * @apiSuccess {String} [reservationId] Identificador de la reserva si existe. * @apiSuccess {String} [overflowEventId] Identificador del evento de desborde si existe. * @apiSuccess {Date} updatedAt Fecha de la última actualización. * @apiSuccess {Date} createdAt Fecha de creación. * * @apiSuccessExample {json} Ejemplo de Respuesta 1: * { * "stateText": "Inscripción confirmada", * "id": "156e4aa1-cada-4e42-bdca-b458b798991c", * "eventId": "3028d48b-1f38-11ef-9b46-000c29a89113", * "date": "2024-07-02T09:30:07.973Z", * "userId": "6747d9eb-c64f-43a3-a4ac-6803b89966cb", * "type": "onsite", * "code_ticket": "ENT-77760177", * "source": "app", * "validated": true, * "reservationId": null, * "overflowEventId": null, * "updatedAt": "2024-07-02T09:30:07.974Z", * "createdAt": "2024-07-02T09:30:07.974Z" * } * * @apiSuccessExample {json} Ejemplo de Respuesta 2: * { * "reservation": { * "assistanceType": "onsite", * "assistanceTypeText": "asistencia presencial", * "stateText": "Inscripciones abiertas a la reserva", * "id": "b996c360-616d-46d4-856f-4dc0449b74f8", * "init_available_date": "2024-06-03T15:00:00.000Z", * "end_available_date": "2024-10-08T20:00:00.000Z", * "gmt": -5, * "state": "publish", * "assistants": 10, * "confirmed": 1, * "sold_out": false, * "allow_multiple": false, * "multiple_limit": 0, * "description": "Reserva", * "reservation_code": "TOL24-CIE339", * "color": "orange", * "allow_overflow": false, * "overflow_reservationId": null, * "marketing_list": null, * "virtual": false, * "createdAt": "2024-07-02T09:39:38.000Z", * "updatedAt": "2024-07-02T09:40:07.000Z", * "userId": "d3eba5de-76cd-44a0-9ebd-92cad7160e71", * "entityId": "9c910423-596b-11ea-bdd2-000c29a89113", * "eventId": "3028d48b-1f38-11ef-9b46-000c29a89113", * "Event": { * "stateCode": "registrations_open", * "stateText": "Inscripciones abiertas", * "assistanceType": "onsite", * "assistanceTypeText": "evento presencial", * "id": "3028d48b-1f38-11ef-9b46-000c29a89113", * "name": "Toluca 2024 - Teen - 6ª Edición", * "description": null, * "campaign_text": null, * "init_date": "2024-10-09T15:00:00.000Z", * "end_date": "2024-10-09T19:00:00.000Z", * "init_available_date": "2024-06-03T15:00:00.000Z", * "end_available_date": "2024-10-08T20:00:00.000Z", * "gmt": -5, * "assistants": 620, * "confirmed": 1, * "sold_out": false, * "allow_multiple": false, * "multiple_limit": null, * "allow_overflow": true, * "overflow_eventId": "36a1aed0-1f39-11ef-9b46-000c29a89113", * "state": "publish", * "typeId": "0", * "venueId": "2481e357-1dfb-4ab7-ba2b-5094620e0281", * "locationId": "df971e1c-c8de-11e9-b18d-000c295f0f58", * "url_streaming": null, * "url_poll": null, * "url_registration": null, * "marketing_list": null, * "userId": "0939bb2a-d33d-4290-ac81-fc9faa1c015e", * "featured": false, * "virtual": false, * "allow_questions": true, * "createdAt": "2024-05-31T12:26:05.000Z", * "updatedAt": "2024-07-02T09:40:07.000Z", * "type": { * "name": "conference", * "title": "Congreso LQDVI" * }, * "location": { * "country": "México", * "city": "Toluca", * "country_code": "MX" * } * }, * "Entity": { * "id": "9c910423-596b-11ea-bdd2-000c29a89113", * "name": "CIEMA A Coruña", * "state": "publish", * "contact_person": null, * "contact_email": null, * "level": null, * "country": "ES", * "createdAt": "2020-02-27T15:15:31.000Z", * "updatedAt": "2020-02-27T15:15:31.000Z" * } * }, * "stateText": "Inscripción confirmada", * "id": "2168615f-69b3-4045-a173-5b70f5ebfd1d", * "eventId": "3028d48b-1f38-11ef-9b46-000c29a89113", * "date": "2024-07-02T09:42:34.846Z", * "userId": "6747d9eb-c64f-43a3-a4ac-6803b89966cb", * "type": "onsite group", * "code_ticket": "ENT-31846388", * "source": "app", * "validated": true, * "reservationId": "b996c360-616d-46d4-856f-4dc0449b74f8", * "overflowEventId": null, * "updatedAt": "2024-07-02T09:42:34.847Z", * "createdAt": "2024-07-02T09:42:34.847Z" * } * * @apiSuccessExample {json} Ejemplo de Respuesta 3: * { * "stateText": "Inscripción confirmada a lista de espera", * "id": "9c6548df-37d8-46c1-8505-3de9e620fab1", * "eventId": "3028d48b-1f38-11ef-9b46-000c29a89113", * "date": "2024-07-02T09:32:45.727Z", * "userId": "6747d9eb-c64f-43a3-a4ac-6803b89966cb", * "type": "onsite", * "code_ticket": "ENT-26677167", * "source": "app", * "validated": false, * "reservationId": null, * "overflowEventId": "36a1aed0-1f39-11ef-9b46-000c29a89113", * "updatedAt": "2024-07-02T09:32:45.728Z", * "createdAt": "2024-07-02T09:32:45.728Z" * } */ routes.post( "/web/events/:id/inscriptions", isAPIKeyUser, SchemaValidator(eventValidation.InscriptionInputType, true), //Prepara los datos de la inscripción tipo .... eventInscriptionController.prepareDataInscription, //Recupera la reservation si viene eventReservationController.recuperateReservationByCode, //Recupera a registra el usuario que se va a inscribir authController.getOrCreateUser, //Comprobamos si tiene ya una incripción, en tal caso, comprobamos el código de reserva sea el de la inscripcion hecha, //si no es así es el caso de un usuario que se reinscribe con otro código de reserva eventInscriptionController.checkInscriptionByUser, //Si es un usuario tutor y solicita un group_size se crea la reserva eventReservationController.createReservationToEntity, eventReservationController.activeReservationToEntity, (req, res, next) => { if (res.locals.dataInscription.reservation) { console.log(">>>>>>>Incripcion con reserva"); eventReservationController.createInscriptionReservation(req, res, next); } else { console.log(">>>>>>>Incripcion sin reserva"); eventInscriptionController.createInscription(req, res, next); } //next(); } // eventInscriptionController.createInscriptionMarketingList ); /** * @api {get} /api/v4/web/entities/colleges Lista de Entidades Educativas * @apiName GetColleges * @apiGroup Entidades * @apiVersion 1.0.0 * @apiDescription Este endpoint devuelve una lista de entidades educativas, incluyendo su nombre, nivel y país. * * @apiSuccess {Object[]} colleges Lista de entidades educativas. * @apiSuccess {String} colleges.id Identificador único de la entidad educativa. * @apiSuccess {String} colleges.name Nombre de la entidad educativa. * @apiSuccess {String} [colleges.level] Nivel educativo (si aplica). * @apiSuccess {String} colleges.country Código de país de la entidad educativa. * * @apiSuccessExample {json} Ejemplo de Respuesta: * [ * { * "id": "757de756-af85-11e9-aa90-000c295f0f58", * "name": "Academia Santa Teresa Málaga", * "level": null, * "country": "ES" * }, * { * "id": "7583028a-af85-11e9-aa90-000c295f0f58", * "name": "Academia Díaz Balaguer", * "level": null, * "country": "ES" * }, * { * "id": "54a4fa2d-48b4-11ee-9b36-000c29a89113", * "name": "AECC reservas", * "level": null, * "country": "ES" * }, * { * "id": "758137a3-af85-11e9-aa90-000c295f0f58", * "name": "Aeroclub de Colombia", * "level": null, * "country": "ES" * }, * { * "id": "75835f07-af85-11e9-aa90-000c295f0f58", * "name": "AFA Formación Oviedo", * "level": null, * "country": "ES" * }, * { * "id": "758196a7-af85-11e9-aa90-000c295f0f58", * "name": "Agora Portals International School - Islas Baleares", * "level": null, * "country": "ES" * }, * { * "id": "75843763-af85-11e9-aa90-000c295f0f58", * "name": "AIS Mallorca", * "level": null, * "country": "ES" * }, * { * "id": "758314a0-af85-11e9-aa90-000c295f0f58", * "name": "Alcalá de Henares", * "level": null, * "country": "ES" * }, * { * "id": "75810f5a-af85-11e9-aa90-000c295f0f58", * "name": "Alcaste - Las Fuentes", * "level": null, * "country": "ES" * }, * { * "id": "6a574ca3-9ece-11ec-9700-000c29a89113", * "name": "Alfaem Salud Mental - León", * "level": null, * "country": "ES" * }, * { * "id": "75810989-af85-11e9-aa90-000c295f0f58", * "name": "Alfonso Escamez", * "level": null, * "country": "ES" * }, * { * "id": "a015dcef-8213-11ee-9b36-000c29a89113", * "name": "Alianza para la FP Dual - Barcelona", * "level": null, * "country": "ES" * }, * { * "id": "7583dd6d-af85-11e9-aa90-000c295f0f58", * "name": "AMA-CLUB DE AMIGOS ALCORCÓN", * "level": null, * "country": "ES" * } * ] */ routes.get( "/web/entities/colleges", isAPIKeyUser, cacheSuccesses("24 hours"), FieldMiddleware.middleware({ invalidFields: generalInvalidFields, }), SortMiddleware.middleware({ default: "name" }), entityController.find({ scopes: ["defaultScope", "onlyColleges"], }) ); /** * @api {get} /api/v4/web/entities/partners Lista de Partners * @apiName GetPartners * @apiGroup Partners * @apiVersion 4.0.0 * @apiDescription Este endpoint devuelve una lista de partners disponibles, incluyendo su nombre, nivel y país. * * @apiSuccess {Object[]} partners Lista de partners disponibles. * @apiSuccess {String} partners.id Identificador único del partner. * @apiSuccess {String} partners.name Nombre del partner. * @apiSuccess {String} [partners.level] Nivel del partner (puede ser nulo). * @apiSuccess {String} partners.country Código del país del partner. * * @apiSuccessExample {json} Ejemplo de Respuesta: * [ * { "id": "7dfc4513-ce5b-11e9-8055-000c29a89113", "name": "ABC", "level": null, "country": "ES" }, { "id": "3c7950ac-48b4-11ee-9b36-000c29a89113", "name": "AECC", "level": null, "country": "ES" }, { "id": "2b43d32b-d4d1-11e9-8055-000c29a89113", "name": "AGR FOOD MARKETING", "level": null, "country": "ES" }, { "id": "aa0cf064-ce5b-11e9-8055-000c29a89113", "name": "ANTONIO PAMPLIEGA", "level": null, "country": "ES" }, { "id": "6c2df6c3-af83-11e9-aa90-000c295f0f58", "name": "ANTONIO PINTOR", "level": null, "country": "ES" }, { "id": "5e5472b3-6e60-11ee-9b36-000c29a89113", "name": "Atrápalo", "level": null, "country": "ES" }, { "id": "df469bb0-fa63-11e9-8055-000c29a89113", "name": "AYTO. BILBAO", "level": null, "country": "ES" }, { "id": "b37764ca-98bc-11ec-9700-000c29a89113", "name": "AYTO. LA CORUÑA", "level": null, "country": "ES" }, { "id": "757f1b60-af85-11e9-aa90-000c295f0f58", "name": "AYTO. MADRID", "level": null, "country": "ES" }, { "id": "9a2f1e6f-d954-11e9-8055-000c29a89113", "name": "AYTO. MÁLAGA", "level": null, "country": "ES" }, { "id": "bddfa9e9-ef85-11e9-8055-000c29a89113", "name": "AYTO. OVIEDO", "level": null, "country": "ES" }, { "id": "29762a98-ce5b-11e9-8055-000c29a89113", "name": "AYTO. SEVILLA", "level": null, "country": "ES" }, { "id": "414c97c6-5274-11ea-bdd2-000c29a89113", "name": "BARCELÓ GRANADA", "level": null, "country": "ES" }, { "id": "03caafb0-5270-11ea-bdd2-000c29a89113", "name": "BIDAFARMA", "level": null, "country": "ES" }, { "id": "db2e5387-2111-11ec-9c03-000c29a89113", "name": "BYG", "level": null, "country": "ES" }, { "id": "2f2c58ac-e11d-11e9-8055-000c29a89113", "name": "CABALLITO DE MAR", "level": null, "country": "ES" }, { "id": "59e03089-a379-11ec-9b36-000c29a89113", "name": "Cabildo Insular de La Gomera - Area Educación", "level": null, "country": "ES" }, { "id": "6c2df93f-af83-11e9-aa90-000c295f0f58", "name": "CAIXABANK", "level": null, "country": "ES" }, * ... * ] */ routes.get( "/web/entities/partners", isAPIKeyUser, cacheSuccesses("24 hours"), FieldMiddleware.middleware({ invalidFields: generalInvalidFields, }), SortMiddleware.middleware({ default: "name" }), entityController.find({ scopes: ["defaultScope", "onlyPartners"], }) ); module.exports = routes;