Spaces:
Runtime error
Runtime error
| 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 | |
| }; | |