"use strict"; const moment = require("moment"); const generateControllers = require("../../core/controllers"); const eventService = require("./event.service"); const eventReservationService = require("./events_reservations.service"); const eventInscriptionService = require("./events_inscriptions.service"); const { extractParamsFromRequest, handleErrorResponse, handleResultResponse, httpStatus, } = require("../../helpers/controller.helper"); const emailHelper = require("../../helpers/mail.helper"); const path = require("path"); const responseTime = require("response-time"); // Module Name const MODULE_NAME = "[eventReservation.controller]"; const controllerOptions = { MODULE_NAME }; function generateHeaderMail(reservation) { let headerMail = null; if (reservation) { headerMail = { to: reservation.Entity.contact_email, name: reservation.Entity.name, bcc: "cbarrantes@loquedeverdadimporta.org", bccName: "Carolina Barrantes", subject: "Códigos de invitación para congreso LQDVI", }; } return headerMail; } function generateBodyMail(reservation) { let bodyMail = null; if (reservation) { bodyMail = { entityName: reservation.Entity.name, eventName: reservation.Event.name, dateEvent: moment(reservation.Event.init_date).format("D [de] MMMM [de] YYYY"), reservationCode: reservation.reservation_code, reservationDescription: reservation.description, }; } return bodyMail; } async function _addConfirmedToEvent(confirmed, event) { const newConfirmed = event.confirmed + confirmed; if (event.assistants < newConfirmed) { console.log("El aforo solicitado es superior a las plazas disponibles"); return false; } if (!(await eventService._updateConfirmedEvent(event.id, newConfirmed))) { console.log("No se ha podido actualizar el aforo del evento"); return false; } //Si se ha llenado ponemos el evento en SOLD_OUT if (event.assistants == newConfirmed) await eventService._updateSoldOutEvent(event.id, true); return true; } async function activeReservationById(id) { //Buscar reserva con evento y entidad let reservation = await eventReservationService._getReservaByIdWithEntityAndEvent(id); if (await _addConfirmedToEvent(reservation.assistants, reservation.Event)) if (!(await eventReservationService._updatePublishReservation(id))) { console.log("No se ha podido publicar la reserva del evento"); return false; } return true; } const extraControllers = { checkReservationCode: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); const appVersion = req && req.headers && req.headers["accept-version"] ? req.headers["accept-version"] : null; console.log("checkReservationCode - appVersion: ", appVersion); console.log("checkReservationCode - PARAMS ", params); const eventId = params.params.id; const encodedInvitationCode = params.params.encodedInvitationCode; const registrationCode = Buffer.from(req.params.encodedInvitationCode, "base64").toString("ascii"); try { const result = await eventReservationService._getReservaByCode(eventId, registrationCode); if (appVersion) { if (appVersion == "1.0.0" || appVersion == "1.0.1" || appVersion == "1.0.2") return handleResultResponse(!!result, null, params, res, httpStatus.OK); else return handleResultResponse(result, null, params, res, httpStatus.OK); } else return handleResultResponse(!!result, null, params, res, httpStatus.OK); } catch (error) { return handleErrorResponse(MODULE_NAME, "checkReservationCode", error, res); } }, getReservationsExcel: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); const eventId = params.params.id; const type = params.params.type; const userId = req.user.id; const reservations = await eventReservationService._getReservationsExcel( req.user, eventId, null, type, function (result, status) { if (result.messenger.code == "S99001") { console.log(result); res.setHeader("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); res.setHeader("Content-Disposition", "attachment; filename=" + result.data.name); res.attachment(result.data.name); res.download(path.resolve(result.data.path), result.data.name); } else { res.status(status).json(result); } } ); }, sendMailReservation: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); const reservationId = params.params.id; const user = req.user; try { const reservation = await eventReservationService._getReservaByIdWithEntityAndEvent(reservationId); if (!reservation) return handleResultResponse("Reserva no encontrada", null, params, res, httpStatus.NOT_FOUND); try { if (reservation.Entity.contact_email) emailHelper.sendReservationCode(generateHeaderMail(reservation), generateBodyMail(reservation)); } catch (error) { // console.log(error); console.log("No se ha podido mandar email con los códigos de invitación"); } return handleResultResponse(null, null, params, res, httpStatus.OK); } catch (error) { return handleResultResponse("Error al buscar la reserva", null, params, res, httpStatus.NOT_FOUND); } }, sendMailReservationsEvent: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); const eventId = params.params.id; const entityId = params.params.entityId; const type = params.params.type; const user = req.user; let reservations = null; let result = ""; try { if (!entityId) reservations = await eventReservationService._getReservasByEventAndType(eventId, type); else reservations = await eventReservationService._getReservasByEventAndEntity(eventId, entityId); if (!reservations) return handleResultResponse("Reservas no encontradas", null, params, res, httpStatus.NOT_FOUND); try { reservations.forEach(function (reservation) { console.log("mando correo: ", reservation.Entity.name); if (reservation.Entity.contact_email && reservation.Entity.contact_email.length !== 0) { console.log("correo: ", reservation.Entity.contact_email); emailHelper.sendReservationCode(generateHeaderMail(reservation), generateBodyMail(reservation)); result = result + "Invitación con código " + reservation.reservation_code + " enviada a " + reservation.Entity.name + " al destinatario " + reservation.Entity.contact_email + "\n"; } else result = result + "Invitación con código " + reservation.reservation_code + " no se ha enviado proque el correo (" + reservation.Entity.contact_email + ") no es válido\n"; }); } catch (error) { // console.log(error); console.log("No se ha podido mandar email con los códigos de invitación"); } return handleResultResponse(result, null, params, res, httpStatus.OK); } catch (error) { return handleResultResponse("Error al buscar las reservas", null, params, res, httpStatus.NOT_FOUND); } }, recuperateReservationByCode: async (req, res, next) => { console.log(">>>>>>>>>>>>>>>>>>>> recuperateReservationByCode"); const params = extractParamsFromRequest(req, res, {}); let dataInscription = res.locals.dataInscription; if (!dataInscription) return handleResultResponse( "Error recuperateReservationByCode, prepareInscription, recuperateEvent requerida", null, params, res, httpStatus.NOT_FOUND ); //SI VIENE CODIGO DE RESERVA, RECUPERAMOS LA RESERVA Y EL EVENTO if (dataInscription.reservationCode) { try { dataInscription.reservation = await eventReservationService._getReservaByCode( dataInscription.eventId, dataInscription.reservationCode ); if (dataInscription.reservation) { dataInscription.reservation = await dataInscription.reservation.toJSON(); dataInscription.event = dataInscription.reservation.Event; } else { // No se ha encontrado return handleResultResponse("Código de reserva no encontrado", null, params, res, httpStatus.NOT_FOUND); } res.locals.dataInscription = dataInscription; } catch (error) { return handleErrorResponse(MODULE_NAME, "recuperateEventAndReservation", error, res); } } next(); }, createReservationToEntity: async (req, res, next) => { console.log(">>>>>>>>>>>>>>>>>>>> createReservationToEntity"); const params = extractParamsFromRequest(req, res, {}); let dataInscription = res.locals.dataInscription; if (!dataInscription || !dataInscription.event) return handleResultResponse( "Error createReservationToEntity, prepareInscription, recuperateEvent requerida", null, params, res, httpStatus.NOT_FOUND ); let dataUser = res.locals.dataUser; if (!dataUser) return handleResultResponse( "Error createReservationToEntity, prepareInscription, recuperateEvent, getOrCreateUser requerida", null, params, res, httpStatus.NOT_FOUND ); //Si viene group_size crearemos un código de reserva if (dataInscription.groupSize > 1) { const reservationData = { reservation_code: eventReservationService._generateReservatioCode(dataInscription.event, dataUser.entityName), state: "draft", //sin confirmar, publish es cuando se descuenta del aforo del evento color: "gray", description: dataInscription.type, init_available_date: dataInscription.event.init_available_date, end_available_date: dataInscription.event.end_available_date, entityId: dataUser.entityId, eventId: dataInscription.event.id, gmt: dataInscription.event.gmt, assistants: dataInscription.groupSize, virtual: dataInscription.type === "online" || dataInscription.type === "online group", userId: dataUser.id, allow_overflow: false, }; ///Aqui podríamos validar si ya hay reserva y dar error ya que no pueden meter codigo de reserva y darnos un group_size superior a 1. dataInscription.reservation = await eventReservationService.create( reservationData, generateControllers.buildContext(req, {}) ); dataInscription.reservation = dataInscription.reservation.toJSON(); res.locals.dataInscription = dataInscription; console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>RESERVATION CREADA", dataInscription.reservation); } else console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>no hago nada"); next(); }, activeReservationToEntity: async (req, res, next) => { console.log(">>>>>>>>>>>>>>>>>>>> ActiveReservationToEntity"); const params = extractParamsFromRequest(req, res, {}); let dataInscription = res.locals.dataInscription; if (!dataInscription) return handleResultResponse( "Error activeReservationToEntity, prepareInscription, recuperateEvent requerida", null, params, res, httpStatus.NOT_FOUND ); if (dataInscription.reservation) { if (res.locals.dataUser.entityLevel === "aliado") { ///Aqui podríamos validar si ya hay reserva y dar error ya que no pueden meter codigo de reserva y darnos un group_size superior a 1. if (!(await eventReservationService._updatePublishReservation(dataInscription.reservation.id))) return handleResultResponse( "No se ha podido publicar la reserva del evento", null, params, res, httpStatus.NOT_FOUND ); dataInscription.reservation.state = "publish"; } } next(); }, activarReservation: async (req, res, next) => { const params = extractParamsFromRequest(req, res, {}); const idResevation = params.params.id; if (!idResevation) return handleResultResponse("Error id de reservation necesario", null, params, res, httpStatus.NOT_FOUND); try { let result = await activeReservationById(idResevation); return handleResultResponse(result, null, params, res, httpStatus.OK); } catch (error) { return handleResultResponse("Error al buscar las reservas", null, params, res, httpStatus.NOT_FOUND); } }, /////////////////////////////////////////////////////////////////// //Esta función se llama desde APP y desde WEB //Inscripción con CODIGO DE RESERVA, SE MODIFICA EL CONFIRMED DE LA RESERVA, YA QUE SE DESCONTARA DEL AFORO DE LA RESERVA // en caso de online, funciona igual ya que descontará la inscripción de la persona del aforo quedando la inscripción online asociada a la reserva /////////////////////////////////////////////////////////////////// createInscriptionReservation: async (req, res, next) => { console.log(">>>>>>>>>>>>>>>>>>>> createInscriptionReservation (event_reservations.controller)"); const params = extractParamsFromRequest(req, res, {}); let dataInscription = res.locals.dataInscription; if (!dataInscription || !dataInscription.event || !dataInscription.reservation) return handleResultResponse( "Error prepareInscription, recuperateEvent, recuperateReservationByCode o createReservationToEntity 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); try { //CON CODIGO DE RESERVA SE MODIFICA EL CONFIRMED DE LA RESERVA, YA QUE SE DESCONTARA DEL AFORO DE LA RESERVA dataInscription.inscriptionsWithReservationCount = await eventInscriptionService._getCountInscriptionsWithReservation(dataInscription.reservation.id); ++dataInscription.inscriptionsWithReservationCount; console.log( "me inscribo por reserva>>>>>>>>>>>>>>>>>>>>>>>>>>><< con asistentes: ", dataInscription.reservation.assistants ); console.log(dataInscription.reservation.sold_out); console.log(dataInscription.inscriptionsWithReservationCount); //COMPROBAMOS SI ES VALIDO O HAY QUE APUNTARLE A LA LISTA DE ESPERA DE LA RESERVA if ( dataInscription.reservation.sold_out == 0 && dataInscription.reservation.assistants >= dataInscription.inscriptionsWithReservationCount ) { dataInscription.validated = true; console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>", dataInscription.type); //Actualizamos aforo de la lista de espera de la reserva y creamos inscripcion en la lista de espera de la reserva if ( await eventReservationService._updateConfirmedReservation( dataInscription.reservation.id, dataInscription.inscriptionsWithReservationCount ) ) dataInscription.inscription = await eventInscriptionService._createInscription( dataInscription.event.id, dataUser.userResult.user.id, dataInscription.type, dataInscription.validated, dataInscription.source, dataInscription.reservation.id, null ); else return handleResultResponse( "No se ha podido actualizar el aforo de la reserva", null, params, res, httpStatus.NOT_FOUND ); //Ponemos la reserva en SOLD_OUT para que no se pueda apuntar nadie más if (dataInscription.reservation.assistants == dataInscription.inscriptionsWithReservationCount) await eventReservationService._updateSoldOutReservation(dataInscription.reservation.id, true); } // APUNTARSE A LISTA DE ESPERA SI SE PUEDE else { if (dataInscription.reservation.allow_overflow === true) { dataInscription.validated = false; dataInscription.inscriptionsWithReservationCount = await eventInscriptionService._getCountInscriptionsWithReservation( dataInscription.reservation.overflow_reservationId ); ++dataInscription.inscriptionsWithReservationCount; // if (dataInscription.reservation.assistants >= dataInscription.inscriptionsWithReservationCount) { //Actualizamos aforo de la reserva y creamos inscripcion if ( await eventReservationService._updateConfirmedReservation( dataInscription.reservation.overflow_reservationId, dataInscription.inscriptionsWithReservationCount ) ) dataInscription.inscription = await eventInscriptionService._createInscription( dataInscription.event.id, dataUser.userResult.user.id, dataInscription.type, dataInscription.validated, dataInscription.source, dataInscription.reservation.overflow_reservationId, null ); else return handleResultResponse( "No se ha podido actualizar el aforo de la reserva", null, params, res, httpStatus.NOT_FOUND ); } else return handleResultResponse( "Aforo completo de la reserva y no hay lista de espera", null, params, res, httpStatus.NOT_FOUND ); } let Result = await dataInscription.inscription.toJSON(); Result = { reservation: dataInscription.reservation, ...Result, }; return handleResultResponse(Result, null, params, res, httpStatus.CREATED); } catch (error) { return handleResultResponse("Error al crear la incripción online", null, params, res, httpStatus.NOT_FOUND); } }, }; module.exports = generateControllers(eventReservationService, extraControllers, controllerOptions);