Email notification

This commit is contained in:
Gowtham M 2025-11-15 11:28:01 +05:30
parent 15c250d28a
commit 5bd1460966
6 changed files with 171 additions and 3 deletions

View File

@ -20,7 +20,7 @@ const path = require("path");
exports.testEmail = async (req, res) => {
placeHolderData = {
contact_name : 'Gowtham',
portal_url : process.env.BASE_URL,
portal_url : process.env.FE_BASE_URL,
username : '--',
password : '--',
support_email : '--',
@ -309,6 +309,12 @@ exports.getAllEstablishments = async (req, res) => {
// Fetch Data
const data = await Establishment.findAll({
where: whereClause,
attributes: {
include: [
[
Sequelize.literal(`(SELECT COUNT(*) FROM establishment_products ep WHERE ep.establishment_id = establishments.id)`),"product_count" ]
]
},
include: [
{ model: CityTown, as: "establishment_city", attributes: ["name"] },
{ model: Emirate, as: "establishment_emirate", attributes: ["name"] },

View File

@ -11,10 +11,12 @@ const Product = db.Product;
const CityTown = db.CityTown;
const Emirate = db.Emirate;
const QuarterlyWindowsConfiguration = db.QuarterlyWindowsConfiguration;
const User = db.user;
const ExcelJS = require("exceljs");
const { Op } = require("sequelize");
const { Sequelize } = require("sequelize");
const { sendEmail } = require("../services/email.service");
const { sendEmailService } = require("../services/email.service");
const { getQuarterPeriods } = require("../services/quarterService");
@ -105,10 +107,94 @@ exports.createSubmission = async (req, res) => {
}
// const result = await Submission.findByPk(submission.id, {
// include: [{ model: SubmissionProduct, as: "products" },{ model: EstablishmentUser,as: "created_user",attributes: ["name"],}],
// });
// //send email
// const EstablishmentData = await Establishment.findOne({ where: { id :result['establishment_id'] } });
// const EstablishmentUserData = await EstablishmentUser.findAll({ where: { establishment_id :result['establishment_id'] , is_active : 1} });
// const AdminUsersData = await User.findAll({ where: { is_active : 1} });
// for await (const userObj of EstablishmentUserData)
// {
// placeHolderData = {
// user_name : userObj.name,
// quarter : result['quarter'],
// year : result['year'],
// establishment_name : EstablishmentData['factory_name'],
// submitted_by : result['created_user.name'],
// submission_date : result['created_at'],
// support_email : process.env.SUPPORT_EMAIL,
// support_phone : process.env.SUPPORT_PHONE,
// portal_url : process.env.FE_BASE_URL,
// }
// await sendEmailService(userObj.email, 'submission_created_mail_to_establishment_user', placeHolderData);
// }
// for await (const userObj of AdminUsersData)
// {
// placeHolderData = {
// user_name : userObj.name,
// quarter : result['quarter'],
// year : result['year'],
// establishment_name : EstablishmentData['factory_name'],
// submitted_by : result['created_user.name'],
// submission_date : result['created_at'],
// support_email : process.env.SUPPORT_EMAIL,
// support_phone : process.env.SUPPORT_PHONE,
// portal_url : process.env.FE_BASE_URL,
// }
// await sendEmailService(userObj.email, 'submission_created_mail_to_admin', placeHolderData);
// }
const result = await Submission.findByPk(submission.id, {
include: [{ model: SubmissionProduct, as: "products" }],
include: [
{ model: SubmissionProduct, as: "products" },
{ model: EstablishmentUser, as: "created_user", attributes: ["name"] },
],
});
// Fetch required data for email
const EstablishmentData = await Establishment.findOne({ where: { id: result.establishment_id }});
const EstablishmentUserData = await EstablishmentUser.findAll({where: { establishment_id: result.establishment_id, is_active: 1 }});
const AdminUsersData = await User.findAll({where: { is_active: 1 }});
// Shared placeholder data
const basePlaceholder = {
quarter: result.quarter,
year: result.year,
establishment_name: EstablishmentData.factory_name,
submitted_by: result.created_user?.name,
submission_date: result.created_at,
support_email: process.env.SUPPORT_EMAIL,
support_phone: process.env.SUPPORT_PHONE,
portal_url: process.env.FE_BASE_URL
};
// --- SEND EMAILS TO ESTABLISHMENT USERS ---
const establishmentEmailPromises = EstablishmentUserData.map((userObj) => {
return sendEmailService(userObj.email,"submission_created_mail_to_establishment_user",{...basePlaceholder,user_name: userObj.name,});
});
// --- SEND EMAILS TO ADMINS ---
const adminEmailPromises = AdminUsersData.map((userObj) => {
return sendEmailService(userObj.email,"submission_created_mail_to_admin",{...basePlaceholder,user_name: userObj.name,} );
});
// Execute ALL emails in parallel
await Promise.all([
...establishmentEmailPromises,
...adminEmailPromises,
]);
res.status(201).json({ status: "success", data: result });
} catch (err) {
@ -634,6 +720,9 @@ exports.approveOrRejectSubmission = async (req, res) => {
const { id } = req.params;
approve_reject_status = req.body.approve_reject_status;
reject_reason = req.body.reject_reason;
approve_or_reject_by = req.body.approve_or_reject_by;
if(approve_reject_status == 1)
{
statusString = 'Approved';
@ -647,7 +736,52 @@ exports.approveOrRejectSubmission = async (req, res) => {
return res.status(404).json({ status: "failed", message: "Submission not found" });
// Update submission main data
const result = await submission.update({ approve_reject_status : approve_reject_status , status : statusString });
const result = await submission.update({ approve_reject_status : approve_reject_status , status : statusString, reject_reason, approve_or_reject_by });
//send email to establishment user
const EstablishmentData = await Establishment.findOne({ where: { id :result['establishment_id'] } });
const EstablishmentUserData = await EstablishmentUser.findAll({ where: { establishment_id :result['establishment_id'] , is_active : 1} });
if(approve_reject_status == 1)
{
for await (const userObj of EstablishmentUserData)
{
placeHolderData = {
user_name : userObj.name,
portal_url : process.env.FE_BASE_URL,
quarter : result['quarter'],
year : result['year'],
establishment_name : EstablishmentData['factory_name'],
submission_date : result['created_at'],
rejection_reason : result['reject_reason'],
support_email : process.env.SUPPORT_EMAIL,
support_phone : process.env.SUPPORT_PHONE,
}
await sendEmailService(userObj.email, 'submission_approved_mail_to_establishment_user', placeHolderData);
}
}else{
for await (const userObj of EstablishmentUserData)
{
placeHolderData = {
user_name : userObj.name,
portal_url : process.env.FE_BASE_URL,
quarter : result['quarter'],
year : result['year'],
establishment_name : EstablishmentData['factory_name'],
submission_date : result['created_at'],
rejection_reason : result['reject_reason'],
support_email : process.env.SUPPORT_EMAIL,
support_phone : process.env.SUPPORT_PHONE,
}
await sendEmailService(userObj.email, 'submission_rejected_mail_to_establishment_user', placeHolderData);
}
}
res.status(200).json({
status: "success",

View File

@ -66,6 +66,16 @@ module.exports = (sequelize, DataTypes) => {
tableName: "establishment_users",
}
);
EstablishmentUser.associate = (models) => {
EstablishmentUser.belongsTo(models.Establishment, {
foreignKey: 'establishment_id',
as: 'establishments',
});
};
return EstablishmentUser;
};

View File

@ -32,6 +32,12 @@ module.exports = (sequelize, DataTypes) => {
approve_reject_status: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
approve_or_reject_by: {
type: DataTypes.INTEGER,
},
reject_reason: {
type: DataTypes.STRING(255),
},
status: {
type: DataTypes.STRING(50),

View File

@ -30,6 +30,10 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.DATE,
allowNull: true,
},
is_active: {
type: DataTypes.BOOLEAN,
defaultValue: true,
},
});
return User;

View File

@ -1838,6 +1838,7 @@ router.post("/unit-master/uploadCSV",[ verifySignature, verifyToken, upload.sing
* non_emirati_female: { type: integer }
* total_emirati: { type: integer }
* total_employees: { type: integer }
* created_by: { type: integer }
* products:
* type: array
* items:
@ -1910,6 +1911,7 @@ router.post("/submissions",[verifySignature, verifyToken], submissionController.
* non_emirati_female: { type: integer }
* total_emirati: { type: integer }
* total_employees: { type: integer }
* updated_by: { type: integer }
* products:
* type: array
* items:
@ -2143,6 +2145,12 @@ router.put("/enableOrDisableSubmissionEditAccess/:id",[verifySignature, verifyTo
* approve_reject_status:
* type: integer
* description: 1 for Approve, 2 for Reject
* reject_reason:
* type: string
* description: rejection reason
* approve_or_reject_by:
* type: integer
* description: logged admin user primary id
* responses:
* 200:
* description: Updated successfully