dss-server / src /services /workflowService.js
yeshwanth-kr's picture
Upload 43 files
8c7b7ca verified
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
};