const Event = require('../Models/Event'); const User = require('../Models/User'); const { notifyUser } = require('../Services/notification'); const { logger } = require('../Middleware/errorHandler'); const { cacheService } = require('../Services/cacheService'); /** * Get all pending certificate verifications */ async function getPendingVerifications(req, res) { try { const { page = 1, limit = 10, eventType } = req.query; const skip = (parseInt(page) - 1) * parseInt(limit); // Build query const query = { 'certificateSettings.verificationStatus': 'pending', 'features.certificateEnabled': true, }; if (eventType) { query.type = eventType; } // Get pending events const events = await Event.find(query) .populate('hostUserId', 'name email') .populate('institutionId', 'name') .populate('certificateSettings.submittedBy', 'name email') .sort({ 'certificateSettings.submittedAt': 1 }) // Oldest first .skip(skip) .limit(parseInt(limit)) .lean(); const totalPending = await Event.countDocuments(query); // Format response const pending = events.map((event) => ({ eventId: event._id, eventTitle: event.title, eventDate: event.date, eventType: event.type, hostName: event.hostUserId?.name, hostEmail: event.hostUserId?.email, institutionName: event.institutionId?.name, certificateConfig: { selectedTemplateId: event.certificateSettings.selectedTemplateId, certificateType: event.certificateSettings.certificateType, awardText: event.certificateSettings.awardText, leftSignatory: event.certificateSettings.leftSignatory, rightSignatory: event.certificateSettings.rightSignatory, uploadedAssets: event.certificateSettings.uploadedAssets, }, submittedAt: event.certificateSettings.submittedAt, submittedBy: event.certificateSettings.submittedBy, })); return res.json({ pending, pagination: { page: parseInt(page), limit: parseInt(limit), total: totalPending, pages: Math.ceil(totalPending / parseInt(limit)), }, }); } catch (error) { logger.error('Get pending verifications error:', error); return res .status(500) .json({ error: 'Error fetching pending verifications' }); } } /** * Get verification statistics */ async function getVerificationStats(req, res) { try { const stats = await Event.aggregate([ { $match: { 'features.certificateEnabled': true, }, }, { $group: { _id: '$certificateSettings.verificationStatus', count: { $sum: 1 }, }, }, ]); const statsObj = { total: 0, pending: 0, approved: 0, rejected: 0, not_configured: 0, }; stats.forEach((stat) => { statsObj[stat._id || 'not_configured'] = stat.count; statsObj.total += stat.count; }); return res.json(statsObj); } catch (error) { logger.error('Get verification stats error:', error); return res .status(500) .json({ error: 'Error fetching verification statistics' }); } } /** * Get specific verification details */ async function getVerificationById(req, res) { try { const { eventId } = req.params; const event = await Event.findById(eventId) .populate('hostUserId', 'name email') .populate('institutionId', 'name') .populate('certificateSettings.submittedBy', 'name email') .populate('certificateSettings.verifiedBy', 'name email') .lean(); if (!event) { return res.status(404).json({ error: 'Event not found' }); } if (!event.features.certificateEnabled) { return res .status(400) .json({ error: 'Certificates not enabled for this event' }); } return res.json({ eventId: event._id, eventTitle: event.title, eventDescription: event.description, eventDate: event.date, eventType: event.type, hostName: event.hostUserId?.name, hostEmail: event.hostUserId?.email, institutionName: event.institutionId?.name, certificateConfig: { selectedTemplateId: event.certificateSettings.selectedTemplateId, certificateType: event.certificateSettings.certificateType, awardText: event.certificateSettings.awardText, leftSignatory: event.certificateSettings.leftSignatory, rightSignatory: event.certificateSettings.rightSignatory, uploadedAssets: event.certificateSettings.uploadedAssets, }, verificationStatus: event.certificateSettings.verificationStatus, submittedAt: event.certificateSettings.submittedAt, submittedBy: event.certificateSettings.submittedBy, verifiedAt: event.certificateSettings.verifiedAt, verifiedBy: event.certificateSettings.verifiedBy, rejectionReason: event.certificateSettings.rejectionReason, }); } catch (error) { logger.error('Get verification by ID error:', error); return res .status(500) .json({ error: 'Error fetching verification details' }); } } /** * Approve certificate configuration */ async function approveCertificateConfig(req, res) { try { const { eventId } = req.params; const verifierId = req.user.id; const event = await Event.findById(eventId).populate( 'hostUserId', 'name email' ); if (!event) { return res.status(404).json({ error: 'Event not found' }); } if (!event.features.certificateEnabled) { return res .status(400) .json({ error: 'Certificates not enabled for this event' }); } if (event.certificateSettings.verificationStatus !== 'pending') { return res.status(400).json({ error: `Certificate configuration is not pending (current status: ${event.certificateSettings.verificationStatus})`, }); } // Check if all required assets are uploaded const assets = event.certificateSettings.uploadedAssets; if ( !assets?.organizationLogo || !assets?.leftSignature || !assets?.rightSignature ) { return res.status(400).json({ error: 'Cannot approve: Missing required assets (organization logo, left signature, or right signature)', }); } // Update verification status and potentially the template const { selectedTemplateId } = req.body; if (selectedTemplateId) { event.certificateSettings.selectedTemplateId = selectedTemplateId; } event.certificateSettings.verificationStatus = 'approved'; event.certificateSettings.verifiedBy = verifierId; event.certificateSettings.verifiedAt = new Date(); await event.save(); // Invalidate cache so verifier dashboard shows updated data await cacheService.invalidateCertificateVerification(eventId); await cacheService.invalidateVerifierCache(); // Notify host const host = event.hostUserId; if (host) { await notifyUser({ userId: host._id, type: 'certificate_verification', message: `Your certificate configuration for "${event.title}" has been approved!`, data: { eventId: event._id, eventTitle: event.title, status: 'approved', }, emailOptions: { to: host.email, subject: `Certificate Configuration Approved: ${event.title}`, html: `
Dear ${host.name},
Your certificate configuration for ${event.title} has been approved by a verifier.
You can now generate certificates for all attended participants.
Next Steps:
Best regards,
CampVerse Team
Dear ${host.name},
Your certificate configuration for ${event.title} has been rejected by a verifier.
Reason: ${reason}
${issuesList ? `Specific Issues:
${issuesList}` : ''}Next Steps:
If you have questions, please contact support.
Best regards,
CampVerse Team
Dear ${host.name},
A verifier has reviewed your certificate configuration for ${event.title} and is requesting the following changes:
${changesList}Next Steps:
Best regards,
CampVerse Team