Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x | const Audit = require('../models/Audit'); const Establishment = require('../models/Establishment'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const PDFDocument = require('pdfkit'); // File upload configuration const storage = multer.diskStorage({ destination: (req, file, cb) => { const uploadDir = 'public/uploads/'; if (!fs.existsSync(uploadDir)) fs.mkdirSync(uploadDir, { recursive: true }); cb(null, uploadDir); }, filename: (req, file, cb) => { const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); cb(null, uniqueSuffix + path.extname(file.originalname)); } }); const upload = multer({ storage, fileFilter: (req, file, cb) => { const filetypes = /jpeg|jpg|png|pdf|doc|docx/; const extname = filetypes.test(path.extname(file.originalname).toLowerCase()); const mimetype = filetypes.test(file.mimetype); extname && mimetype ? cb(null, true) : cb(new Error('Only images, PDFs and Word documents are allowed')); }, limits: { fileSize: 10 * 1024 * 1024 } // 10MB }).array('evidence'); // API Methods exports.getAllAudits = async (req, res) => { try { const query = req.user.role === 'admin' ? {} : { user: req.user.id }; const audits = await Audit.find(query) .populate('establishment', 'name location') .populate('user', 'username'); res.json(audits); } catch (error) { console.error('Error fetching audits:', error); res.status(500).json({ error: 'Error fetching audits' }); } }; exports.getAudit = async (req, res) => { try { const audit = await Audit.findById(req.params.id) .populate('establishment', 'name location') .populate('user', 'username') .populate('aspects') .populate('evidence'); if (!audit) return res.status(404).json({ error: 'Audit not found' }); res.json(audit); } catch (error) { console.error('Error fetching audit:', error); res.status(500).json({ error: 'Error fetching audit' }); } }; exports.createAudit = async (req, res) => { try { const { establishment_id, audit_date, aspects, observations, recommendations } = req.body; const user_id = req.user.id; const auditId = await Audit.create({ establishment_id, user_id, audit_date }); for (const aspect of JSON.parse(aspects)) { const aspectId = await Audit.addAspect(auditId, { aspect_type: aspect.type, is_compliant: aspect.compliant, notes: aspect.notes }); if (aspect.type === 'biodiversity' && aspect.details) { await Audit.addBiodiversityDetail(aspectId, { invasive_plants_status: aspect.details.status, details: aspect.details.details, action_plan: aspect.details.actionPlan }); } } upload(req, res, async (err) => { if (err) { console.error(err); return res.status(400).json({ error: err.message }); } if (req.files?.length > 0) { for (const file of req.files) { await Audit.addEvidence( auditId, { file_path: `/uploads/${file.filename}`, file_name: file.originalname, file_type: file.mimetype.split('/')[0], file_size: file.size }, user_id ); } } await Audit.updateObservations(auditId, observations, recommendations); res.json({ success: true, auditId }); }); } catch (error) { console.error(error); res.status(500).json({ error: 'Error creating audit' }); } }; // Web Methods (keep your existing web methods) exports.newAuditForm = async (req, res) => { /* ... */ }; exports.listAudits = async (req, res) => { /* ... */ }; exports.viewAudit = async (req, res) => { /* ... */ }; exports.generatePdfReport = async (req, res) => { const auditId = req.params.id; const audit = await Audit.findById(auditId) .populate('establishment', 'name location') .populate('user', 'username') .populate('aspects') .populate('evidence'); if (!audit) { return res.status(404).json({ error: 'Audit not found' }); } const doc = new PDFDocument({ margin: 50 }); res.setHeader('Content-disposition', `attachment; filename=EMP-Report-${auditId}.pdf`); res.setHeader('Content-type', 'application/pdf'); doc.pipe(res); // Header doc.image('public/images/logo.png', 50, 45, { width: 50 }); doc.fontSize(20).text('Environmental Management Plan Audit Report', 110, 57); doc.fontSize(10).text(`Report ID: EMP-${auditId}`, 50, 100); doc.text(`Date Generated: ${new Date().toLocaleDateString()}`, 50, 115); doc.moveDown(); // Establishment Details doc.fontSize(14).text('Establishment Details', { underline: true }); doc.fontSize(12).text(`Name: ${audit.establishment.name}`); doc.text(`Location: ${audit.establishment.location}`); doc.text(`Audit Date: ${new Date(audit.audit_date).toLocaleDateString()}`); doc.text(`Auditor: ${audit.user.username}`); doc.moveDown(); // Compliance Summary doc.fontSize(14).text('Compliance Summary', { underline: true }); doc.fontSize(12).text(`Overall Compliance Score: ${audit.overall_compliance_score || 'N/A'}`); doc.moveDown(); // Audit Aspects doc.fontSize(14).text('Audit Aspects', { underline: true }); audit.aspects.forEach(aspect => { doc.fontSize(12).text(`${aspect.aspect_type}: ${aspect.is_compliant ? 'Compliant' : 'Non-Compliant'}`); if (aspect.notes) doc.text(`Notes: ${aspect.notes}`).moveDown(); }); doc.moveDown(); // Observations doc.fontSize(14).text('Observations', { underline: true }); doc.fontSize(12).text(audit.observations || 'No observations recorded'); doc.moveDown(); // Recommendations doc.fontSize(14).text('Recommendations', { underline: true }); doc.fontSize(12).text(audit.recommendations || 'No recommendations'); doc.moveDown(); // Footer doc.fontSize(10) .text('This report was automatically generated by the EMP Audit System', 50, doc.page.height - 50, { align: 'center' }); doc.end(); }; |