diff --git a/src/libs/middlewares/reqQueryFields.js b/src/libs/middlewares/reqQueryFields.js new file mode 100644 index 0000000000000000000000000000000000000000..10836590ae7c6b5ffc9dddeac9164aea0689234f --- /dev/null +++ b/src/libs/middlewares/reqQueryFields.js @@ -0,0 +1,167 @@ +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const parseParams = require(`${libs}/middlewares/parseParams`); + +const _ = require('lodash'); + +class ReqQueryFields { + constructor(fields = {}, fieldValues = {}) { + // Parâmetros no campo query da requisição. + // Exemplo de field: + // { + // name: 'dims', + // field: true, + // where: false + // } + this.fields = fields; + this.fieldValues = fieldValues; + } + + addField(field) { + // Parâmetro no campo query da requisição. + // Exemplo de field: + // { + // name: 'dims', + // field: true, + // where: false, + // fieldValues: {} + // } + if(typeof this.fields[field.name] === 'undefined') { + this.fields[field.name] = field; + } + return this; + } + + addValue(fieldValue) { + // Array de valores aceitos pelo campo + // Exemplo de valor: + // { + // name: 'location', + // table: 'localizacao', + // tableField: 'descricao' + // resultField: 'location_name', + // where: { + // relation: '=', + // type: 'integer', + // field: 'id_localizacao', + // table: 'turma' + // }, + // join: { + // primary: 'pk_localizacao_id', + // foreign: 'id_localizacao', + // foreignTable: 'turma' + // } + // } + + if(typeof this.fieldValues[fieldValue.name] === 'undefined') { + this.fieldValues[fieldValue.name] = fieldValue; + } + return this; + } + + parse() { + return (req, res, next) => { + Object.keys(this.fields).map((key, index) => { + let params = []; + let f = this.fields[key]; + log.debug('f'); + log.debug(f); + Object.keys(this.fieldValues).map((k, i) => { + let value = this.fieldValues[k]; + log.debug('value'); + log.debug(value); + params.push(value.name); + }); + let queryField = f.name; + let arrayOfParams = params; + req[queryField] = {}; + if (req.query[queryField]) { + const params = req.query[queryField].split(','); + // Temporary object to hold the params and it's values + const obj = {}; + for (const param of params) { + // Get the key and the value - state:41 is key 'state' whith value 41. + // kv is then an array [key, value] or [key] if there is no value + const kv = param.split(':'); + // Check if there is a value. If there isn't, assign true + obj[kv[0]] = (typeof kv[1] === 'undefined') ? true : kv[1]; + // obj is now an object {kv[0]: kv[1]} ou {kv[0]: true} + } + + // If the array exists and is not empty we intersect + if (typeof arrayOfParams !== 'undefined' && arrayOfParams.length > 0) { + // Intersect the keys of the obj with the array arrayOfParams + // The intersection array is assigned with the keys + const intersection = _.intersection(arrayOfParams, Object.keys(obj)); + // This is a bit tricky... + // For each key in the intersection array we get it's value in the obj + // and assign it to the custom attribute in the req obj. + // For example: instersection => ["state"] so + // obj[intersection[i]] (with i=0) is obj["state"], that is 41 + // and req[queryField]["state"] = 41 + for (let i = 0; i < intersection.length; ++i) { + req[queryField][intersection[i]] = obj[intersection[i]]; + } + req[queryField].size = intersection.length; + } else { + req[queryField] = obj; + req[queryField].size = Object.keys(obj).length; + } + } + }); + next(); + }; + } + + build() { + return (req, res, next) => { + Object.keys(this.fields).map((key, index) => { + let field = this.fields[key]; + log.debug(field); + let param = req[field.name]; + log.debug(param); + Object.keys(param).map((k, i) => { + let values = this.fieldValues; + log.debug(k); + if(typeof values[k] !== 'undefined') { + // Clonamos para não alterar + let value = _.clone(values[k]); + log.debug(value); + // Checa se não fizemos o join para este valor e se é necessário fazer + if(!value.hasJoined && typeof value.join !== 'undefined') { + let foreignTable = ''; + if(value.join.foreignTable) foreignTable = value.join.foreignTable+'.'; + // Fazemos o join + req.sql.join(value.table, null, foreignTable+value.join.foreign+'='+value.table+'.'+value.join.primary); + // Marcamos o join como feito para não ter problemas + value.hasJoined = true; + } + // Se o valor é um campo a ser incluÃdo no SELECT + if(typeof field.field !== 'undefined' && field.field) { + log.debug('SELECT'); + req.sql.field(value.table+'.'+value.tableField, value.resultField || value.tableField) + .group(value.table+'.'+value.tableField) + .order(value.table+'.'+value.tableField); + } + // Se o valor é um campo para ser usado no WHERE + if(typeof field.where !== 'undefined' && field.where) { + log.debug('WHERE'); + // Valor do where + let whereValue = param[k]; + // Valor sempre vem como string, necessário fazer parse para o banco + if(value.where.type === 'integer') whereValue = parseInt(whereValue, 10); + if(value.where.type === 'double') whereValue = parseFloat(whereValue); + let tbl = value.where.table || value.table; + req.sql.where(tbl+'.'+value.where.field+' '+value.where.relation+' ?', whereValue); + } + } + }); + }); + next(); + }; + } +} + +module.exports = ReqQueryFields;