Spaces:
Runtime error
Runtime error
| const dayjs = require('dayjs'); | |
| const { | |
| Document, | |
| Employee, | |
| Vendor, | |
| User, | |
| SafetyBadge, | |
| GatePass, | |
| AlertLog | |
| } = require('../models'); | |
| const { sendEmail, sendWhatsApp } = require('./notificationService'); | |
| async function ensureMandatoryDocuments(employeeId) { | |
| const rows = await Document.find({ employee_id: employeeId }, { type: 1, verified_by_hr: 1 }).lean(); | |
| const hasAadhar = rows.some((r) => r.type === 'Aadhar'); | |
| const hasUan = rows.some((r) => r.type === 'UAN'); | |
| const hasEsi = rows.some((r) => r.type === 'ESI'); | |
| const hasCompPolicy = rows.some((r) => r.type === 'Compensation_Policy'); | |
| const hasPvc = rows.some((r) => r.type === 'PVC'); | |
| return hasAadhar && hasUan && (hasEsi || hasCompPolicy) && hasPvc; | |
| } | |
| async function countVendorWorkers(vendorId) { | |
| return Employee.countDocuments({ | |
| vendor_id: vendorId, | |
| is_active: true, | |
| status: { $in: ['Pending', 'HR_Approved', 'Safety_Approved', 'Active'] } | |
| }); | |
| } | |
| async function findVendorContact(vendorId) { | |
| return User.findOne({ vendor_id: vendorId, role: 'Vendor', is_active: true }, { email: 1, phone: 1 }).lean(); | |
| } | |
| async function sendAlert(alertType, table, refId, recipientEmail, recipientPhone, subject, message) { | |
| if (!recipientEmail) return; | |
| const existing = await AlertLog.findOne({ | |
| alert_type: alertType, | |
| reference_table: table, | |
| reference_id: String(refId), | |
| recipient_email: recipientEmail, | |
| channel: 'Email' | |
| }).lean(); | |
| if (!existing) { | |
| await sendEmail(recipientEmail, subject, message); | |
| await AlertLog.create({ | |
| alert_type: alertType, | |
| reference_table: table, | |
| reference_id: String(refId), | |
| recipient_email: recipientEmail, | |
| channel: 'Email', | |
| message, | |
| sent_at: new Date() | |
| }); | |
| } | |
| if (recipientPhone) { | |
| const existingWa = await AlertLog.findOne({ | |
| alert_type: alertType, | |
| reference_table: table, | |
| reference_id: String(refId), | |
| recipient_email: recipientEmail, | |
| channel: 'WhatsApp' | |
| }).lean(); | |
| if (!existingWa) { | |
| await sendWhatsApp(`whatsapp:${recipientPhone}`, message); | |
| await AlertLog.create({ | |
| alert_type: alertType, | |
| reference_table: table, | |
| reference_id: String(refId), | |
| recipient_email: recipientEmail, | |
| channel: 'WhatsApp', | |
| message, | |
| sent_at: new Date() | |
| }); | |
| } | |
| } | |
| } | |
| async function processBadgeAlerts(adminUsers) { | |
| const today = dayjs().startOf('day'); | |
| const maxDate = today.add(30, 'day').endOf('day').toDate(); | |
| const badges = await SafetyBadge.find({ expiry_date: { $lte: maxDate } }) | |
| .populate({ path: 'employee_id', model: 'Employee', select: 'name vendor_id is_active' }) | |
| .lean(); | |
| for (const badge of badges) { | |
| const employee = badge.employee_id; | |
| if (!employee || !employee.is_active) continue; | |
| const vendor = await Vendor.findById(employee.vendor_id, { name: 1, is_active: 1 }).lean(); | |
| if (!vendor || !vendor.is_active) continue; | |
| const daysToExpiry = dayjs(badge.expiry_date).startOf('day').diff(today, 'day'); | |
| let alertType; | |
| let subject; | |
| if (daysToExpiry <= 0) { | |
| alertType = 'SAFETY_BADGE_EXPIRED'; | |
| subject = `Safety Badge Expired - ${employee.name}`; | |
| } else if (daysToExpiry === 7) { | |
| alertType = 'SAFETY_BADGE_7_DAYS'; | |
| subject = `Safety Badge Expires in 7 Days - ${employee.name}`; | |
| } else if (daysToExpiry === 30) { | |
| alertType = 'SAFETY_BADGE_30_DAYS'; | |
| subject = `Safety Badge Expires in 30 Days - ${employee.name}`; | |
| } else { | |
| continue; | |
| } | |
| const message = `${employee.name} (${vendor.name}) safety badge due date: ${dayjs(badge.expiry_date).format('DD/MM/YYYY')}.`; | |
| const vendorUser = await findVendorContact(vendor._id); | |
| if (vendorUser) { | |
| await sendAlert(alertType, 'safety_badges', badge._id, vendorUser.email, vendorUser.phone, subject, message); | |
| } | |
| for (const adminUser of adminUsers) { | |
| await sendAlert(alertType, 'safety_badges', badge._id, adminUser.email, adminUser.phone, subject, message); | |
| } | |
| } | |
| } | |
| async function processGatePassAlerts(adminUsers) { | |
| const today = dayjs().startOf('day'); | |
| const maxDate = today.add(30, 'day').endOf('day').toDate(); | |
| const gatePasses = await GatePass.find({ expiry_date: { $lte: maxDate } }) | |
| .populate({ path: 'employee_id', model: 'Employee', select: 'name vendor_id is_active' }) | |
| .lean(); | |
| for (const gatePass of gatePasses) { | |
| const employee = gatePass.employee_id; | |
| if (!employee || !employee.is_active) continue; | |
| const vendor = await Vendor.findById(employee.vendor_id, { name: 1, is_active: 1 }).lean(); | |
| if (!vendor || !vendor.is_active) continue; | |
| const daysToExpiry = dayjs(gatePass.expiry_date).startOf('day').diff(today, 'day'); | |
| let alertType; | |
| let subject; | |
| if (daysToExpiry <= 0) { | |
| alertType = 'GATE_PASS_EXPIRED'; | |
| subject = `Gate Pass Expired - ${employee.name}`; | |
| } else if (daysToExpiry === 7) { | |
| alertType = 'GATE_PASS_7_DAYS'; | |
| subject = `Gate Pass Expires in 7 Days - ${employee.name}`; | |
| } else if (daysToExpiry === 30) { | |
| alertType = 'GATE_PASS_30_DAYS'; | |
| subject = `Gate Pass Expires in 30 Days - ${employee.name}`; | |
| } else { | |
| continue; | |
| } | |
| const message = `${employee.name} (${vendor.name}) gate pass due date: ${dayjs(gatePass.expiry_date).format('DD/MM/YYYY')}.`; | |
| const vendorUser = await findVendorContact(vendor._id); | |
| if (vendorUser) { | |
| await sendAlert(alertType, 'gate_passes', gatePass._id, vendorUser.email, vendorUser.phone, subject, message); | |
| } | |
| for (const adminUser of adminUsers) { | |
| await sendAlert(alertType, 'gate_passes', gatePass._id, adminUser.email, adminUser.phone, subject, message); | |
| } | |
| } | |
| } | |
| async function sendExpiryAlerts() { | |
| const adminUsers = await User.find({ role: 'Admin', is_active: true }, { email: 1, phone: 1 }).lean(); | |
| await processBadgeAlerts(adminUsers); | |
| await processGatePassAlerts(adminUsers); | |
| await GatePass.updateMany( | |
| { expiry_date: { $lt: dayjs().startOf('day').toDate() }, status: { $ne: 'Expired' } }, | |
| { $set: { status: 'Expired' } } | |
| ); | |
| } | |
| module.exports = { | |
| ensureMandatoryDocuments, | |
| countVendorWorkers, | |
| sendExpiryAlerts | |
| }; | |