app2-api/modules/events/events_reservations.controller.js

526 lines
22 KiB
JavaScript

"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 mailService = require("./mail.service");
const marketingListService = require("./marketing_list.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 };
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(mailService.generateHeaderMailReservation(reservation), mailService.generateBodyMailReservation(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(mailService.generateHeaderMailReservation(reservation), mailService.generateBodyMailReservation(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) => {
const params = extractParamsFromRequest(req, res, {});
let dataInscription = res.locals.dataInscription;
if (!dataInscription)
return handleResultResponse(
"Error recuperateReservationByCode, prepareDataInscription requerida",
null,
params,
res,
httpStatus.NOT_FOUND
);
console.log(">>>>>>>>>>>>>>>>>>>> recuperateReservationByCode", dataInscription.type);
//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, "recuperateReservationByCode", 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, prepareDataInscription, requerida",
null,
params,
res,
httpStatus.NOT_FOUND
);
let dataUser = res.locals.dataUser;
if (!dataUser)
return handleResultResponse(
"Error createReservationToEntity, prepareDataInscription, getOrCreateUser requerida",
null,
params,
res,
httpStatus.NOT_FOUND
);
console.log(">>>>>>>>>>>>>>>>>>>> createReservationToEntity>>>>>>", dataInscription.type);
//Si viene group_size crearemos un código de reserva
if (dataInscription.groupSize > 1) {
if (!dataUser.entityId) {
return handleResultResponse(
"Error No es posible crear reserva grupal si no pertences a una entidad educativa",
null,
params,
res,
httpStatus.NOT_FOUND
)};
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 === 'online group')? 'Incripción online en grupo' : 'Reserva',
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,
};
//Comprobamos aforo si no es online, si no es posible apuntarse iria a lista de espera
if (dataInscription.type !== "online" && dataInscription.type !== "online group"){
const plazasDisponibles = dataInscription.event.assistants - dataInscription.event.confirmed;
if (plazasDisponibles < reservationData.assistants)
if (dataInscription.event.allow_overflow){
reservationData.overflowEventId = dataInscription.event.overflow_eventId;
reservationData.description = reservationData.description + ' en lista de espera'
console.log('Asigno lista de espera>>>>>>>>>>>>>>>>>>>>>>>',reservationData.eventId);
}
else return handleResultResponse("Aforo lleno no es posible efectuar la reserva", null, params, res, httpStatus.NOT_FOUND);
}
///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) => {
const params = extractParamsFromRequest(req, res, {});
let dataInscription = res.locals.dataInscription;
let dataUser = res.locals.dataUser;
if (!dataUser || !dataInscription || !dataInscription.event)
return handleResultResponse(
"Error createReservationToEntity, prepareDataInscription, ActiveReservationToEntity requerida",
null,
params,
res,
httpStatus.NOT_FOUND
);
//En caso de ser online no descontamos ningun aforo ya que no se controla de momento
if (dataInscription.type === "online" || dataInscription.type === "online group") {
console.log(">> No se aplica descuento de aforo");
next();
return;
};
//En caso de ser una inscripción normal o una reserva ya publicada no descontamos ningun aforo al evento
if (!dataInscription.reservation || (dataInscription.reservation.state === 'publish')){ // || (!dataInscription.reservationCode) || (dataInscription.reservationCode === "")) {
console.log(">> No se aplica descuento de aforo ya que es una reserva publicada");
next();
return;
};
//Si es centro aliado
if (dataUser.entityLevel === "aliado") {
//La reserva puede estar asociada a la lista de espera es de donde se quitará aforo, si no al evento
const eventToDiscountAssistants = dataInscription.reservation.overflowEventId
? await eventService._getEvent(dataInscription.reservation.overflowEventId)
: dataInscription.event;
const plazasDisponibles = eventToDiscountAssistants.assistants - eventToDiscountAssistants.confirmed;
if (plazasDisponibles < dataInscription.reservation.assistants)
return handleResultResponse("Aforo lleno no es posible efectuar la reserva", null, params, res, httpStatus.NOT_FOUND)
const newAforo = eventToDiscountAssistants.assistants - dataInscription.reservation.assistants;
//Modificamos los asistentes de evento (AFORO) para quitar los de la reserva
if (!(await eventService._updateAssistantsEvent(eventToDiscountAssistants.id, newAforo)))
return handleResultResponse(
"No se ha podido actualizar el aforo del evento, para reservar las plazas solicitadas",
null,
params,
res,
httpStatus.NOT_FOUND
);
//Si se ha llenado ponemos el evento en SOLD_OUT
if (eventToDiscountAssistants.confirmed == newAforo)
await eventService._updateSoldOutEvent(eventToDiscountAssistants.id, true);
//Finalmente publicamos la reserva solo si no está asociada a la lista de espera
if (!dataInscription.reservation.overflowEventId) {
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";
//Mandamos el código de reserva para que registra a sus alumnos
dataInscription.reservation.contact_email = dataUser.email;
dataInscription.reservation.contact_name = dataUser.name;
dataInscription.reservation.event = dataInscription.event;
console.log('MANDAMOS CODIO RESERVA>>>>>>',dataInscription.reservation);
try{
mailService.sendReservationEmail(dataInscription.reservation);
}catch(error){
console.log(error);
}
}
}
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 prepareDataInscription, 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
);
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
) {
console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>ESTA ES LA RESERVA>>>>>>>>>>>>>>>')
//Es la inscripción automática del tutor o alguien que tiene el código y eso no puede ser
if (dataInscription.reservation.state === 'publish')
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.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,
};
// Incluimos correo en sendinblue
try {
// marketingListService.addMarketingList(dataUser, dataInscription);
} catch(error){ console.log('Se ha producido un error al añadir a SenINBlue>>>>>>>>>>>>>>>>><<', 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);}
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);