Files
mek-tech-consulting/routes/quality.js
T

105 lines
4.4 KiB
JavaScript

const express = require('express');
const router = express.Router();
const path = require('path');
const fs = require('fs');
const multer = require('multer');
const http = require('http');
const QS_HOST = process.env.QS_HOST || 'python-quality';
const QS_PORT = parseInt(process.env.QS_PORT || '3002');
const SHARED_UPLOAD_DIR = path.join(__dirname, '..', 'data', 'uploads');
if (!fs.existsSync(SHARED_UPLOAD_DIR)) fs.mkdirSync(SHARED_UPLOAD_DIR, { recursive: true });
const storage = multer.diskStorage({
destination: (req, file, cb) => cb(null, SHARED_UPLOAD_DIR),
filename: (req, file, cb) => cb(null, Date.now() + '-' + file.originalname)
});
const upload = multer({ storage, limits: { fileSize: 100 * 1024 * 1024 } });
function qsApi(path, method, body) {
return new Promise((resolve, reject) => {
const opts = { hostname: QS_HOST, port: QS_PORT, path, method, headers: { 'Content-Type': 'application/json' }, timeout: 30000 };
const req = http.request(opts, (res) => {
let data = '';
res.on('data', c => data += c);
res.on('end', () => {
if (method === 'GET' && res.statusCode >= 400) return reject(new Error('offline'));
try { resolve(JSON.parse(data)); } catch(e) { resolve({ raw: data }); }
});
});
req.on('error', (e) => reject(e));
req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
if (body) req.write(JSON.stringify(body));
req.end();
});
}
router.get('/', async (req, res) => {
let files = [];
let qsStatus = 'offline';
let services = {};
try {
const dirFiles = fs.readdirSync(SHARED_UPLOAD_DIR).filter(f => f !== '.gitkeep');
files = dirFiles.map(f => ({ file_id: f.split('.')[0], filename: f, size: fs.statSync(path.join(SHARED_UPLOAD_DIR, f)).size }));
await qsApi('/python-quality/', 'GET');
qsStatus = 'online';
} catch (e) { qsStatus = 'offline'; }
try {
const { getServicesStatus } = require('../lib/services');
services = await getServicesStatus();
} catch (e) {}
const { getDb } = require('../db');
const clients = getDb().prepare('SELECT id, name FROM clients ORDER BY name').all();
const clientId = req.query.client_id || req.session.activeClientId || null;
res.render('quality-dashboard', { files, qsStatus, services, clients, clientId, uploaded: null, profile: null, report: null, error: null });
});
router.post('/upload', upload.single('file'), async (req, res) => {
if (!req.file) return res.redirect('/quality');
try {
const resp = await qsApi('/python-quality/api/profile', 'POST', { file_id: req.file.filename.split('.')[0], shared_path: path.join(SHARED_UPLOAD_DIR, req.file.filename) });
const profile = resp.profile || resp;
const uploaded = { file_id: req.file.filename.split('.')[0], original_name: req.file.originalname, rows: profile.rows, columns: profile.columns };
res.render('quality-dashboard', { files: [], qsStatus: 'online', uploaded, profile, report: null, error: null });
} catch (e) {
res.render('quality-dashboard', { files: [], qsStatus: 'online', uploaded: null, profile: null, report: null, error: 'Kon bestand niet analyseren: ' + (e.message || 'onbekende fout') });
}
});
router.post('/quality-check/:fileId', async (req, res) => {
try {
const result = await qsApi('/python-quality/api/quality-check', 'POST', { file_id: req.params.fileId, checks: ['completeness', 'uniqueness', 'range', 'type'] });
res.json(result);
} catch (e) { res.status(500).json({ error: e.message }); }
});
router.get('/profile/:fileId', async (req, res) => {
try {
const result = await qsApi('/python-quality/api/profile', 'POST', { file_id: req.params.fileId });
res.json(result);
} catch (e) { res.status(500).json({ error: e.message }); }
});
router.get('/report/:reportId', async (req, res) => {
try {
const result = await qsApi('/python-quality/api/report/' + req.params.reportId, 'GET');
res.json(result);
} catch (e) { res.status(500).json({ error: e.message }); }
});
router.post('/dbt/validate', async (req, res) => {
try {
const result = await qsApi('/python-quality/api/dbt/validate', 'POST', req.body);
res.json(result);
} catch (e) { res.status(500).json({ error: e.message }); }
});
router.post('/dbt/test', async (req, res) => {
try {
const result = await qsApi('/python-quality/api/dbt/test', 'POST', req.body);
res.json(result);
} catch (e) { res.status(500).json({ error: e.message }); }
});
module.exports = router;