app2-api/modules/events/events_inscriptions.controller.js
2025-01-31 11:53:19 +01:00

599 lines
26 KiB
JavaScript

"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 : Buffer.from(req.body.code, "base64").toString("ascii"),
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(">>>>>>>>>>>>>>>>>>>>>>>>>>>>><Inscripcion a borrar:");
console.log(inscription.id);
//Solo se tiene en cuenta el marketinglist del evento
marketingListId = inscription.event.marketing_list;
//Si no existe la inscripcion damos error
if (!inscription)
return handleResultResponse("Inscription no encontrada", null, params, res, httpStatus.NOT_FOUND);
//Si user{} quiere decir que lo llaman desde API4 para eliminar desde la web
//Si no es vacio es desde la APP y tiene que cumplirse la comprobación, de hecho esto no seria posible si es asi damos error
if (!lodash.isEmpty(user) && inscription.userId !== user.id)
return handleResultResponse("Inscription no encontrada", null, params, res, httpStatus.NOT_FOUND);
//En el caso de ser una inscripción grupal y el tutor se quiere quitar, se podrá hacer solo en el caso de que en la reserva no haya ya confirmados
if (inscription.user.profile === "tutor" && inscription.reservation && inscription.reservation.confirmed > 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(">>>>>>>>>>>>>>>>>>>>>>>>>>>>><Inscripcion borrada");
//En todos los casos en el que se elimine una inscripción hay que refrescar los confirmados de la reserva o del evento
//en el caso de ser un tutor que ha realizado una reserva y solo está el confirmado, se borra y punto no se actualiza nada
if (
inscription.user.profile === "tutor" &&
inscription.reservation &&
inscription.reservation.confirmed === 1
) {
//Eliminamos la reserva hecha del centro aliado
if (!((await eventReservationService._deleteReservation(inscription.reservation.id)) > 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);