diff --git a/app/controllers/dashboard.controller.js b/app/controllers/dashboard.controller.js index d92a124..26a8560 100644 --- a/app/controllers/dashboard.controller.js +++ b/app/controllers/dashboard.controller.js @@ -158,7 +158,10 @@ exports.getEstablishmentDashboard = async (req, res) => { where: { year: q.year, quarter: q.quarter, - establishment_id: establishment_id + establishment_id: establishment_id , + status: { + [Op.ne]: "Draft", // not equal + }, } }); @@ -217,6 +220,8 @@ exports.adminDashboard = async (req, res) => { // only when query param not used → not started count let notStartedCount = 0; + whereCond.status = { [Op.ne]: "Draft" }; + const startedEstIds = await Submission.findAll({ where: whereCond, attributes: [[Sequelize.fn("DISTINCT", Sequelize.col("establishment_id")), "id"]], diff --git a/app/controllers/submission.controller.js b/app/controllers/submission.controller.js index a23207f..3c1855f 100644 --- a/app/controllers/submission.controller.js +++ b/app/controllers/submission.controller.js @@ -21,6 +21,92 @@ const { getQuarterPeriods } = require("../services/quarterService"); const { sanitizeForLog } = require("../utils/sanitize"); const logger = require("../services/logger"); + +const sendSubmissionCreatedEmails = async (submission_id) => { + try { + + // Fetch required data + const result = await Submission.findByPk(submission_id, { + include: [ + { model: SubmissionProduct, as: "products" }, + { model: EstablishmentUser, as: "created_user", attributes: ["name"] }, + ], + }); + + 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 }, + }); + + const formatSubmissionDate = (date) => { + const formatted = new Intl.DateTimeFormat("en-GB", { + day: "2-digit", + month: "short", + year: "numeric", + hour: "2-digit", + minute: "2-digit", + hour12: true, + timeZone: "Asia/Dubai", + }).format(new Date(date)); + + const [datePart, timePart] = formatted.split(", "); + return `${datePart}, ${timePart.toUpperCase()} GST (UAE)`; + }; + + const surveyData = await QuarterlyWindowsConfiguration.findOne({ + where: { year: result.year, quarter: result.quarter }, + }); + + // Shared placeholder + const basePlaceholder = { + quarter: result.quarter, + year: result.year, + establishment_name: EstablishmentData?.factory_name, + submitted_by: result.created_user?.name, + submission_date: formatSubmissionDate(result.created_at), + support_email: process.env.SUPPORT_EMAIL, + support_phone: process.env.SUPPORT_PHONE, + portal_url: process.env.FE_BASE_URL, + logo_url: `${process.env.APP_BASE_URL}/assets/FCSCLogo.png`, + survey_name: surveyData?.survey_name, + }; + + // Establishment users + const establishmentEmailPromises = EstablishmentUserData.map((userObj) => + sendEmailService( + userObj.email, + "submission_created_mail_to_establishment_user", + { ...basePlaceholder, user_name: userObj.name } + ) + ); + + // Admin users + const adminEmailPromises = AdminUsersData.map((userObj) => + sendEmailService( + userObj.email, + "submission_created_mail_to_admin", + { ...basePlaceholder, user_name: userObj.name } + ) + ); + + await Promise.all([ + ...establishmentEmailPromises, + ...adminEmailPromises, + ]); + + } catch (error) { + logger.error("Email sending failed:", error.message); + } +}; + + exports.createSubmission = async (req, res) => { try { @@ -147,113 +233,73 @@ exports.createSubmission = async (req, res) => { } + + //send submission email + if(submissionData.status == 'Submitted'){ + sendSubmissionCreatedEmails(submission.id); + } + + + + // const result = await Submission.findByPk(submission.id, { - // include: [{ model: SubmissionProduct, as: "products" },{ model: EstablishmentUser,as: "created_user",attributes: ["name"],}], + // 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 }}); - // //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} }); + // const formatSubmissionDate = (date) => { + // const formatted = new Intl.DateTimeFormat("en-GB", { + // day: "2-digit", + // month: "short", + // year: "numeric", + // hour: "2-digit", + // minute: "2-digit", + // hour12: true, + // timeZone: "Asia/Dubai" + // }).format(new Date(date)); + // const [datePart, timePart] = formatted.split(", "); + // const upperTime = timePart.toUpperCase(); + // return `${datePart}, ${upperTime} GST (UAE)`; + // }; - // 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, - // } + // const surveyData = await QuarterlyWindowsConfiguration.findOne({ where: { year :result['year'] , quarter : result['quarter'] } }); - // 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, - // logo_url: `${process.env.APP_BASE_URL}/assets/FCSCLogo.png` - // } - - // await sendEmailService(userObj.email, 'submission_created_mail_to_admin', placeHolderData); - // } - - - const result = await Submission.findByPk(submission.id, { - 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 }}); - - const formatSubmissionDate = (date) => { - const formatted = new Intl.DateTimeFormat("en-GB", { - day: "2-digit", - month: "short", - year: "numeric", - hour: "2-digit", - minute: "2-digit", - hour12: true, - timeZone: "Asia/Dubai" - }).format(new Date(date)); - const [datePart, timePart] = formatted.split(", "); - const upperTime = timePart.toUpperCase(); - return `${datePart}, ${upperTime} GST (UAE)`; - }; - - const surveyData = await QuarterlyWindowsConfiguration.findOne({ where: { year :result['year'] , quarter : result['quarter'] } }); - - // Shared placeholder data - const basePlaceholder = { - quarter: result.quarter, - year: result.year, - establishment_name: EstablishmentData.factory_name, - submitted_by: result.created_user?.name, - submission_date: formatSubmissionDate(result.created_at), - support_email: process.env.SUPPORT_EMAIL, - support_phone: process.env.SUPPORT_PHONE, - portal_url: process.env.FE_BASE_URL, - logo_url: `${process.env.APP_BASE_URL}/assets/FCSCLogo.png`, - survey_name: surveyData.survey_name - }; - - // --- 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, - ]); + // // Shared placeholder data + // const basePlaceholder = { + // quarter: result.quarter, + // year: result.year, + // establishment_name: EstablishmentData.factory_name, + // submitted_by: result.created_user?.name, + // submission_date: formatSubmissionDate(result.created_at), + // support_email: process.env.SUPPORT_EMAIL, + // support_phone: process.env.SUPPORT_PHONE, + // portal_url: process.env.FE_BASE_URL, + // logo_url: `${process.env.APP_BASE_URL}/assets/FCSCLogo.png`, + // survey_name: surveyData.survey_name + // }; + // // --- 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, + // ]); //send inserted data to FE @@ -304,7 +350,8 @@ exports.createSubmission = async (req, res) => { res.status(500).send({ status: "failed", message: "Internal server error" }); } }; - + + exports.updateSubmission = async (req, res) => { try { const { id } = req.params; @@ -389,15 +436,57 @@ exports.updateSubmission = async (req, res) => { } } - // Fetch updated data with associations - const updatedSubmission = await Submission.findByPk(id, { - include: [{ model: SubmissionProduct, as: "products" }], + + + //send submission email + if(submissionData.status == 'Submitted'){ + sendSubmissionCreatedEmails(id); + } + + //send updated data to FE + let submission_data = await Submission.findOne( { + where: { id : id }, + include: [ + { + model: Establishment, + as: "establishment" , + }, + { + model: SubmissionProduct, + as: "products", + include: [ + { + model: Product, + as: "product", + attributes: ["id", "product_name", "hs_code", "hs_description"], + }, + { + model: UnitMaster, + as: "unit", + attributes: ["uom"], + }, + { + model: VariationReasonMaster, + as: "variation_reason", + attributes: ["reason"], + }, + { + model: ZeroTargetReasonMaster, + as: "zero_target_reason", + attributes: ["reason"], + }, + ], + }, + ], }); + res.status(200).json({ status: "success", message: "Submission updated successfully", + submission_data : submission_data }); + } catch (err) { logger.error(err.message); logger.error(`Stack trace: ${err.stack}`); @@ -405,6 +494,7 @@ exports.updateSubmission = async (req, res) => { } }; + exports.submissionHistory = async (req, res) => { try { @@ -440,6 +530,7 @@ exports.submissionHistory = async (req, res) => { } }; + exports.submissionList = async (req, res) => { try { const { @@ -593,6 +684,7 @@ exports.submissionList = async (req, res) => { } }; + exports.viewSubmissionDetails = async (req, res) => { try {