dss-server / src /controllers /dashboardController.js
yeshwanth-kr's picture
Upload 43 files
8c7b7ca verified
const {
Employee,
Vendor,
GatePass,
RenewRequest,
Document,
SafetyInduction,
SafetyBadge
} = require('../models');
const { toValidObjectIdStrings } = require('../utils/objectId');
function latestByEmployee(rows) {
const map = new Map();
for (const row of rows) {
const key = String(row.employee_id);
if (!map.has(key)) map.set(key, row);
}
return map;
}
async function vendorDashboard(req, res, next) {
try {
const vendorId = req.user.vendor_id;
const employees = await Employee.find({ vendor_id: vendorId }).sort({ created_at: -1 }).lean();
const employeeIds = employees.map((e) => e._id);
const gatePasses = await GatePass.find({ employee_id: { $in: employeeIds } }).sort({ created_at: -1 }).lean();
const gatePassIds = gatePasses.map((g) => g._id);
const renewRequests = await RenewRequest.find({
gate_pass_id: { $in: gatePassIds },
status: 'Requested'
}, { gate_pass_id: 1 })
.lean();
const documents = await Document.find({ employee_id: { $in: employeeIds } }).lean();
const inductions = await SafetyInduction.find({ employee_id: { $in: employeeIds } }).lean();
const gatePassByEmployee = latestByEmployee(gatePasses);
const renewRequestedByGatePass = new Set(renewRequests.map((r) => String(r.gate_pass_id)));
const inductionByEmployee = new Map(inductions.map((i) => [String(i.employee_id), i]));
const docsByEmployee = new Map();
for (const doc of documents) {
const key = String(doc.employee_id);
if (!docsByEmployee.has(key)) docsByEmployee.set(key, []);
docsByEmployee.get(key).push(doc);
}
const rows = employees.map((employee) => {
const key = String(employee._id);
const gp = gatePassByEmployee.get(key);
const docs = docsByEmployee.get(key) || [];
const induction = inductionByEmployee.get(key);
const rejectedDocs = docs
.filter((d) => d.hr_status === 'Rejected')
.map((d) => `${d.type}${d.hr_remarks ? ` - ${d.hr_remarks}` : ''}`);
const approvedTypes = docs.filter((d) => d.verified_by_hr).map((d) => d.type);
return {
id: key,
employee_code: employee.employee_code,
name: employee.name,
status: employee.status,
due_date: employee.due_date,
profile_photo_path: employee.profile_photo_path,
gate_pass_id: gp ? String(gp._id) : 0,
issue_date: gp?.issue_date || null,
expiry_date: gp?.expiry_date || null,
pass_status: gp?.status || null,
can_renew: gp?.expiry_date ? new Date(gp.expiry_date) < new Date() : false,
renew_requested: gp ? renewRequestedByGatePass.has(String(gp._id)) : false,
total_docs_count: docs.length,
pending_docs_count: docs.filter((d) => d.hr_status === 'Pending').length,
rejected_docs_count: rejectedDocs.length,
rejected_docs_details: rejectedDocs.length ? rejectedDocs.join(' | ') : null,
approved_doc_types: approvedTypes.length ? approvedTypes.join('|') : null,
induction_id: induction ? String(induction._id) : null,
scheduled_test_date: induction?.scheduled_date || null,
test_status: induction?.test_status || null,
test_date: induction?.test_date || null,
failure_remarks: induction?.failure_remarks || null,
retest_requested: Boolean(induction?.retest_requested)
};
});
return res.json(rows);
} catch (error) {
return next(error);
}
}
async function hrDashboard(req, res, next) {
try {
const employees = await Employee.find({ is_active: true }).sort({ created_at: -1 }).lean();
const vendorIds = toValidObjectIdStrings(employees.map((e) => e.vendor_id));
const vendors = vendorIds.length
? await Vendor.find({ _id: { $in: vendorIds }, is_active: true }, { name: 1 }).lean()
: [];
const vendorMap = new Map(vendors.map((v) => [String(v._id), v]));
const filteredEmployees = employees.filter((e) => vendorMap.has(String(e.vendor_id)));
const filteredEmployeeIds = filteredEmployees.map((e) => e._id);
const documents = await Document.find({ employee_id: { $in: filteredEmployeeIds } }).lean();
const badges = await SafetyBadge.find({ employee_id: { $in: filteredEmployeeIds } }, { employee_id: 1, expiry_date: 1 }).lean();
const gatePasses = await GatePass.find({ employee_id: { $in: filteredEmployeeIds } }).sort({ created_at: -1 }).lean();
const docsByEmployee = new Map();
for (const doc of documents) {
const key = String(doc.employee_id);
if (!docsByEmployee.has(key)) docsByEmployee.set(key, []);
docsByEmployee.get(key).push(doc);
}
const badgeMap = new Map(badges.map((b) => [String(b.employee_id), b]));
const passMap = latestByEmployee(gatePasses);
const rows = [];
for (const employee of filteredEmployees) {
const key = String(employee._id);
const vendor = vendorMap.get(String(employee.vendor_id));
const docs = docsByEmployee.get(key) || [];
const badge = badgeMap.get(key);
const pass = passMap.get(key);
if (docs.length === 0) {
rows.push({
employee_id: key,
employee_code: employee.employee_code,
employee_name: employee.name,
status: employee.status,
profile_photo_path: employee.profile_photo_path,
vendor_name: vendor?.name || 'N/A',
document_id: null,
type: null,
file_path: null,
verified_by_hr: false,
hr_status: null,
hr_remarks: null,
pvc_validity_date: null,
hse_due_date: badge?.expiry_date || null,
pass_due_date: pass?.expiry_date || null,
pass_status: pass?.status || null
});
} else {
for (const doc of docs) {
rows.push({
employee_id: key,
employee_code: employee.employee_code,
employee_name: employee.name,
status: employee.status,
profile_photo_path: employee.profile_photo_path,
vendor_name: vendor?.name || 'N/A',
document_id: String(doc._id),
type: doc.type,
file_path: doc.file_path,
pvc_validity_date: doc.pvc_validity_date,
verified_by_hr: doc.verified_by_hr,
hr_status: doc.hr_status,
hr_remarks: doc.hr_remarks,
hse_due_date: badge?.expiry_date || null,
pass_due_date: pass?.expiry_date || null,
pass_status: pass?.status || null
});
}
}
}
return res.json(rows);
} catch (error) {
return next(error);
}
}
async function safetyDashboard(req, res, next) {
try {
const inductions = await SafetyInduction.find({ test_status: 'Pending' })
.sort({ scheduled_date: 1 })
.populate({ path: 'employee_id', model: 'Employee', select: 'name vendor_id is_active status' })
.lean();
const calendar = [];
for (const induction of inductions) {
const employee = induction.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 badge = await SafetyBadge.findOne({ employee_id: employee._id }, { badge_no: 1, expiry_date: 1 }).lean();
calendar.push({
id: String(induction._id),
employee_id: String(employee._id),
employee_code: employee.employee_code,
employee_name: employee.name,
vendor_name: vendor.name,
scheduled_date: induction.scheduled_date,
completed_date: induction.completed_date,
test_status: induction.test_status,
test_date: induction.test_date,
failure_remarks: induction.failure_remarks,
retest_requested: induction.retest_requested,
retest_requested_at: induction.retest_requested_at,
badge_no: badge?.badge_no || null,
expiry_date: badge?.expiry_date || null
});
}
const hrApprovedEmployees = await Employee.find({ status: 'HR_Approved', is_active: true })
.sort({ created_at: -1 })
.lean();
const eligible = [];
for (const employee of hrApprovedEmployees) {
const vendor = await Vendor.findById(employee.vendor_id, { name: 1, is_active: 1 }).lean();
if (!vendor || !vendor.is_active) continue;
const induction = await SafetyInduction.findOne({ employee_id: employee._id }, { retest_requested: 1 }).lean();
if (!induction || induction.retest_requested === true) {
eligible.push({
id: String(employee._id),
employee_code: employee.employee_code,
name: employee.name,
vendor_name: vendor.name
});
}
}
return res.json({ calendar, eligible });
} catch (error) {
return next(error);
}
}
module.exports = {
vendorDashboard,
hrDashboard,
safetyDashboard
};