"use strict"; const httpStatus = require("http-status"); const generateControllers = require("../../core/controllers"); const eventInscriptionService = require("./events_inscriptions.service"); const eventReservationService = require("./events_reservations.service"); const eventService = require("./event.service"); const mailService = require("./mail.service"); const marketingListService = require("./marketing_list.service"); const QRHelper = require("../../helpers/qr.helper"); const { extractParamsFromRequest, handleResultResponse, handleErrorResponse, } = require("../../helpers/controller.helper"); const { data } = require("../../core/logger"); const lodash = require("lodash"); const userService = require("../auth/user.service"); // Module Name const MODULE_NAME = "[eventInscription.controller]"; const controllerOptions = { MODULE_NAME }; async function refreshConfirmed(inscription) { if (!inscription) { throw new Error("Error al eliminar inscripción, no puedo cambiar confirmados a la reserva asociada"); } if (inscription.type === "online") return true; //En caso de inscripciones const EventOrReservationChangeId = inscription.reservationId ? inscription.reservationId : inscription.overflowEventId ? inscription.overflowEventId : inscription.eventId; let NewConfirmed = 0; //Si la inscripción viene por una reserva modificamos los confirmados de la reserva if (inscription.reservationId != null) { console.log("Tengo reservation>>>>>>>>>>>>>>>>>>", inscription.reservationId); NewConfirmed = await eventInscriptionService._getCountInscriptionsWithReservation(EventOrReservationChangeId); //No se tienen en cuenta los marketinglist de las otras estructuras si lo tuviera seria esto // marketingListId = (await eventReservationService._getReservaById(EventOrReservationChangeId)) // .marketing_list; //Inscripcion de lista de espera bien de reserva o de evento de lista de espera } else if (inscription.overflowEventId != null) { console.log("Tengo overflow>>>>>>>>>>>>>>>>>>", inscription.overflowEventId); NewConfirmed = await eventInscriptionService._getCountInscriptionsWithOverflowEventId(EventOrReservationChangeId); //No se tienen en cuenta los marketinglist de las otras estructuras si lo tuviera seria esto /// marketingListId = (await eventService._getEvent(EventOrReservationChangeId)).marketing_list; //Inscripción al evento (ni reserva ni lista de espera) } else if (inscription.eventId != null) { NewConfirmed = await eventInscriptionService._getCountInscriptionsWithoutReservationAndOverflow( EventOrReservationChangeId ); //No se tienen en cuenta los marketinglist de las otras estructuras si lo tuviera seria esto //marketingListId = (await eventService._getEvent(EventOrReservationChangeId)).marketing_list; } //Actualizamos aforo del evento o de la reserva if (inscription.reservationId != null) { console.log(">>>>>>>>>>>>>>Voy a actualizar aforo reserva", EventOrReservationChangeId); console.log(">>>>>>>>>>>>>> ", NewConfirmed); if (!(await eventReservationService._updateConfirmedReservation(EventOrReservationChangeId, NewConfirmed))) { throw new Error("Error al eliminar inscripción, no puedo cambiar confirmados a la reserva asociada"); } } else { console.log(">>>>>>>>>>>>>>Voy a actualizar aforo evento", EventOrReservationChangeId); console.log(">>>>>>>>>>>>>> ", NewConfirmed); if (!(await eventService._updateConfirmedEvent(EventOrReservationChangeId, NewConfirmed))) { throw new Error("Error al eliminar inscripción, no puedo cambiar confirmados a la inscripcion"); } } } const extraControllers = { /////////////////////////////////////////////////////////////////// //Prepara la estructura de datos para el registro de inscripciones /////////////////////////////////////////////////////////////////// prepareDataInscription: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); //Si no viene type es porque es una inscripción con la app antigua y el valor por defecto es onsite let typeInscription = "onsite"; if (req.body.type && req.body.type === "online") typeInscription = "online"; //Si viene code es la appa antigua o la nueva if ((req.body.code && req.body.code !== "") || (req.body.group_size && req.body.group_size > 1)) typeInscription = typeInscription + " group"; let dataInscription = { eventId: params.params.id, reservationCode: req.user ? req.body.code.trim() : Buffer.from(req.body.code, "base64").toString("ascii").trim(), //quitamos espacios por si nos lo manda así el formulario para evitar errores. type: typeInscription, groupSize: req.body.group_size ? req.body.group_size : 1, //Si no viene group_size será uno porque es una inscripcion de la APP antigua source: req.user ? (lodash.isEmpty(req.user) ? "web4V" : "app") : "web", //En el caso de tener ya usuario, si es vacio viene de formulario WEBV4, si no por la APP, y en caso de no tener user el formulario web actual validated: false, //si no esta validado la inscripción es a la lista de espera inscriptionsWithoutReservationAndOverflowCount: null, //nº total de inscritos sin reserva y sin overflow asignada inscriptionsWithReservationCount: null, //nº total de inscritos a la reserva asignada event: null, reservation: null, inscription: null, }; try { dataInscription.event = await eventService._getEvent(dataInscription.eventId); if (dataInscription.event) { dataInscription.event = await dataInscription.event.toJSON(); } else { // No se ha encontrado return handleResultResponse("Evento no encontrado", null, params, res, httpStatus.NOT_FOUND); } } catch (error) { return handleErrorResponse(MODULE_NAME, "encontrado", error, res); } res.locals.dataInscription = dataInscription; console.log(">>>>>>>>>>>>>>>>>>>> prepareDataInscription", dataInscription.type); next(); }, //////////////////////////////////////////////////////////////////////////////// //Esta función comprueba si el usuario ya tiene una inscripción para el evento //si es así se comprueba que no quiera cambiar de codigo de reserva y se actualiza //////////////////////////////////////////////////////////////////////////////// checkInscriptionByUser: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); let dataInscription = res.locals.dataInscription; if (!dataInscription || !dataInscription.event) return handleResultResponse( "Error checkInscriptionByUser, prepareDataInscription requerida", null, params, res, httpStatus.NOT_FOUND ); let dataUser = res.locals.dataUser; if (!dataUser) return handleResultResponse( "Error checkInscriptionByUser, prepareDataInscription, getOrCreateUser requerida", null, params, res, httpStatus.NOT_FOUND ); try { //Comprobamos que el usuario no tenga ya inscripcion para ese evento dataInscription.inscription = await eventInscriptionService._getInscriptionByEventAndUser( dataInscription.event.id, dataUser.userResult.user.id ); if (dataInscription.inscription) { console.log("esta es la inscripcion que ya tengo>>>>", dataInscription.inscription); //Si la inscripcion no tiene reserva o la tiene y es la misma de la insripcion devuelvo la inscripcion if ( !dataInscription.inscription.reservationId || (dataInscription.reservation && dataInscription.inscription.reservationId == dataInscription.reservation.id) ) return handleResultResponse(dataInscription.inscription, null, params, res, httpStatus.OK); //En caso contrario devuelvo la plaza a la reserva que tenia la inscripción anterior y apunto la inscripción a la nueva reserva //ACTUALIZAMOS LA RESERVA DE LA INSCRIPCION CON LA NUEVA Y CAMBIAMOS COMFIRMADOS DEVOLVIENDO LA INSCRIPCIÓN CON LA NUEVA RESERVA let CountConfirmedOldReservation = await eventInscriptionService._getCountInscriptionsWithReservation( dataInscription.inscription.reservationId ); console.log("actualizo confirmados de la reserva anterior"); await eventReservationService._updateConfirmedReservation( dataInscription.inscription.reservationId, --CountConfirmedOldReservation ); let CountConfirmedNewReservation = await eventInscriptionService._getCountInscriptionsWithReservation( dataInscription.reservation.id ); console.log("actualizo confirmados de la nueva reserva"); await eventReservationService._updateConfirmedReservation( dataInscription.reservation.id, ++CountConfirmedNewReservation ); await eventInscriptionService._updateReservationOfInscription( dataInscription.inscription.id, dataInscription.reservation.id ); dataInscription.inscription = await eventInscriptionService._getInscriptionById(dataInscription.inscription.id); return handleResultResponse(dataInscription.inscription, null, params, res, httpStatus.OK); } } catch (error) { return handleResultResponse("Error checkInscriptionByUser", error, params, res, httpStatus.NOT_FOUND); } next(); }, getInscription: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); const inscriptionId = params.params.id; const userId = req.user.id; try { let inscription = await eventInscriptionService._getInscriptionById(inscriptionId); if (!inscription) { return handleResultResponse("Inscripción no encontrada", null, params, res, httpStatus.NOT_FOUND); }; /* Se quita esta validación porque ya no se va a cumplir que solo se elimine la entrada por parte del porpio usuario desde la APP // ahora el formulario web AP4 podrá eliminar entradas de cualquier petición (protegido por apikey) else if (inscription.userId !== userId) { return handleResultResponse("Inscripción no encontrada", null, params, res, httpStatus.NOT_FOUND); }*/ //console.log("inscripcion encontrada>>>>>>>>>>>>>>>>>>>>>>>>>>>", inscription); inscription = await inscription.toJSON(); //console.log(">>>>>>>voy a dar inscription>>><", inscription.user); var member = marketingListService._generateMarketingDTO(inscription); member.qrConfig = QRHelper.generateQRConfig(member); inscription.code_ticket_qr = await QRHelper.getInscriptionQRCode(member.qrConfig); //Si el usuario de la inscripción no es tutor limpiamos la información de la reserva if (inscription.user.profile !== "tutor") if (inscription.reservation) inscription.reservation.assistants = null; if (inscription.reservation === null) { console.log("asigno green"); inscription.color = "green"; /* parche */ inscription.reservation = { color: "green", description: "Entrada", }; } //MAPEO SALIDA API4 //Tratamos resultado, si hay que remover campos para API4 web if (res.locals.v4){ /*const arrayFieldsremove = res.locals.v4.removeFields; arrayFieldsremove.forEach(campo => { if (campo in inscription) { delete inscription[campo]; } });*/ //En lugar de estar quitando campo creamos un DTO nuevo con la información que nos interesa const inscriptionResume = { id : inscription.id, stateText : inscription.stateText, code_ticket : inscription.code_ticket, eventName : inscription.event.name, userName : inscription.user.name, userSurname : inscription.user.surname, }; inscription = inscriptionResume; }; console.log(">>>>>>>voy a dar inscription", inscription); return handleResultResponse(inscription, null, params, res, httpStatus.OK); } catch (error) { return handleResultResponse("Error al buscar la inscripción", null, params, res, httpStatus.NOT_FOUND); } }, //////////////////////////////////////////////////////////////////////////////// //Esta función comprueba si el email ya tiene una inscripción para el evento //////////////////////////////////////////////////////////////////////////////// checkInscriptionByMail: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); var eventId = params.params.id; var email = params.params.email; console.log(">checkInscriptionByMail>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", eventId, email); try { const user = await userService._getUserByEmail(email); if (user) { const result = await eventInscriptionService._getInscriptionByEventAndUser(eventId, user.id); if (result) return handleResultResponse(result.stateText, null, params, res, httpStatus.OK); } return handleResultResponse("No hay inscripción con ese email", null, params, res, httpStatus.NOT_FOUND); } catch (error) { return handleErrorResponse(MODULE_NAME, "checkInscription", error, res); } }, /////////////////////////////////////////////////////////////////// //Esta función se llama solo desde APP //Inscripción sin CODIGO DE RESERVA, SE MODIFICA EL CONFIRMED DEL EVENTO, YA QUE SE DESCONTARA DEL AFORO DEL EVENTO // en caso de online no afectará a los aforos /////////////////////////////////////////////////////////////////// createInscription: async (req, res, next) => { console.log(">>>>>>>>>>>>>>>>>>>> createInscription (event_inscriptions.controller)"); const params = extractParamsFromRequest(req, res, {}); let dataInscription = res.locals.dataInscription; if (!dataInscription || !dataInscription.event) return handleResultResponse("Error prepareDataInscription requerida", null, params, res, httpStatus.NOT_FOUND); let dataUser = res.locals.dataUser; if (!dataUser) return handleResultResponse("Error getOrCreateUser requerida", null, params, res, httpStatus.NOT_FOUND); if (dataInscription.reservation) return handleResultResponse( "Error existe una reserva por lo que debe llamar a createInscriptionReservation", null, params, res, httpStatus.NOT_FOUND ); try { //ONLINE //Si es una inscripcion online no se validan aforos se crea inscripción y ya esta if (dataInscription.type === "online" || dataInscription.type === "online group") { //creamos inscripcion dataInscription.inscription = await eventInscriptionService._createInscription( dataInscription.event.id, dataUser.userResult.user.id, dataInscription.type, true, //validated, dataInscription.source, null, null ); console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>ENTRADA ONLINE", dataInscription.inscription); } //ONSITE INDIVIDUAL if (!dataInscription.inscription) { let inscriptionsWithoutReservationAndOverflowCount = await eventInscriptionService._getCountInscriptionsWithoutReservationAndOverflow(dataInscription.event.id); ++inscriptionsWithoutReservationAndOverflowCount; console.log("Vamos a ver si hay aforo>>>>", inscriptionsWithoutReservationAndOverflowCount); //COMPROBAMOS SI ES VALIDO O HAY QUE APUNTARLE A LA LISTA DE ESPERA DEL EVENTO if ( dataInscription.event.sold_out == 0 && dataInscription.event.assistants >= inscriptionsWithoutReservationAndOverflowCount ) { dataInscription.validated = true; console.log("actualizamos afoorooo>>>"); //Actualizamos aforo del evento y creamos inscripcion if ( await eventService._updateConfirmedEvent( dataInscription.event.id, inscriptionsWithoutReservationAndOverflowCount ) ) { try { dataInscription.inscription = await eventInscriptionService._createInscription( dataInscription.event.id, dataUser.id, dataInscription.type, dataInscription.validated, dataInscription.source, null, null ); } catch (error) { console.log("SSSSSSSSSSSSSSSSSSSSSSSSS", error); } } else return handleResultResponse( "No se ha podido actualizar el aforo del evento", null, params, res, httpStatus.NOT_FOUND ); console.log("Inscripcion hecha>>>", dataInscription.inscription); //Ponemos el evento en SOLD_OUT if (dataInscription.event.assistants == inscriptionsWithoutReservationAndOverflowCount) await eventService._updateSoldOutEvent(dataInscription.event.id, true); } // APUNTARSE A la lista de espera si se puede else { dataInscription.validated = false; if (dataInscription.event.allow_overflow === false) { console.log("Aforo completo y no hay lista de espera"); return handleResultResponse( "Aforo completo y no hay lista de espera", null, params, res, httpStatus.NOT_FOUND ); } //recuperamos la cantidad de apuntados al evento overflow (lista de espera) let ConfirmedWaitList = await eventInscriptionService._getCountInscriptionsWithOverflowEventId( dataInscription.event.overflow_eventId ); //recuperamos aforo de la lista de espera dataInscription.overflow_event = await eventService._getEvent(dataInscription.event.overflow_eventId); console.log( "cantidad apuntados a lista de espera asociado, aforo >>>>>>>>>>>>>>>>>>>>>", ConfirmedWaitList, dataInscription.overflow_event.assistants ); //Si no hay espacio a lista de espera damos el mismo error que no hay lista de espera if (dataInscription.overflow_event.assistants < ++ConfirmedWaitList) { console.log("Aforo completo de lista de espera"); return handleResultResponse( "Aforo completo y no hay lista de espera", null, params, res, httpStatus.NOT_FOUND ); } //Creamos inscripción a lista de espera if (await eventService._updateConfirmedEvent(dataInscription.event.overflow_eventId, ConfirmedWaitList)) { dataInscription.inscription = await eventInscriptionService._createInscription( dataInscription.event.id, dataUser.userResult.user.id, dataInscription.type, dataInscription.validated, dataInscription.source, null, dataInscription.event.overflow_eventId ); } else { console.log("No se ha podido actualizar el aforo de la lista de espera del evento"); return handleResultResponse( "No se ha podido actualizar el aforo de la lista de espera del evento", null, params, res, httpStatus.NOT_FOUND ); } } //FIN APUNTARSE A la lista de espera si se puede } dataInscription.inscription = await dataInscription.inscription.toJSON(); //Incluimos correo en sendinblue try { marketingListService.addMarketingList(dataUser, dataInscription); } catch (error) { console.log("Se ha producido un error al añadir a Hubspot >>>>>>>>>>>>>>>>>", error); } //Mandamos correo con entrada o lista de espera try { mailService.sendEmailConfirm(dataUser, dataInscription); } catch (error) { console.log("Se ha producido un error al enviar mail>>>>>>>>>>>>>>>>><<", error); } //MAPEO SALIDA API4 //Tratamos resultado, si hay que remover campos para API4 web if (res.locals.v4) { const arrayFieldsremove = res.locals.v4.removeFields; arrayFieldsremove.forEach((campo) => { if (campo in dataInscription.inscription) { delete dataInscription.inscription[campo]; } }); } return handleResultResponse(await dataInscription.inscription, null, params, res, httpStatus.CREATED); } catch (Error) { return handleResultResponse( "Error al crear la incripción createInscription", null, params, res, httpStatus.NOT_FOUND ); } }, deleteInscription: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); const user = req.user; const inscriptionId = params.params.id; let marketingListId = null; try { const inscription = await eventInscriptionService._getInscriptionById(inscriptionId); console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1) return handleResultResponse( "No se pudo eliminar inscripción por ser tutor de grupo y tener alumnos apuntados, pongase en contacto con nosotros", null, params, res, httpStatus.NOT_FOUND ); //Borramos inscripción if ((await eventInscriptionService._deleteInscription(inscription.id)) > 0) { console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> 0)) return handleResultResponse( "No se pudo eliminar inscripción por ser tutor de grupo online y tener alumnos apuntados, pongase en contacto con nosotros", null, params, res, httpStatus.NOT_FOUND ); if (inscription.reservation.state === "publish" && lodash.words(inscription.type).includes("onsite")) { const eventOfReservation = await eventService._getEvent(inscription.reservation.eventId); //Modificamos los asistentes de evento (AFORO) para añadir las plazas de la reserva eliminada const newAforo = eventOfReservation.assistants + inscription.reservation.assistants; if (!(await eventService._updateAssistantsEvent(eventOfReservation.id, newAforo))) return handleResultResponse( "No se ha podido actualizar el aforo del evento, para reservar las plazas solicitadas", null, params, res, httpStatus.NOT_FOUND ); } } //En el caso de ser cualquier usuario o un tutor inscrito de forma libre o a una reserva de la que no es titular //Actualizamos confirmados asistentes else refreshConfirmed(inscription); } else return handleResultResponse("No se pudo eliminar inscripción", null, params, res, httpStatus.NOT_FOUND); //Quitamos correo en sendinblue try { await marketingListService._deleteMember(marketingListId, inscription.user.email, inscription); } catch (error) { console.log("Se ha producido un error al eliminar de SenINBlue>>>>>>>>>>>>>>>>><<", error); } //Mandamos correo de confirmación de eliminación try { mailService.sendEmailCancelate(inscription); } catch (error) { console.log("Se ha producido un error al enviar mail>>>>>>>>>>>>>>>>><<", error); } console.log(">>>>>>>>>>>>>>Inscripcion eliminada con todos los pasos"); return handleResultResponse("Inscripción eliminada", null, params, res, httpStatus.DELETEOK); } catch (error) { console.log("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrorrrr", error); return handleResultResponse("Error al eliminar inscripción", null, params, res, httpStatus.NOT_FOUND); } }, deleteInscriptionsByUser: async (req, res, next) => { try { //const context = buildContext(req, config); //const user = context.user ? context.user : null; const user = { id: req.body.id, phone: req.body.phone, email: req.body.email, }; await eventInscriptionService._deleteInscriptionByUser(user.id); next(); } catch (error) { console.error(error); } }, }; module.exports = generateControllers(eventInscriptionService, extraControllers, controllerOptions);