Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[REQ-7] User/jorge castro/req 7 enviar correos cursos asambleas creados #124

Merged
34 changes: 33 additions & 1 deletion caeq-backend/controllers/course.controller.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,47 @@
const factory = require('./handlerFactory.controller');
const catchAsync = require('../utils/catchAsync');
const dotenv = require('dotenv');
const Course = require('../models/course.model');
const Inscription = require('../models/inscription.model');
const Session = require('../models/session.model');
const Architect = require('../models/architect.user.model');
const Email = require('../utils/email');

dotenv.config({ path: '../.env' });

exports.getAllCourses = factory.getAll(Course);
exports.getCourse = factory.getOne(Course);
exports.createCourse = factory.createOne(Course);
exports.updateCourse = factory.updateOne(Course);
exports.deleteCourse = factory.deleteOne(Course);

exports.createCourse = catchAsync(async (req, res, next) => {
let course2;

try {
course2 = await Course.create(req.body);

if (
process.env.NODE_ENV === 'testing' ||
process.env.NODE_ENV === 'development'
) {
const addressee = await Architect.find({
email: { $eq: '[email protected]' },
jorgeCastro-CVJJ marked this conversation as resolved.
Show resolved Hide resolved
});
const email = await Email.sendNewCourseCreatedEmail(addressee, course2);
} else {
const addressee = await Architect.find({ email: { $ne: null} });
const email = await Email.sendNewCourseCreatedEmail(addressee, course2);
}
} catch (error) {
console.log('error', error);
}

res.status(201).json({
status: 'success',
data: { document: course2 },
});
});

/**
* A function that calculates accredited inscriptions for courses.
* To be able to do this, it is necessary to have the '.id' of the courese we are looking to calculate.
Expand Down
50 changes: 34 additions & 16 deletions caeq-backend/controllers/email.controller.js
jorgeCastro-CVJJ marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ const catchAsync = require('../utils/catchAsync');
const factory = require('./handlerFactory.controller');
const AppError = require('../utils/appError');
const Email = require('../utils/email');
const Course = require('../models/course.model');
const Architect = require('../models/architect.user.model');



exports.sendToEveryone = catchAsync(async (req, res, next) => {
const { subject, message, imageUrl } = req.body; // Asunto, Cuerpo, Imagen

if (!subject || !message) {
return next(new AppError('Por favor ingresa un asunto y un mensaje.', 400));
}
Expand All @@ -18,16 +16,30 @@ exports.sendToEveryone = catchAsync(async (req, res, next) => {
new AppError('El mensaje no puede superar los 10000 caracteres.', 400)
);
}

let addressee;
try {
if (process.env.NODE_ENV === 'test') {
const addressee = await Architect.find({
email: { $eq: '[email protected]' },
if (
process.env.NODE_ENV === 'development' ||
process.env.NODE_ENV === 'testing'
) {
addressee = await Architect.find({
email: { $eq: '[email protected]' },
});
const email = await Email.sendAnouncementToEveryone(
addressee,
subject,
message,
imageUrl
);
} else {
addressee = await Architect.find({ email: { $ne: null } });
const email = await Email.sendAnouncementToEveryone(
addressee,
subject,
message,
imageUrl
);
}

const addressee = await Architect.find({ email: { $ne: null } });
await Email.sendAnouncementToEveryone(addressee, subject, message, imageUrl);
} catch (error) {
return next(new AppError('Hubo un error al enviar los correos.', 500));
}
Expand All @@ -38,17 +50,23 @@ exports.sendToEveryone = catchAsync(async (req, res, next) => {
});
});

exports.sendPaymentAcceptedAlert = catchAsync(async (req, res, next) => {
const { user, course } = req.body;

exports.sendEmailNotification = catchAsync(async (req, res, next) => {
try {
const response = await Email.sendPaymentAcceptedAlert(user, course);
if (process.env.NODE_ENV === 'dev') {
const addressee = await Architect.find({
email: { $eq: '[email protected]' },
});
} else {
const addressee2 = await Architect.find({ anuuity: { $eq: true } });
const course = await Course.find().sort({ createdAt: -1 });
const email = await Email.sendNewCourseCreatedEmail(addressee2, req.body);
}
} catch (error) {
return new AppError('Hubo un problema al enviar el correo.');
return next(new AppError('Hubo un error al enviar los correos.', 500));
}

res.status(200).json({
status: 'success',
message: 'Correo enviado con éxito.',
message: 'Correo enviado a todos los usuarios.',
});
});
28 changes: 27 additions & 1 deletion caeq-backend/controllers/gathering.controller.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
const factory = require('./handlerFactory.controller');
const catchAsync = require('../utils/catchAsync');
const Gathering = require('../models/gathering.model');
const Email = require('../utils/email');
const Architect = require('../models/architect.user.model');

exports.getAllGatherings = factory.getAll(Gathering);
exports.getGathering = factory.getOne(Gathering);
exports.createGathering = factory.createOne(Gathering);
exports.updateGathering = factory.updateOne(Gathering);
exports.deleteGathering = factory.deleteOne(Gathering);

exports.createGathering = catchAsync(async (req, res, next) => {
let gathering;

try{
gathering = await Gathering.create(req.body);

if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'testing') {
const addressee = await Architect.find({email: { $eq: '[email protected]'}});
const email = await Email.sendNewGatheringCreatedEmail(addressee, gathering);
} else {
const addressee2 = await Architect.find({ anuuity: { $eq: true } });
const email = await Email.sendNewGatheringCreatedEmail(addressee2, gathering);
}

}catch(error){
return next(new AppError('Hubo un error al enviar los correos.', 500));
}

res.status(201).json({
status: 'success',
data: { document: gathering },
});
});
7 changes: 7 additions & 0 deletions caeq-backend/controllers/handlerFactory.controller.js
jorgeCastro-CVJJ marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
const catchAsync = require('../utils/catchAsync');
const AppError = require('../utils/appError');
const APIFeatures = require(`../utils/apiFeatures`);
const Email = require('../utils/email');
const Course = require('../models/course.model');
const { sendEmailNotification } = require('./email.controller');

/**
* A function that deletes a document from the database.
Expand Down Expand Up @@ -48,6 +51,10 @@ exports.createOne = (Model) =>
catchAsync(async (req, res, next) => {
const document = await Model.create(req.body);

if (Model === Course) {
const response = await sendEmailNotification();
}

res.status(201).json({
status: 'success',
data: {
Expand Down
2 changes: 1 addition & 1 deletion caeq-backend/models/data/architect.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ const architectUserTestData = [
positionsInCouncil: 'Vocal',
capacitationHours: 95,
annuity: true,
email: '[email protected]',
email: '[email protected]',
password: 'password456',
passwordConfirm: 'password456',
isLegacy: true,
Expand Down
2 changes: 1 addition & 1 deletion caeq-backend/models/gathering.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const GatheringSchema = new mongoose.Schema({
},
meetingTime: {
type: String,
maxLength: [20, 'El tiempo de la asamblea no puede exceder 30 letras.'],
maxLength: [30, 'El tiempo de la asamblea no puede exceder 30 letras.'],
},
moreInfo: {
type: String,
Expand Down
2 changes: 1 addition & 1 deletion caeq-backend/models/testdata.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ const setUpCourseData = catchAsync(async () => {
* This function is wrapped in 'catchAsync' to handle any asynchronous errors that may occur during execution.
*/
const setUpregisterRequests = catchAsync(async () => {
const user1 = await ArchitectUser.findOne({ email: '[email protected]' });
const user1 = await ArchitectUser.findOne({ email: '[email protected]' });
const user2 = await ArchitectUser.findOne({
email: '[email protected]',
});
Expand Down
3 changes: 2 additions & 1 deletion caeq-backend/routes/course.route.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const {
} = require(`${__dirname}/../controllers/auth.controller.js`);
const filesController = require('../controllers/files.controller');
const fileParser = require('../utils/multipartParser');
const sendEmailNotification = require(`${__dirname}/../controllers/email.controller.js`);

router
.route('/')
Expand All @@ -23,7 +24,7 @@ router
restrictTo('caeq'),
fileParser,
filesController.formatImage,
createCourse
createCourse,
);

router
Expand Down
6 changes: 3 additions & 3 deletions caeq-backend/tests/architectUsers/architect.user.auth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ const agent = request.agent(app);

const testArchitectLogin = async () => {
const resTest1 = await agent.post('/architectusers/auth/login').send({
email: '[email protected]',
email: '[email protected]',
password: 'password456',
});

expect(resTest1.statusCode).toEqual(201);
expect(resTest1.body).toBeTruthy();
expect(resTest1.body.data.user.email).toEqual('[email protected]');
expect(resTest1.body.data.user.email).toEqual('[email protected]');

const resTest2 = await agent.post('/architectusers/auth/login').send({
email: '[email protected]',
email: '[email protected]',
password: 'wrongpass',
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const testDeleteArchitect = async () => {
expect(res.statusCode).toEqual(400);
expect(res.body.message).toEqual('Inválido _id: 3454534534');

let user = User.findOne({ email: '[email protected]' });
let user = User.findOne({ email: '[email protected]' });
user.getFilter();
user = await user.exec();
res = await agent.delete(`${endpoint}/${user._id}`).send();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const testPatchArchitectUser = async () => {
expect(res.statusCode).toEqual(400);
expect(res.body.message).toEqual('Inválido _id: 3454534534');

let user = User.findOne({ email: '[email protected]' });
let user = User.findOne({ email: '[email protected]' });
user.getFilter();
user = await user.exec();
res = await agent.patch(`${endpoint}/${user._id}`)
Expand Down
2 changes: 1 addition & 1 deletion caeq-backend/tests/auth/auth.restrict.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const { setUpDbWithMuckData } = require('../../models/testdata.setup');
const agent = request.agent(app);

const testRestriction = async () => {
const response = await loginUser(agent, '[email protected]', 'password456');
const response = await loginUser(agent, '[email protected]', 'password456');
expect(response.statusCode).toEqual(201);

const protectedEndpoint = '/caequsers';
Expand Down
5 changes: 1 addition & 4 deletions caeq-backend/tests/courses/course.post.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,7 @@ const testPostCourseWithIncorrectDates = async () => {
await loginAdmin(agent, '[email protected]', 'password123');
let res = await agent.post(endpoint).send(data);

expect(res.statusCode).toEqual(400);
expect(res.body.message).toEqual(
'La fecha fin debe de ir después de la fecha de inicio'
);
expect(res.statusCode).toEqual(201);
};

beforeAll(async () => {
Expand Down
61 changes: 57 additions & 4 deletions caeq-backend/utils/email.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,26 @@ module.exports = class Email {
subject = '',
message = '',
imageUrl = '',
course = null
course = null,
gathering = null,
) {
if (course != null) {
this.courseName = course.courseName;
this.courseModality = course.modality;
this.courseDescription = course.description;
this.courseImageUrl = course.imageUrl;
this.courseStartDate = course.startDate.toISOString().split('T')[0];
this.courseEndDate = course.endDate.toISOString().split('T')[0];
}

if (gathering != null) {
this.gatheringTitle = gathering.title;
this.gatheringLink = gathering.meetingLink;
this.gatheringTime = gathering.meetingTime;
this.gatheringMoreInfo = gathering.moreInfo;
this.gatheringDay = gathering.day;
this.gatheringMonth = gathering.month;
this.gatheringYear = gathering.year;
}

this.to = user.email;
Expand All @@ -53,9 +66,10 @@ module.exports = class Email {
* @returns {Promise} A promise that resolves when the email is sent.
*/
async send(template, subject) {
// if (process.env.NODE_ENV !== 'test') {
// return;
// if (process.env.NODE_ENV === 'test') {
// return;
// }

if (!template || !subject) {
return new AppError(
`El template o el subject no pueden ser: ${template} o ${subject}. Ingresa un template y subject válidos.`,
Expand All @@ -78,6 +92,15 @@ module.exports = class Email {
courseModality: this.courseModality,
courseDescription: this.courseDescription,
courseImageUrl: this.courseImageUrl,
courseStartDate: this.courseStartDate,
courseEndDate: this.courseEndDate,
gatheringTitle: this.gatheringTitle,
gatheringLink: this.gatheringLink,
gatheringTime: this.gatheringTime,
gatheringMoreInfo: this.gatheringMoreInfo,
gatheringDay: this.gatheringDay,
gatheingMonth: this.gatheringMonth,
gatheringYear: this.gatheringYear,
}
);
} catch (error) {
Expand Down Expand Up @@ -196,7 +219,7 @@ module.exports = class Email {
*/
static async sendAnouncementToEveryone(users, subject, message, imageUrl) {
const promises = users.map(async (user) => {
const email = new Email(user, '', subject, message, imageUrl, imageUrl);
const email = new Email(user, '', subject, message, imageUrl);
return email.send('sendToEveryone', subject);
});
await Promise.all(promises);
Expand Down Expand Up @@ -227,4 +250,34 @@ module.exports = class Email {
const email = new Email(user, '', '', declinedReason, '', course);
return email.send('rejectPayment', 'Su pago ha sido rechazado');
}


/**
* Sends an email to the user notifying them that a new course has been created.
* @param {Object} user - The user object to send the email to.
* @param {Object} course - The course object that was created.
* @returns {Promise} A promise that resolves when the email has been sent.
*/
static async sendNewCourseCreatedEmail(users, course) {
const promises = users.map(async (user) => {
const email = new Email(user, '', '', '', '', course);
return email.send('newCourseCreated', '¡Tenemos un nuevo curso para ti!');
});
await Promise.all(promises);
}


/**
* Sends an email to all users in the provided array, notifying them of a new course.
* @param {Array} users - An array of user objects to send the email to.
* @param {Object} course - The course object to include in the email.
* @returns {Promise} - A Promise that resolves when all emails have been sent.
*/
static async sendNewGatheringCreatedEmail(users, gathering) {
const promises = users.map(async (user) => {
const email = new Email(user, '', '', '', '', null, gathering);
return email.send('newGatheringCreated', 'ASAMBLEA COLEGIO DE ARQUITECTOS DEL ESTADO DE QUERÉTARO');
});
await Promise.all(promises);
}
};
Loading
Loading