diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b704d53 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,13 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "attach", + "name": "Node: Nodemon", + "processId": "${command:PickProcess}", + "restart": true, + "protocol": "inspector" + } + ] +} diff --git a/config/environments/development.js b/config/environments/development.js index 8481837..2872983 100644 --- a/config/environments/development.js +++ b/config/environments/development.js @@ -1,51 +1,58 @@ module.exports = { - database: { - username: 'lqdvi', - password: 'Z286y386*a', - database: 'lqdvi_v2', - host: 'localhost', - dialect: 'mysql', - }, + database: { + username: "lqdvi", + password: "Z286y386*a", + database: "lqdvi_v2", + host: "localhost", + dialect: "mysql", + }, - cache: { - enabled: false, - defaultDuration: '1 minute', - debug: true, - }, + cache: { + enabled: false, + defaultDuration: "1 minute", + debug: true, + }, - session: { - secret_token: process.env.SECRET_TOKEN || "B57J=7B`NQ$y98|~5;hc715bo09^5oz8NR+]n9r~215B91Nd9P%25_N6r!GHcOKp|18y5-73Dr5^@9k7n]5l<-41D1o", - token_expires_in: '365d' - }, + session: { + secret_token: + process.env.SECRET_TOKEN || + "B57J=7B`NQ$y98|~5;hc715bo09^5oz8NR+]n9r~215B91Nd9P%25_N6r!GHcOKp|18y5-73Dr5^@9k7n]5l<-41D1o", + token_expires_in: "365d", + }, - server: { - hostname: process.env.HOSTNAME || '127.0.0.1', - port: process.env.PORT || 19999, - public_url: "" - }, + server: { + hostname: process.env.HOSTNAME || "127.0.0.1", + port: process.env.PORT || 19999, + public_url: "", + }, - cdn: { - hostname: "https://cdnapp2.loquedeverdadimporta.org", - }, + cdn: { + hostname: "https://cdnapp2.loquedeverdadimporta.org", + }, - uploads: { - path: "/home/rodax/Documentos/cdn2", - thumb_size: 300, - thumb_prefix: "th_", - }, + uploads: { + path: "/home/rodax/Documentos/cdn2", + thumb_size: 300, + thumb_prefix: "th_", + }, - paginate: { - limit: 10, - maxLimit: 50 - }, + paginate: { + limit: 10, + maxLimit: 50, + }, - vimeo: { - CLIENT_ID: '9581f2d0ed211dc1e31b5c825117dc1f00d77ba0', - CLIENT_SECRET: '3kf0hQ63OXSPm7z2X1qyOV4iH57Xha0cyRXn0VJneq8zHbWKjfB1/9H8KcgBgzgkzw0Y9x/xFLUAauuHLEkqHxLBw8QueanCgIZev1L5xoksrKuKX7gMvErqqP+uFNnA', - ACCESS_TOKEN: 'fcc7b31fe690a768efa920e13d750449' - }, + vimeo: { + CLIENT_ID: "9581f2d0ed211dc1e31b5c825117dc1f00d77ba0", + CLIENT_SECRET: + "3kf0hQ63OXSPm7z2X1qyOV4iH57Xha0cyRXn0VJneq8zHbWKjfB1/9H8KcgBgzgkzw0Y9x/xFLUAauuHLEkqHxLBw8QueanCgIZev1L5xoksrKuKX7gMvErqqP+uFNnA", + ACCESS_TOKEN: "fcc7b31fe690a768efa920e13d750449", + }, - sendinblue: { - API_KEY: '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' - } -} + sendinblue: { + API_KEY: "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", + }, + + hubspot: { + API_KEY: "pat-eu1-36a3fff1-1877-44ae-a32e-00e91c3e650b", + }, +}; diff --git a/config/environments/production.js b/config/environments/production.js index 1932395..1cc576a 100644 --- a/config/environments/production.js +++ b/config/environments/production.js @@ -1,60 +1,66 @@ module.exports = { - database: { - username: 'lqdvi', - password: 'Z286y386*a', - database: 'lqdvi_v2', - host: 'localhost', - dialect: 'mysql', + database: { + username: "lqdvi", + password: "Z286y386*a", + database: "lqdvi_v2", + host: "localhost", + dialect: "mysql", - /* + /* username: process.env.DB_USERNAME, password: process.env.DB_PASSWORD, database: process.env.DB_NAME, host: process.env.DB_HOSTNAME, dialect: 'mysql', */ - }, + }, - cache: { - enabled: true, - defaultDuration: '1 minute', - debug: true, - }, + cache: { + enabled: true, + defaultDuration: "1 minute", + debug: true, + }, + session: { + secret_token: + process.env.SECRET_TOKEN || + "B57J=7B`NQ$y98|~5;hc715bo09^5oz8NR+]n9r~215B91Nd9P%25_N6r!GHcOKp|18y5-73Dr5^@9k7n]5l<-41D1o", + token_expires_in: "365d", + }, - session: { - secret_token: process.env.SECRET_TOKEN || "B57J=7B`NQ$y98|~5;hc715bo09^5oz8NR+]n9r~215B91Nd9P%25_N6r!GHcOKp|18y5-73Dr5^@9k7n]5l<-41D1o", - token_expires_in: '365d' - }, + server: { + hostname: process.env.HOSTNAME || "127.0.0.1", + port: process.env.PORT || 19999, + public_url: "https://apiapp3.loquedeverdadimporta.org/api/v3", + }, - server: { - hostname: process.env.HOSTNAME || '127.0.0.1', - port: process.env.PORT || 19999, - public_url: "https://apiapp3.loquedeverdadimporta.org/api/v3" - }, + cdn: { + hostname: "https://cdnapp2.loquedeverdadimporta.org", + }, - cdn: { - hostname: "https://cdnapp2.loquedeverdadimporta.org", - }, + uploads: { + path: "/opt/app2/cdn2", + thumb_size: 300, + thumb_prefix: "th_", + }, - uploads: { - path: "/opt/app2/cdn2", - thumb_size: 300, - thumb_prefix: "th_", - }, + paginate: { + limit: 10, + maxLimit: 50, + }, - paginate: { - limit: 10, - maxLimit: 50 - }, + vimeo: { + CLIENT_ID: "9581f2d0ed211dc1e31b5c825117dc1f00d77ba0", + CLIENT_SECRET: + "3kf0hQ63OXSPm7z2X1qyOV4iH57Xha0cyRXn0VJneq8zHbWKjfB1/9H8KcgBgzgkzw0Y9x/xFLUAauuHLEkqHxLBw8QueanCgIZev1L5xoksrKuKX7gMvErqqP+uFNnA", + ACCESS_TOKEN: "fcc7b31fe690a768efa920e13d750449", + }, - vimeo: { - CLIENT_ID: '9581f2d0ed211dc1e31b5c825117dc1f00d77ba0', - CLIENT_SECRET: '3kf0hQ63OXSPm7z2X1qyOV4iH57Xha0cyRXn0VJneq8zHbWKjfB1/9H8KcgBgzgkzw0Y9x/xFLUAauuHLEkqHxLBw8QueanCgIZev1L5xoksrKuKX7gMvErqqP+uFNnA', - ACCESS_TOKEN: 'fcc7b31fe690a768efa920e13d750449' - }, + sendinblue: { + API_KEY: "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", + }, - sendinblue: { - API_KEY: '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' - } -} + hubspot: { + API_KEY: "pat-eu1-36a3fff1-1877-44ae-a32e-00e91c3e650b", + }, +}; diff --git a/helpers/hubspot.helper.js b/helpers/hubspot.helper.js index a3ddd4b..e5914e8 100644 --- a/helpers/hubspot.helper.js +++ b/helpers/hubspot.helper.js @@ -15,8 +15,6 @@ function _getMemberByEmail(userEmail) { const defaultClient = new hubspot.Client({ accessToken: config.hubspot.API_KEY }); return new Promise(function (resolve, reject) { - console.debug("_existsMember HS:", userEmail); - defaultClient.crm.contacts.searchApi .doSearch({ filterGroups: [ @@ -63,7 +61,6 @@ function _getMemberByEmail(userEmail) { ], } */ - console.debug("HS API called successfully. Returned total: " + data.total); if (data.total === 1) { resolve(data.results[0]); } else { @@ -82,8 +79,6 @@ function _createMember(member) { const defaultClient = new hubspot.Client({ accessToken: config.hubspot.API_KEY }); return new Promise(function (resolve, reject) { - console.debug("_createMember HS:", member.email); - /** * member = { id: "3cc58b92-d144-492d-a8e8-9e1294b5b10b", @@ -118,13 +113,11 @@ function _createMember(member) { entidad_protagonista: member.entity ? member.entity : "", }; - console.debug(newContact); defaultClient.crm.contacts.basicApi .create({ properties: newContact, }) .then(function (newContact) { - console.debug("HS API called successfully. Returned data: " + newContact.id); resolve(newContact); }) .catch(function (error) { @@ -139,8 +132,6 @@ function _updateMember(email, member) { const defaultClient = new hubspot.Client({ accessToken: config.hubspot.API_KEY }); return new Promise(function (resolve, reject) { - console.debug("_updateMember HS:", email); - /** * member = { email: "darranz@rodax-software.com", @@ -165,7 +156,7 @@ function _updateMember(email, member) { entidad_protagonista: member.entity ? member.entity : "", }, }) - .then(function (response) { + .then(function (updatedContact) { /** * response = { createdAt: "2023-07-25T08:19:05.729Z", @@ -190,7 +181,6 @@ function _updateMember(email, member) { }} */ - console.debug("HS API called successfully. Returned data: " + response); resolve(updatedContact); }) .catch(function (error) { @@ -207,14 +197,11 @@ function _deleteMember(email) { const defaultClient = new hubspot.Client({ accessToken: config.hubspot.API_KEY }); return new Promise(function (resolve, reject) { - console.debug("_deleteMember HS:", email); - _getMemberByEmail(email).then((data) => { if (data && data.id) { defaultClient.crm.contacts.basicApi .archive(data.id) .then(function (response) { - console.debug("HS API called successfully. Returned data: " + response); resolve(); }) .catch(function (error) { @@ -289,13 +276,9 @@ async function _addInscriptionToMember(hbContact, member) { } async function _deleteInscriptionFromMember(hbContact, inscription) { - /** - * arg1: {id: 'c8a39de5-2de6-45e8-84b5-bda22ff81492', source: 'app', event_name: 'Sevilla 2023 - 22ª Edición', event_date: Mon Jun 03 2024 09:00:00 GMT+0200 (hora de verano de Europa central), event_marketing_list: null, …} - */ - console.log(inscription); - const { event: { + init_date, location: { city: delete_city, country: delete_country }, }, } = inscription; @@ -304,37 +287,38 @@ async function _deleteInscriptionFromMember(hbContact, inscription) { let ciudad_del_evento = String(properties.ciudad_del_evento || "").split(";"); if (ciudad_del_evento.includes(delete_city)) { - if (ciudad_del_evento.length > 1) { - ciudad_del_evento = ciudad_del_evento.filter((ciudad) => ciudad !== delete_city); - ciudad_del_evento = ciudad_del_evento.join(";"); - } else { - ciudad_del_evento = null; // + ciudad_del_evento = ciudad_del_evento.filter((ciudad) => ciudad !== delete_city); + } + + const delete_year = String(new Date(init_date).getUTCFullYear()); + let ano_del_congreso = String(properties.ano_del_congreso || "").split(";"); + if (ano_del_congreso.includes(delete_year)) { + if (ano_del_congreso.length > 1 || ciudad_del_evento.length === 0) { + ano_del_congreso = ano_del_congreso.filter((year) => year !== delete_year); } } let pais = String(properties.pais || "").split(";"); if (pais.includes(delete_country)) { - if (pais.length > 1) { - pais = pais.filter((ciudad) => ciudad !== delete_city); - pais = pais.join(";"); - } else { - pais = null; // + if (pais.length > 1 || ciudad_del_evento.length === 0) { + pais = pais.filter((item) => item !== delete_country); } } const defaultClient = new hubspot.Client({ accessToken: config.hubspot.API_KEY }); const updatedContact = await defaultClient.crm.contacts.basicApi.update(hbContact.id, { properties: { - ciudad_del_evento, - //pais, - //ano_del_congreso, - tipo_de_evento: "Congreso", + ciudad_del_evento: ciudad_del_evento.join(";"), + pais: pais.join(";"), + ano_del_congreso: ano_del_congreso.join(";"), }, }); - return; + return updatedContact; } +/***************************************************************************** */ + async function addMemberToList(listId, member) { let hbContact = await _getMemberByEmail(member.email); if (hbContact && hbContact.id) { @@ -356,20 +340,6 @@ async function deleteMemberFromList(listId, userEmail, inscription) { let hbContact = await _getMemberByEmail(userEmail); if (hbContact && hbContact.id) { await _deleteInscriptionFromMember(hbContact, inscription); - - /* - _deleteInscriptionFromMember(hbContact, inscription).then(() => { - // ¿debo archivarlo? - // si-> _deleteMemeber(userEmail); - }) - if (_hbContactWithLastInscription(hbContact)) { - return _deleteMember(userEmail); - } else { - return _updateMember(email, inscription) - } - } else { - return _createMember(member); - }*/ } return; } diff --git a/helpers/push.helper.js b/helpers/push.helper.js index f992ac1..94441c1 100644 --- a/helpers/push.helper.js +++ b/helpers/push.helper.js @@ -1,7 +1,9 @@ const { Expo } = require('expo-server-sdk'); // Create a new Expo SDK client -const expo = new Expo(); +const expo = new Expo({ + useFcmV1: true // this can be set to true in order to use the FCM v1 API +}); const createPushMessage = (data) => { const pushMessage = { diff --git a/modules/auth/auth.controller.js b/modules/auth/auth.controller.js index ff06f70..20be072 100644 --- a/modules/auth/auth.controller.js +++ b/modules/auth/auth.controller.js @@ -8,7 +8,7 @@ const crypto = require("crypto"); const securityHelper = require("../../helpers/security.helper"); const authService = require("./auth.service"); const userService = require("./user.service"); -const marketing = require("../../helpers/sendinblue.helper"); +const marketing = require("../../helpers/hubspot.helper"); const marketingService = require("../events/marketing_list.service"); const eventInscriptionService = require("../events/events_inscriptions.service"); const { RequestContactImportNewList } = require("sib-api-v3-sdk"); diff --git a/modules/events/event.controller.js b/modules/events/event.controller.js index 114effe..61710a7 100644 --- a/modules/events/event.controller.js +++ b/modules/events/event.controller.js @@ -298,19 +298,27 @@ const extraControllers = { httpStatus.NOT_FOUND ); - try { - //Eliminamos miembro de la lista de mailchimp a la que está asociado + if (marketingListIdOverflow) { + try { + //Eliminamos miembro de la lista de mailchimp a la que está asociado - await marketingListService._deleteMember(marketingListIdOverflow, inscription.user.email); // inscription.marketing_memberId); - } catch (error) { - console.log("validate incription", error); + await marketingListService._deleteMember(marketingListIdOverflow, inscription.user.email); // inscription.marketing_memberId); + } catch (error) { + console.log("validate incription", error); + } } //Mandar correo de confirmacion de inscripcion try { var member = generateMemberInscription(inscription.user, inscription, inscription.reservation); + + /**** */ + member.marketing_memberId = await eventInscriptionService._addMember(marketingListIdEvent, member); eventInscriptionService._updateMarketingMemberOfInscription(inscription.id, member.marketing_memberId); + + /*** */ + member.qrConfig = QRHelper.generateQRConfig(member); member.qrCode = await QRHelper.getInscriptionQRCode(member.qrConfig); member.qrCodeUrl = QRHelper.getInscriptionQRCodeUrl(inscription.id); diff --git a/modules/events/events_inscriptions.controller.js b/modules/events/events_inscriptions.controller.js index 7023509..2499988 100644 --- a/modules/events/events_inscriptions.controller.js +++ b/modules/events/events_inscriptions.controller.js @@ -8,7 +8,11 @@ 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 { + extractParamsFromRequest, + handleResultResponse, + handleErrorResponse, +} = require("../../helpers/controller.helper"); const { data } = require("../../core/logger"); const lodash = require("lodash"); const userService = require("../auth/user.service"); @@ -17,41 +21,34 @@ const userService = require("../auth/user.service"); 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; + if (inscription.type === "online") return true; //En caso de inscripciones const EventOrReservationChangeId = inscription.reservationId ? inscription.reservationId : inscription.overflowEventId - ? inscription.overflowEventId - : inscription.eventId; + ? inscription.overflowEventId + : inscription.eventId; - let NewConfirmed = 0; + 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 - ); + 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 + //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 - ); + 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; @@ -61,9 +58,9 @@ async function refreshConfirmed(inscription) { EventOrReservationChangeId ); - //No se tienen en cuenta los marketinglist de las otras estructuras si lo tuviera seria esto + //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) { @@ -78,7 +75,7 @@ async function refreshConfirmed(inscription) { if (!(await eventService._updateConfirmedEvent(EventOrReservationChangeId, NewConfirmed))) { throw new Error("Error al eliminar inscripción, no puedo cambiar confirmados a la inscripcion"); } - }; + } } const extraControllers = { @@ -88,21 +85,19 @@ const extraControllers = { 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 + //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"; + 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))) + //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 + 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 ? "app" : "web", //En el caso de tener ya usuario viene por APP sino viene por web 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 @@ -162,16 +157,15 @@ const extraControllers = { ); if (dataInscription.inscription) { - console.log("esta es la inscripcion que ya tengo>>>>", - 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))) + 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( @@ -198,11 +192,10 @@ const extraControllers = { 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(); }, @@ -226,17 +219,16 @@ const extraControllers = { 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.user.profile !== "tutor") if (inscription.reservation) inscription.reservation.assistants = null; if (inscription.reservation === null) { - console.log('asigno green'); - inscription.color = 'green'; + console.log("asigno green"); + inscription.color = "green"; /* parche */ inscription.reservation = { - color: 'green', - description: 'Entrada', + color: "green", + description: "Entrada", }; } @@ -268,7 +260,6 @@ const extraControllers = { } }, - /////////////////////////////////////////////////////////////////// //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 @@ -280,13 +271,7 @@ const extraControllers = { let dataInscription = res.locals.dataInscription; if (!dataInscription || !dataInscription.event) - return handleResultResponse( - "Error prepareDataInscription requerida", - null, - params, - res, - httpStatus.NOT_FOUND - ); + return handleResultResponse("Error prepareDataInscription requerida", null, params, res, httpStatus.NOT_FOUND); let dataUser = res.locals.dataUser; if (!dataUser) @@ -302,7 +287,6 @@ const extraControllers = { ); 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") { @@ -317,23 +301,22 @@ const extraControllers = { 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) + 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>>>'); + console.log("actualizamos afoorooo>>>"); //Actualizamos aforo del evento y creamos inscripcion if ( await eventService._updateConfirmedEvent( @@ -350,10 +333,11 @@ const extraControllers = { dataInscription.source, null, null - ) - } catch (error) { console.log('SSSSSSSSSSSSSSSSSSSSSSSSS', error) } - } - else + ); + } catch (error) { + console.log("SSSSSSSSSSSSSSSSSSSSSSSSS", error); + } + } else return handleResultResponse( "No se ha podido actualizar el aforo del evento", null, @@ -361,7 +345,7 @@ const extraControllers = { res, httpStatus.NOT_FOUND ); - console.log('Inscripcion hecha>>>', dataInscription.inscription); + console.log("Inscripcion hecha>>>", dataInscription.inscription); //Ponemos el evento en SOLD_OUT if (dataInscription.event.assistants == inscriptionsWithoutReservationAndOverflowCount) @@ -381,7 +365,7 @@ const extraControllers = { res, httpStatus.NOT_FOUND ); - }; + } //recuperamos la cantidad de apuntados al evento overflow (lista de espera) let ConfirmedWaitList = await eventInscriptionService._getCountInscriptionsWithOverflowEventId( @@ -389,8 +373,10 @@ const extraControllers = { ); //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 + 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 @@ -403,12 +389,10 @@ const extraControllers = { res, httpStatus.NOT_FOUND ); - }; + } //Creamos inscripción a lista de espera - if ( - await eventService._updateConfirmedEvent(dataInscription.event.overflow_eventId, ConfirmedWaitList) - ) { + if (await eventService._updateConfirmedEvent(dataInscription.event.overflow_eventId, ConfirmedWaitList)) { dataInscription.inscription = await eventInscriptionService._createInscription( dataInscription.event.id, dataUser.userResult.user.id, @@ -421,7 +405,7 @@ const extraControllers = { } else { console.log("No se ha podido actualizar el aforo de la lista de espera del evento"); return handleResultResponse( - "o se ha podido actualizar el aforo de la lista de espera del evento", + "No se ha podido actualizar el aforo de la lista de espera del evento", null, params, res, @@ -429,28 +413,35 @@ const extraControllers = { ); } } //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 SenINBlue>>>>>>>>>>>>>>>>><<', error); } + } 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); } - + } catch (error) { + console.log("Se ha producido un error al enviar mail>>>>>>>>>>>>>>>>><<", error); + } 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); + 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; @@ -469,9 +460,15 @@ const extraControllers = { if (!inscription || 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 + //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) + 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) { @@ -479,41 +476,56 @@ const extraControllers = { //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) { + 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); + 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")) { + 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); + return handleResultResponse( + "No se ha podido actualizar el aforo del evento, para reservar las plazas solicitadas", + null, + params, + res, + httpStatus.NOT_FOUND + ); } } - else //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 - refreshConfirmed(inscription); - } - else - return handleResultResponse("No se pudo eliminar inscripción", null, params, res, httpStatus.NOT_FOUND); - + 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); - } catch (error) { console.log('Se ha producido un error al eliminar de SenINBlue>>>>>>>>>>>>>>>>><<', error); } + 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); } + } 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); @@ -521,7 +533,6 @@ const extraControllers = { }, deleteInscriptionsByUser: async (req, res, next) => { - try { //const context = buildContext(req, config); //const user = context.user ? context.user : null; @@ -538,10 +549,7 @@ const extraControllers = { } catch (error) { console.error(error); } - } - - - + }, }; module.exports = generateControllers(eventInscriptionService, extraControllers, controllerOptions); diff --git a/modules/events/events_inscriptions.service.js b/modules/events/events_inscriptions.service.js index 7c068ef..f2bb902 100644 --- a/modules/events/events_inscriptions.service.js +++ b/modules/events/events_inscriptions.service.js @@ -5,7 +5,6 @@ const _ = require("lodash"); const moment = require("moment"); const { generateService, parseParamsToFindOptions } = require("../../helpers/service.helper"); const models = require("../../core/models"); -const marketing = require("../../helpers/sendinblue.helper"); const Sequelize = require("sequelize"); const xlsx = require("node-xlsx"); const fs = require("fs"); @@ -37,9 +36,9 @@ const extraMethods = { _fillInscriptionColor: (inscription) => { if (inscription && inscription.type) { const isVirtual = inscription.type === "online" || inscription.type === "online group"; - if ((inscription.reservationId === null) && (!isVirtual)) { + if (inscription.reservationId === null && !isVirtual) { // Inscripción normal - inscription.color = 'green'; + inscription.color = "green"; } } @@ -229,7 +228,6 @@ const extraMethods = { }, _deleteInscriptionByUser: (userId) => { - return models.EventInscription.destroy({ where: { userId: userId, @@ -239,7 +237,6 @@ const extraMethods = { //Elimina todas las inscripciones de una determinada reserva/invitacion _deleteInscriptionsByReservation: (reservationId) => { - return models.EventInscription.destroy({ where: { reservationId: reservationId, @@ -280,23 +277,19 @@ const extraMethods = { ); }, - _getInscriptionsWithoutMemberId: (eventId) => { return models.EventInscription.scope(["includeEventAndVenue", "includeReservation", "defaultScope"]).findAll({ where: { eventId: eventId, - marketing_memberId: null + marketing_memberId: null, }, }); }, _getInscriptionsExcel: (user, eventId, callback) => { - console.log("DESCARGA EXCEL INSCRIPCIONES TOTALES>>>>>>>> "); console.log(">>>>>>>>>>>>>>>>>>>>>> ', dataInscription); + console.log("entro _generateMarketingDTO >>> ", dataInscription); let { event, inscription, user, reservation } = dataInscription; let inscriptionDTO = {}; //En el caso de generar el MarketingDTO para el ticket de la APP, fallaba porque el propio dataInscription, es la inscription y de el cuelgan user, event y reservation //Sin embargo cuando se llama desde addMarketingList la inscription cualga de dataInscripcion como el resto de elementos - if (dataInscription) - if (!inscription) - inscription = dataInscription; + if (dataInscription) if (!inscription) inscription = dataInscription; if (!event) { - throw new Error('Falta datos del evento en la inscripción (_generateMarketingDTO)'); + throw new Error("Falta datos del evento en la inscripción (_generateMarketingDTO)"); } - if (!event.marketing_list) { - console.warn('Falta rellenar la lista de Sendinblue en el evento (_generateMarketingDTO)', event.name); - } + /*if (!event.marketing_list) { <-- YA NO HACE FALTA CON HUBSPOT + console.warn("Falta rellenar la lista de Sendinblue en el evento (_generateMarketingDTO)", event.name); + }*/ if (inscription) { inscriptionDTO.id = inscription.id; @@ -41,6 +39,8 @@ function _generateMarketingDTO(dataInscription) { inscriptionDTO.event_name = event.name ? event.name : "N/A"; inscriptionDTO.event_date = event.init_date ? event.init_date : "N/A"; inscriptionDTO.event_marketing_list = event ? event.marketing_list : null; + inscriptionDTO.event_country = event ? event.location.country : null; + inscriptionDTO.event_city = event ? event.location.city : null; inscriptionDTO.date_inscription = inscription.date; inscriptionDTO.code_ticket = inscription.code_ticket; inscriptionDTO.validated = inscription.validated; @@ -51,18 +51,24 @@ function _generateMarketingDTO(dataInscription) { inscriptionDTO.qrConfig = null; inscriptionDTO.qrCode = null; + /** HUBSPOT */ + // inscriptionDTO.event_city = event.venue ? event.venue.city : null; + // inscriptionDTO.event_country = event.venue ? event.venue.country : null; + if (user) { - //Era para mailchimp + //Era para mailchimp /// inscriptionDTO.marketing_memberId = inscription.marketing_memberId ? inscription.marketing_memberId : null; inscriptionDTO.email = user.email; inscriptionDTO.name = user.name; inscriptionDTO.surname = user.surname; + inscriptionDTO.phone = user.phone; // <-- HUBSPOT + inscriptionDTO.profile = user.profile; // <-- HUBSPOT inscriptionDTO.userId = user.id; - inscriptionDTO.entity = reservation && reservation.Entity ? reservation.Entity.name : (user.Entity ? user.Entity.name : user.entityId); - }; - + inscriptionDTO.entity = + reservation && reservation.Entity ? reservation.Entity.name : user.Entity ? user.Entity.name : user.entityId; + } } - console.log('salgo>>>', inscriptionDTO); + console.log("salgo>>>", inscriptionDTO); return inscriptionDTO; } @@ -70,64 +76,53 @@ function sleep(time) { return new Promise((resolve) => setTimeout(resolve, time)); } - async function _addMember(inscriptionDTO) { - console.debug('>>>> _addMember', inscriptionDTO.email); - console.debug('>>>> event_marketing_list', inscriptionDTO.event_marketing_list); + console.debug(">>>> _addMember", inscriptionDTO.email); + console.debug(">>>> event_marketing_list", inscriptionDTO.event_marketing_list); // console.debug(member); return new Promise(function (resolve, reject) { - if (!inscriptionDTO.event_marketing_list) { - // || !member.validated) { - resolve(inscriptionDTO); - } else { - marketing - .addMemberToList(inscriptionDTO.event_marketing_list, inscriptionDTO) - .then(function (result) { - resolve(result.ID); - }) - .catch(function (error) { - reject(error); - }); - } + //if (!inscriptionDTO.event_marketing_list) { + // || !member.validated) { + //resolve(inscriptionDTO); + //} else { + /** + * HUBSPOT + */ + + marketing + .addMemberToList(inscriptionDTO.event_marketing_list, inscriptionDTO) + .then(function (result) { + resolve(result.ID); + }) + .catch(function (error) { + reject(error); + }); + //} }); } -async function _deleteMember(idLista, email) { - console.debug( - "Elimino miembro de la lista de marketing>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<", - email, - idLista, - ); +async function _deleteMember(idLista, email, inscription = undefined) { + console.debug("Elimino miembro de la lista de marketing>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<", email, idLista); return new Promise(function (resolve, reject) { - if (!idLista || !email) { - resolve(); - } else { - resolve(marketing.deleteMemberFromList(idLista, email)); - } + resolve(marketing.deleteMemberFromList(idLista, email, inscription)); }); } - async function addMarketingList(dataUser, dataInscription) { dataInscription.user = dataUser.userResult.user; return _addMember(_generateMarketingDTO(dataInscription)); } - - - - async function syncronizeEventWithMarketingList(eventId) { let result = false; try { let inscriptionsToSync = await eventInscriptionService._getInscriptionsWithoutMemberId(eventId); - for (var i = 0; i < inscriptionsToSync.length; i++) { const item = inscriptionsToSync[i].get({ - plain: true + plain: true, }); //Adaptamos el objeto a lo que espera _generateMarketingDTO // dataInscription {incription:{...}, event:{...}, reservation:{...}, user:{...}} @@ -139,8 +134,7 @@ async function syncronizeEventWithMarketingList(eventId) { // console.log(marketingDTO) // _deleteMember(marketingDTO.event_marketing_list, marketingDTO.email) }); - - }; + } result = true; return result; @@ -149,24 +143,23 @@ async function syncronizeEventWithMarketingList(eventId) { } } - function userToMarketingDTO(user) { const result = {}; - result.email = user.email ? user.email : ''; - result.name = user.name ? user.name : ''; - result.surname = user.surname ? user.surname : ''; - result.userId = user.id ? user.id : ''; - result.entity = user.Entity ? user.Entity.name : ''; + result.email = user.email ? user.email : ""; + result.name = user.name ? user.name : ""; + result.surname = user.surname ? user.surname : ""; + result.phone = user.phone ? user.phone : ""; + result.userId = user.id ? user.id : ""; + result.profile = user.profile ? user.profile : ""; + result.entity = user.Entity ? user.Entity.name : ""; return result; } - module.exports = { syncronizeEventWithMarketingList, addMarketingList, _deleteMember, _generateMarketingDTO, userToMarketingDTO, - }; diff --git a/package.json b/package.json index 7d963e7..f50e0af 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "license": "ISC", "main": "server.js", "scripts": { - "start": "NODE_ENV=development nodemon server.js", + "start": "NODE_ENV=development nodemon --inspect=0.0.0.0 server.js", "start:prod": "NODE_ENV=production pm2 start server.js -n 'api3' -i 4 --node-args='--max_old_space_size=4096'", "lint": "eslint **/*.js --quiet", "test": "echo \"Error: no test specified\" && exit 1" @@ -20,6 +20,7 @@ "nodemon": "^1.18.9" }, "dependencies": { + "@hubspot/api-client": "^11.1.0", "apicache": "^1.4.0", "args-list": "^0.3.3", "async": "^2.6.2",