UNPKG

alphascript-server

Version:

CRUD operations for mongo and other functionalities to get started quickly in any CMS project

379 lines (343 loc) 11.8 kB
var api = require('../../../'); var moment = require('moment'); var objectPath = require("object-path"); var PdfTable = require('voilab-pdf-table'); var PdfDocument = require('pdfkit'); module.exports = { getMetadata: function (reportKey) { var report = api.reportMap[reportKey]; return function (req, res) { res.json({ title: report.title, fields: report.fields }); }; }, getReport: function (reportKey) { var report = api.reportMap[reportKey]; return function (req, res) { var params = {}, invokes = [], i, field; //SELECT var project = {}, requires = [], toRemove = []; if (typeof req.query.select !== 'undefined') params.select = req.query.select instanceof Array ? req.query.select : [req.query.select]; else return res.status(400).send("Deve incluir pelo menos 1 campo no relatório"); for (i = 0; i < params.select.length; i++) { field = report.fields[parseInt(params.select[i])]; if (typeof field.name !== 'undefined') { params.select[i] = field.name; continue; } invokes.push(field.invoke); field.requires.forEach(function (require) { if (requires.indexOf(require) !== -1) return; requires.push(require); }); params.select.splice(i, 1); i--; } requires.forEach(function (require) { if (params.select.indexOf(require) !== -1) return; params.select.push(require); toRemove.push(require); }); params.select.forEach(function (subselect) { project[subselect] = 1; }); //SORT var sort = undefined; try { params.sort = JSON.parse(req.query.sort); if (typeof params.sort.field !== 'undefined' && typeof params.sort.type !== 'undefined') { field = report.fields[parseInt(params.sort.field)]; if (typeof field.name === 'undefined') { sort = function (a, b) { if (a[field.invoke] < b[field.invoke]) return -1; if (a[field.invoke] > b[field.invoke]) return 1; return 0; }; } else { sort = {}; sort[field.name] = params.sort.type; } } } catch (err) { //api.error.log(err); } //AGGREGATING OPERATOR params.aggregator = "$and"; try { var aggregator = JSON.parse(req.query.aggregator); params.aggregator = aggregator.value; } catch (err) { //api.error.log(err); } //QUERY if (typeof req.query.query !== 'undefined') params.query = req.query.query instanceof Array ? req.query.query : [req.query.query]; var query = {}; query[params.aggregator] = []; var invokeQuery = []; for (i = 0; i < (params.query || []).length; i++) { var subquery = params.query[i]; try { subquery = JSON.parse(subquery); } catch (err) { api.error.log(err); return res.status(400).send("Não foi possível formular a sua busca com os dados fornecidos"); } if (subquery.field && subquery.field.type === 'Boolean') subquery.operator = "equals"; if (typeof subquery.field === 'undefined' || typeof subquery.operator === 'undefined') { return res.status(400).send("Erro num dos filtros definidos"); } var assembledSubquery = assembleQuery(subquery.field, subquery.operator, subquery.value); if (typeof subquery.field.name === 'undefined') { invokeQuery.push(assembledSubquery); } else { query[params.aggregator].push(assembledSubquery); } } //ASSEMBLE AGGREGATE STAGES var aggregate = []; report.aggregate.forEach(function (stage) { aggregate.push(stage); }); if (query[params.aggregator].length > 0) aggregate.push({ $match: query }); aggregate.push({ $project: project }); if (typeof sort === 'object') aggregate.push({ $sort: sort }); //GET DATA FROM DB var db = typeof report.db === 'function' ? report.db(req) : report.db; db[report.model].aggregate(aggregate).allowDiskUse(true)/*.cursor({ batchSize: 1000, async: true })*/.exec(function (err, items) { if (err) { if (err.code === 16389) return res.status(500).send("Listagem solicitada excede o tamanho máximo permitido, deve filtrar os seus dados"); api.error.log(err); return res.status(500).send(api.error.DB_GENERIC); } //ASSEMBLE ITEMS items = items.filter(function (item) { //SET DYNAMIC FIELDS if (invokes.length > 0 || invokeQuery.length > 0) { invokes.forEach(function (invoke) { item[invoke] = report.invoke[invoke](item, items); }); var invalid = invokeQuery.some(function (subquery) { return !subquery.invoke(item[subquery.field]); }); if (invalid) return false; } //CLEANUP toRemove.forEach(function (key) { objectPath.del(item, key); }); return true; }); //SET DYNAMIC SORT if (typeof sort === 'function') items.sort(sort); //ASSEMBLE RESPONSE if (req.query.xls) { //on excel var xls = { sheets: [] }; var xlsHeader = {}; //headers invokes.forEach(function (invoke) { params.select.push(invoke); }); params.select.forEach(function (select) { if (toRemove.indexOf(select) !== -1) return; var field = report.fields.find(function (field) { return field.name === select || field.invoke === select; }); var key = typeof field.name === 'undefined' ? field.invoke : field.name; xlsHeader[key] = field.caption; }); var filename = report.title + '_' + moment().format('YYYY-MM-DD') + '.xlsx'; xls.sheets.push({ header: xlsHeader, sheetName: 'listagem', items: items }); res.setHeader('Content-Type', 'application/vnd.openxmlformats'); res.setHeader("Content-Disposition", "attachment; filename=" + filename); res.send(api.xlsx.fromJson(xls)); } else if (req.query.pdf) { //on pdf var pdf = new PdfDocument({ autoFirstPage: false, size: [842, 595], bufferPages: true, }); pdf.fontSize(8); //headers invokes.forEach(function (invoke) { params.select.push(invoke); }); var cols = params.select.filter(function (select) { return toRemove.indexOf(select) === -1; }); cols = cols.map(function (select) { var field = report.fields.find(function (field) { return field.name === select || field.invoke === select; }); var key = typeof field.name === 'undefined' ? field.invoke : field.name; return { field: key, title: field.caption, width: (842 - 130) / cols.length }; }); var table = new PdfTable(pdf, { bottomMargin: 30 }); table.setColumnsDefaults({ headerBorder: 'LTBR', align: 'left' }).addColumns(cols).onPageAdded(function (tb) { tb.addHeader(); }); pdf.addPage(); items = items.map(function (item) { var _item = {}; cols.forEach(function (col) { _item[col.field] = objectPath.get(item, col.field); }); return _item; }); table.addBody(items); pdf.pipe(res); return pdf.end(); } else { //on screen res.json(items); } }); }; } }; function assembleQuery(field, operator, value) { //assert if field is dynamic var mongo, fieldPointer; if (typeof field.name === 'undefined') { fieldPointer = field.invoke; mongo = false; } else { fieldPointer = field.name; mongo = true; } //parse value data type if (field.type === 'Date') value = value ? new Date(value) : undefined; else if (field.type === 'Number') value = value ? parseFloat(value) : undefined; var parts = fieldPointer.split('.'), subquery = {}, criteriaMain, criteriaNull; if (mongo) { var key; switch (operator) { case "greaterThan": key = "$gt"; subquery[fieldPointer] = {}; subquery[fieldPointer][key] = value; break; case "greaterThanOrEquals": key = "$gte"; subquery[fieldPointer] = {}; subquery[fieldPointer][key] = value; break; case "lesserThan": key = "$lt"; subquery[fieldPointer] = {}; subquery[fieldPointer][key] = value; break; case "lesserThanOrEquals": key = "$lte"; subquery[fieldPointer] = {}; subquery[fieldPointer][key] = value; break; case "notEquals": key = "$ne"; subquery[fieldPointer] = {}; subquery[fieldPointer][key] = value; break; default: break; } if (!key) { switch (operator) { case "contains": subquery[fieldPointer] = new RegExp('.*' + value + '.*', 'i'); break; case "startsWith": subquery[fieldPointer] = new RegExp('^' + value + '.*', 'i'); break; case "endsWith": subquery[fieldPointer] = new RegExp('.*' + value + '$', 'i'); break; case "notExists": subquery[fieldPointer] = { $exists: false }; break; default: subquery[fieldPointer] = value; break; } } } else { subquery.field = fieldPointer; switch (operator) { case "greaterThan": subquery.invoke = function (thisValue) { return thisValue > value; }; break; case "greaterThanOrEquals": subquery.invoke = function (thisValue) { return thisValue >= value; }; break; case "lesserThan": subquery.invoke = function (thisValue) { return thisValue < value; }; break; case "lesserThanOrEquals": subquery.invoke = function (thisValue) { return thisValue <= value; }; break; case "notEquals": subquery.invoke = function (thisValue) { return thisValue !== value; }; break; case "equals": subquery.invoke = function (thisValue) { return thisValue === value; }; break; case "contains": subquery.invoke = function (thisValue) { return new RegExp('.*' + value + '.*', 'i').test(thisValue); }; break; case "startsWith": subquery.invoke = function (thisValue) { return new RegExp('^' + value + '.*', 'i').test(thisValue); }; break; case "endsWith": subquery.invoke = function (thisValue) { return new RegExp('.*' + value + '$', 'i').test(thisValue); }; break; case "notExists": subquery.invoke = function (thisValue) { return typeof thisValue === 'undefined'; }; break; case "exists": subquery.invoke = function (thisValue) { return typeof thisValue !== 'undefined'; }; break; default: console.log('unknown operator: ' + operator); } } return subquery; }