diff --git a/src/libs/middlewares/downloadDatabase.js b/src/libs/middlewares/downloadDatabase.js new file mode 100644 index 0000000000000000000000000000000000000000..d1566b8c11c334e688da4f34641c728820c10e2c --- /dev/null +++ b/src/libs/middlewares/downloadDatabase.js @@ -0,0 +1,67 @@ +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const execute = require(`${libs}/middlewares/query`).execute; + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const Download = require(`${libs}/models/download`); + +module.exports = function download(table, mappingTable) { + return (req, res, next) => { + // First, query the mapping + execute(`SELECT target_name, name FROM ${mappingTable}`, undefined, (err, result) => { + if(err) { + log.error(err.stack); + next(new Error('Request could not be satisfied due to a database error.')); + } else { + let header = ''; + req.sql.from(table); + result.forEach((field) => { + req.sql.field(table + '.' + field.name, field.target_name); + if(header === '') header += field.target_name; + else header = header + ';' + field.target_name; + }); + + let form = { + query: req.sql.toString(), + table: req.sql.tableFrom, + name: req.sql.tableFrom, + username: req.user.name, + email: req.user.email, + header + }; + + request.post(config.cdn.url + '/api/v1/file', {form}, (err, response, body) => { + if(err) { + log.error(err); + return res.json({error: err}); + } + + Download.findOne({query: req.sql.toString()}, (err, download) => { + if(download) { + download.updatedAt = Date.now(); + } else { + download = new Download({ + userId: req.user._id, + table, + mappingTable, + query: req.sql.toString() + }); + } + + download.save((err) => { + if(err) { + log.error(err); + } + res.json({msg: 'Wait for download email', waitForIt: true}); + }); + }); + }); + } + }); + } +}; \ No newline at end of file diff --git a/src/libs/middlewares/query.js b/src/libs/middlewares/query.js index b76f6ff7759efeefc89ef0d394770871e7bd4c05..ae002df2fb13727152497dc9ad61c1371d98d194 100644 --- a/src/libs/middlewares/query.js +++ b/src/libs/middlewares/query.js @@ -26,4 +26,4 @@ function execute(text, values, cb) { }); } -module.exports = query; +module.exports = {query, execute}; diff --git a/src/libs/models/download.js b/src/libs/models/download.js new file mode 100644 index 0000000000000000000000000000000000000000..8cd16000bf7716ebfeaf64ffb9133a95ee79dd3f --- /dev/null +++ b/src/libs/models/download.js @@ -0,0 +1,37 @@ +const mongoose = require('mongoose'); +const Schema = mongoose.Schema; +const libs = `${process.cwd()}/libs`; +const log = require(`${libs}/log`)(module); +const User = require(`${libs}/models/user`); + +let Download = new Schema({ + userId: { + type: Schema.Types.ObjectId, + required: true, + ref: 'User' + }, + table: { + type: String, + required: true + }, + mappingTable: { + type: String, + required: true + }, + query: { + type: String, + required: true + }, + createdAt: { + type: Date, + required: true, + default: Date.now + }, + updatedAt: { + type: Date, + required: true, + default: Date.now + } +}); + +module.exports = mongoose.model('Download', Download); diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js index e205726df4fdc6fe117337cebd5eaf4b66f0091f..8dbc4cb0bfd35289924e9469fac17f95ec5f5f39 100644 --- a/src/libs/routes/api.js +++ b/src/libs/routes/api.js @@ -46,6 +46,8 @@ const resetToken = require(`${libs}/routes/resetToken`); const educationYears = require(`${libs}/routes/educationYears`); +const downloads = require(`${libs}/routes/downloads`); + const infrastructure = require(`${libs}/routes/infrastructure`); const distributionFactor = require(`${libs}/routes/distributionFactor`); @@ -77,6 +79,7 @@ api.use('/auth/token', oauth2.token); api.use('/verify', verifyToken); api.use('/reset', resetToken); api.use('/education_years', educationYears); +api.use('/downloads', downloads); api.use('/infrastructure', infrastructure); api.use('/distribution_factor', distributionFactor); api.use('/siope', siope); diff --git a/src/libs/routes/city.js b/src/libs/routes/city.js index 65fba27ea92db049f156a196b7fdbd2da0fc0756..1f6aee12630ba58b48f2f53bb17fc9ab10b4fad1 100644 --- a/src/libs/routes/city.js +++ b/src/libs/routes/city.js @@ -6,7 +6,7 @@ const libs = `${process.cwd()}/libs`; const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/class.js b/src/libs/routes/class.js index 63e782292cfba57c5eb61cd2551a55aaff981aee..1d944ccd1a45bd47a8409daf804fbc61480a0bb3 100644 --- a/src/libs/routes/class.js +++ b/src/libs/routes/class.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); @@ -18,7 +18,9 @@ const id2str = require(`${libs}/middlewares/id2str`); const config = require(`${libs}/config`); -const request = require(`request`); +const download = require(`${libs}/middlewares/downloadDatabase`); + +const passport = require('passport'); const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; @@ -342,42 +344,6 @@ classApp.get('/', rqfCount.parse(), rqfCount.build(), (req, res, next) => { next(); }, query, id2str.transform(), response('class')); -classApp.get('/download', (req, res, next) => { - // first, query the mapping - req.sql.from('mapping_turma') - .field('target_name') - .field('name'); - next(); -}, query, (req, res, next) => { - req.resetSql(); - next(); -}, rqfCount.parse(), rqfCount.build(), (req, res, next) => { - let username = req.query.user; - let email = req.query.email; - - req.sql.from('turma') - .field('*'); - let header = ''; - req.result.forEach((result) => { - if(header === '') header += result.name; - else header = header + ';' + result.name; - }); - - let form = { - query: req.sql.toString(), - table: req.sql.tableFrom, - name: req.sql.tableFrom, - username, - email, - header - }; - request.post(config.cdn.url + '/api/v1/file', {form}, (err, response, body) => { - if(err) { - log.error(err); - return res.json({error: err}); - } - res.json({msg: 'Wait for download email'}); - }); -}); +classApp.get('/download', passport.authenticate('bearer', { session: false }), rqfCount.parse(), rqfCount.build(), download('turma', 'mapping_turma')); module.exports = classApp; diff --git a/src/libs/routes/classroom.js b/src/libs/routes/classroom.js index f2dd5a3b5051509e1b3c62ba74f7a1267e807117..084291a740014d2811897b62fc16f51aeef3c0d1 100644 --- a/src/libs/routes/classroom.js +++ b/src/libs/routes/classroom.js @@ -6,7 +6,7 @@ const libs = `${process.cwd()}/libs`; const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/distributionFactor.js b/src/libs/routes/distributionFactor.js index f7d40502e6a0e6802b630405d916d0829b65be11..5cd08ebacb275672df829fe86a0ad0ae4ba42796 100644 --- a/src/libs/routes/distributionFactor.js +++ b/src/libs/routes/distributionFactor.js @@ -6,7 +6,7 @@ const libs = `${process.cwd()}/libs`; const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const multiQuery = require(`${libs}/middlewares/multiQuery`); diff --git a/src/libs/routes/downloads.js b/src/libs/routes/downloads.js new file mode 100644 index 0000000000000000000000000000000000000000..7a6c4172b690b08a9382336db00b9c361c3fa3b6 --- /dev/null +++ b/src/libs/routes/downloads.js @@ -0,0 +1,30 @@ +const express = require('express'); + +const downloadApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const Download = require(`${libs}/models/download`); + +const User = require(`${libs}/models/user`); + +const passport = require('passport'); + +downloadApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, next) => { + Download.find({userId: req.user._id}, (err, downloads) => { + if (err) { + log.error(err); + return next(err); + } + + if(!downloads) { + res.statusCode = 404; + return res.json({msg: 'Nenhum download encontrado'}); + } + res.json(downloads); + }); +}); + +module.exports = downloadApp; diff --git a/src/libs/routes/enrollment.js b/src/libs/routes/enrollment.js index 84e47d99518fd10741d9cb78d3cd695eecbf3629..1b9ad6ba46ea8bdff092529bfe504355eeff414a 100644 --- a/src/libs/routes/enrollment.js +++ b/src/libs/routes/enrollment.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); @@ -18,7 +18,9 @@ const id2str = require(`${libs}/middlewares/id2str`); const config = require(`${libs}/config`); -const request = require(`request`); +const passport = require('passport'); + +const download = require(`${libs}/middlewares/downloadDatabase`); const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; @@ -479,42 +481,6 @@ simRqf.addField({ } }); -enrollmentApp.get('/download', (req, res, next) => { - // first, query the mapping - req.sql.from('mapping_matricula') - .field('target_name') - .field('name'); -next(); -}, query, (req, res, next) => { - req.resetSql(); - next(); -}, rqf.parse(), rqf.build(), (req, res, next) => { - let username = req.query.user; - let email = req.query.email; - - req.sql.from('matricula') - .field('*'); - let header = ''; - req.result.forEach((result) => { - if(header === '') header += result.name; - else header = header + ';' + result.name; - }); - - let form = { - query: req.sql.toString(), - table: req.sql.tableFrom, - name: req.sql.tableFrom, - username, - email, - header - }; - request.post(config.cdn.url + '/api/v1/file', {form}, (err, response, body) => { - if(err) { - log.error(err); - return res.json({error: err}); - } - res.json({msg: 'Wait for download email'}); - }); -}); +enrollmentApp.get('/download', passport.authenticate('bearer', { session: false }), rqf.parse(), rqf.build(), download('matricula', 'mapping_matricula')); module.exports = enrollmentApp; diff --git a/src/libs/routes/idhm.js b/src/libs/routes/idhm.js index 4ac014d7ba6fb8b8e83fa1bccac4af3bdf8471db..278ca24b319c30b0b9a38aead8d09abc5dfbeb5b 100644 --- a/src/libs/routes/idhm.js +++ b/src/libs/routes/idhm.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/idhme.js b/src/libs/routes/idhme.js index 8b00559e3ace7f434eccae0c3506ab14481844dd..f9ba82b60b8312e492d71fecbba1e2e46b5c8789 100644 --- a/src/libs/routes/idhme.js +++ b/src/libs/routes/idhme.js @@ -6,7 +6,7 @@ const libs = `${process.cwd()}/libs`; const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/idhml.js b/src/libs/routes/idhml.js index 3a36276aebde7dc949e8e9c3db5780ba4bebb0ca..d8dd79c324a00ae03176bdcc4465e6493e779bf4 100644 --- a/src/libs/routes/idhml.js +++ b/src/libs/routes/idhml.js @@ -6,7 +6,7 @@ const libs = `${process.cwd()}/libs`; const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/idhmr.js b/src/libs/routes/idhmr.js index 6a1d0207faca396a3e2c9ca0bb5374c8917bca78..c2d29659d0aa0f063bce90b683fa197127655b11 100644 --- a/src/libs/routes/idhmr.js +++ b/src/libs/routes/idhmr.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/infrastructure.js b/src/libs/routes/infrastructure.js index ab9331cb8cb5dda65015b33ec013c32c493c4ad2..2e5ebec3aac4b03d8a8c89d5c6069b7760666a0f 100644 --- a/src/libs/routes/infrastructure.js +++ b/src/libs/routes/infrastructure.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const multiQuery = require(`${libs}/middlewares/multiQuery`); @@ -24,27 +24,29 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i let rqf = new ReqQueryFields(); -infrastructureApp.get('/year_range', cache('15 day'), (req, res, next) => { +infrastructureApp.use(cache('15 day')); + +infrastructureApp.get('/year_range', (req, res, next) => { req.sql.from('escola') .field('MIN(escola.ano_censo)', 'start_year') .field('MAX(escola.ano_censo)', 'end_year'); next(); }, query, response('range')); -infrastructureApp.get('/years', cache('15 day'), (req, res, next) => { +infrastructureApp.get('/years', (req, res, next) => { req.sql.from('escola') .field('DISTINCT escola.ano_censo', 'year'); next(); }, query, response('years')); -infrastructureApp.get('/source', cache('15 day'), (req, res, next) => { +infrastructureApp.get('/source', (req, res, next) => { req.sql.from('fonte') .field('fonte', 'source') .where('tabela = \'escola\''); next(); }, query, response('source')); -infrastructureApp.get('/location', cache('15 day'), (req, res, next) => { +infrastructureApp.get('/location', (req, res, next) => { req.result = [ {id: 1, name: 'Urbana'}, {id: 2, name: 'Rural'} @@ -52,7 +54,7 @@ infrastructureApp.get('/location', cache('15 day'), (req, res, next) => { next(); }, response('location')); -infrastructureApp.get('/location_detailed', cache('15 day'), (req, res, next) => { +infrastructureApp.get('/location_detailed', (req, res, next) => { req.result = [ {id: 1, name: "Urbana"}, {id: 2, name: "Rural"}, @@ -64,7 +66,7 @@ infrastructureApp.get('/location_detailed', cache('15 day'), (req, res, next) => next(); }, response('location_detailed')); -infrastructureApp.get('/adm_dependency', cache('15 day'), (req, res, next) => { +infrastructureApp.get('/adm_dependency', (req, res, next) => { req.sql.from('dependencia_adm') .field('id') .field('nome', 'name') @@ -72,7 +74,7 @@ infrastructureApp.get('/adm_dependency', cache('15 day'), (req, res, next) => { next(); }, query, response('adm_dependency')); -infrastructureApp.get('/adm_dependency_detailed', cache('15 day'), (req, res, next) => { +infrastructureApp.get('/adm_dependency_detailed', (req, res, next) => { req.sql.from('dependencia_adm_priv') .field('id', 'id') .field('nome', 'name'); @@ -251,7 +253,7 @@ function matchQueries(queryTotal, queryPartial) { return match; } -infrastructureApp.get('/', rqf.parse(), rqf.build(), cache('15 day'), (req, res, next) => { +infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.querySet = []; req.queryIndex = {}; diff --git a/src/libs/routes/pibpercapita.js b/src/libs/routes/pibpercapita.js index b503dca1283979fe8d5c3e8d44ce67b3397b145b..c7aaebc1662f2ade26dd2e1e280a4b5a23ec2ab0 100644 --- a/src/libs/routes/pibpercapita.js +++ b/src/libs/routes/pibpercapita.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/population.js b/src/libs/routes/population.js index c362941be6a1f07c129e64eaa60f104423a714d0..f08991b308147b7747b10ed461ccf45ac2424110 100644 --- a/src/libs/routes/population.js +++ b/src/libs/routes/population.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/region.js b/src/libs/routes/region.js index fdffe00fb8eb5d6ec406b3b62febf397e7ecb375..b1076e6484836b8a4911b8d0ada3631f1304e3c0 100644 --- a/src/libs/routes/region.js +++ b/src/libs/routes/region.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/school.js b/src/libs/routes/school.js index 933db24631cb0bd8741c46e049797610dbb980ff..4cbd1314327eb0b12147041cacff73dbfdae306e 100644 --- a/src/libs/routes/school.js +++ b/src/libs/routes/school.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); @@ -20,6 +20,10 @@ const request = require(`request`); const config = require(`${libs}/config`); +const passport = require('passport'); + +const download = require(`${libs}/middlewares/downloadDatabase`); + const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; let rqf = new ReqQueryFields(); @@ -469,42 +473,6 @@ schoolApp.get('/count', cache('15 day'), rqfCount.parse(), rqfCount.build(), (re next(); }, query, id2str.transform(), response('school')); -schoolApp.get('/count/download', (req, res, next) => { - // first, query the mapping - req.sql.from('mapping_escola') - .field('target_name') - .field('name'); - next(); -}, query, (req, res, next) => { - req.resetSql(); - next(); -}, rqfCount.parse(), rqfCount.build(), (req, res, next) => { - let username = req.query.user; - let email = req.query.email; - - req.sql.from('escola').field('*'); - let header = ''; - req.result.forEach((result) => { - req.sql.field(result.name, result.target_name); - if(header === '') header += result.target_name; - else header = header + ';' + result.target_name; - }); - - let form = { - query: req.sql.toString(), - table: req.sql.tableFrom, - name: req.sql.tableFrom, - username, - email, - header - }; - request.post(config.cdn.url + '/api/v1/file', {form}, (err, response, body) => { - if(err) { - log.error(err); - return res.json({error: err}); - } - res.json({msg: 'Wait for download email'}); - }); -}); +schoolApp.get('/count/download', passport.authenticate('bearer', { session: false }), rqfCount.parse(), rqfCount.build(), download('escola', 'mapping_escola')); module.exports = schoolApp; diff --git a/src/libs/routes/simulation.js b/src/libs/routes/simulation.js index 5e02c03a09bb71996c2fc279fd9a5563e32f825e..13dcd9e5f9b0d87edf4c9e22a75b975c55b0a2f5 100644 --- a/src/libs/routes/simulation.js +++ b/src/libs/routes/simulation.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/siope.js b/src/libs/routes/siope.js index 622da904d074ff80b1d328bcada59ad23eb317ec..51c1c36833b99ff097cf8a85a0c90c20598f737b 100644 --- a/src/libs/routes/siope.js +++ b/src/libs/routes/siope.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const multiQuery = require(`${libs}/middlewares/multiQuery`); diff --git a/src/libs/routes/spatial.js b/src/libs/routes/spatial.js new file mode 100644 index 0000000000000000000000000000000000000000..844255316dc35da602201aae0bdb1268070309f6 --- /dev/null +++ b/src/libs/routes/spatial.js @@ -0,0 +1,355 @@ +const express = require('express'); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const log = require(`${libs}/log`)(module); + +const query = require(`${libs}/middlewares/query`).query; + +const sqlQuery = require(`${libs}/db/query_exec`); + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const spatialApp = express(); + +let rqf = new ReqQueryFields(); + +function processResultSet(querySet, querySetLabels = ["result"], singleResult = false) { + const resultMap = new Map(); + let resultIdx = 0; + // loop relies on the fact that Promise.all maintains the order of the original iterable + for(let result of querySet) { + const resultLbl = querySetLabels[resultIdx]; + resultMap[resultLbl] = []; + if (singleResult) { + resultMap[resultLbl] = result[0]; + } else { + for(let row of result) { + log.debug(row); + resultMap[resultLbl].push(row); + } + } + resultIdx++; + } + log.debug(resultMap); + return resultMap; +} + +function dbExecAll(querySet = []) { + // Issue all queries concurrently to the database, for every query object in the iterable + // NOTE: Array.map() returns a copy of the original array with each object 'mapped'. + return querySet.map((qry) => { return sqlQuery(qry.toString()); }); +} + +rqf.addField({ + name: 'filter', + field: true, + where: true +}).addValue({ + name: 'region', + table: 'regiao', + tableField: 'nome', + resultField: 'region_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id' + } +}).addValue({ + name: 'school', + table: 'escola', + tableField: 'nome_escola', + resultField: 'school_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}); + +spatialApp.get('/sociodemographic', rqf.parse(), rqf.build(), (req, res, next) => { + const populationYearQry = squel.select() + .field('MAX(ibge_populacao.ano_censo)') + .from('ibge_populacao'); + + const populationQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('SUM(populacao)', 'population') + .field('ibge_populacao.ano_censo', 'census_year') + .from('ibge_populacao') + .where(`ibge_populacao.ano_censo IN (${populationYearQry.toString()})`) + .group('ibge_populacao.ano_censo'); + + const pibYearQry = squel.select() + .field('MAX(ibge_pib.ano_censo)') + .from('ibge_pib'); + + const pibQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('AVG(ibge_pib.pib_per_capita)', 'gdp_per_capita') + .field('ibge_pib.ano_censo', 'census_year') + .from('ibge_pib') + .where(`ibge_pib.ano_censo IN (${pibYearQry.toString()})`) + .group('ibge_pib.ano_censo'); + + const idhYearQry = squel.select() + .field('MAX(adh_idh.ano_censo)') + .from('adh_idh'); + + const idhQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('AVG(idhm)', 'idhm') + .field('adh_idh.ano_censo', 'census_year') + .from('adh_idh') + .where(`adh_idh.ano_censo IN (${idhYearQry.toString()})`) + .group('adh_idh.ano_censo'); + + const analfabYearQry = squel.select() + .field('MAX(adh_analfabetismo.ano_censo)') + .from('adh_analfabetismo'); + + const analfabQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('AVG(t_analf15m)', 'analfabetism') + .field('adh_analfabetismo.ano_censo', 'census_year') + .from('adh_analfabetismo') + .where(`adh_analfabetismo.ano_censo IN (${analfabYearQry.toString()})`) + .group('adh_analfabetismo.ano_censo'); + + const giniYearQry = squel.select() + .field('MAX(adh_gini.ano_censo)') + .from('adh_gini'); + + const giniQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('AVG(gini)', 'gini') + .field('adh_gini.ano_censo', 'census_year') + .from('adh_gini') + .where(`adh_gini.ano_censo IN (${giniYearQry.toString()})`) + .group('adh_gini.ano_censo'); + + // map query objects to their respective response labels + const queryLabels = [ "population", "gdp", "idh", "analfab", "gini" ]; + const querySet = [ populationQry, pibQry, idhQry, analfabQry, giniQry ]; + // wait until all queries finish or one of them fail + Promise.all(dbExecAll(querySet)).then((queryResults) => { + req.result = processResultSet(queryResults, queryLabels, true); + next(); + }).catch((error) => { + log.error(`[SQL query error] ${error}`); + next(error); + }); +}, response('spatial')); + +spatialApp.get('/educational', rqf.parse(), rqf.build(), (req, res, next) => { + const censusYearQry = squel.select() + .field('MAX(escola.ano_censo)', 'ano_censo') + .from('escola') + .toString(); + + const totalSchoolsQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('\'Total\'', 'location_name') + .field('COUNT(DISTINCT(escola.id))', 'total') + .field('escola.ano_censo', 'census_year') + .from('turma') + .from('escola') + .where('escola.ano_censo=turma.ano_censo AND escola.id=turma.escola_id') + .where(`escola.ano_censo IN (${censusYearQry})`) + .where('turma.tipo_turma_id = 0') + .group('escola.ano_censo'); + + const schoolsPerLocationQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('COUNT(DISTINCT(escola.id))', 'total') + .field('escola.ano_censo', 'census_year') + .field('localizacao.descricao', 'location_name') + .from('localizacao') + .from('turma') + .from('escola') + .where('escola.cod_localizacao=localizacao.id') + .where('escola.ano_censo=turma.ano_censo AND escola.id=turma.escola_id') + .where(`escola.ano_censo IN (${censusYearQry})`) + .where('turma.tipo_turma_id = 0') + .group('escola.cod_localizacao') + .group('escola.ano_censo') + .group('localizacao.descricao') + .order('localizacao.descricao'); + + const schoolsPerAdmDependencyQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('COUNT(DISTINCT(escola.id))', 'total') + .field('escola.ano_censo', 'census_year') + .field('dependencia_adm.nome', 'adm_dependency_name') + .from('dependencia_adm') + .from('escola') + .where('escola.dependencia_adm_id=dependencia_adm.id') + .where(`escola.ano_censo IN (${censusYearQry})`) + .group('escola.ano_censo') + .group('dependencia_adm.nome') + .order('escola.ano_censo') + .order('dependencia_adm.nome'); + + const enrollmentsQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('COALESCE(SUM(uc201.matriculas), 0)', 'total') + .field('uc201.ano_censo', 'census_year') + .from('uc201') + .group('uc201.ano_censo'); + + const enrollmentsPerAdmDepQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('COALESCE(SUM(uc201.matriculas), 0)', 'total') + .field('uc201.ano_censo', 'census_year') + .field('dependencia_adm.nome', 'adm_dependency_name') + .from('dependencia_adm') + .from('uc201') + .where('uc201.dependencia_adm_id=dependencia_adm.id') + .group('dependencia_adm.nome') + .group('uc201.ano_censo'); + + const enrollmentsPerSchoolLevelQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('COALESCE(SUM(uc201.matriculas), 0)', 'total') + .field('uc201.ano_censo', 'census_year') + .field('etapa_ensino.desc_etapa', 'school_level_name') + .field('dependencia_adm.nome', 'adm_dependency_name') + .from('etapa_ensino') + .from('dependencia_adm') + .from('uc201') + .where('uc201.etapas_mod_ensino_segmento_id=etapa_ensino.id') + .where('uc201.dependencia_adm_id=dependencia_adm.id') + .group('etapa_ensino.desc_etapa') + .group('dependencia_adm.nome') + .group('uc201.ano_censo'); + + const enrollmentsPerLocationQry = req.sql.clone() + .field('\'Brasil\'', 'name') + .field('COALESCE(SUM(uc201.matriculas), 0)', 'total') + .field('uc201.ano_censo', 'census_year') + .field('localizacao.descricao', 'location_name') + .from('localizacao') + .from('uc201') + .where('uc201.localizacao=localizacao.id') + .group('localizacao.descricao') + .group('uc201.ano_censo'); + + const queryLabels = [ "school", "school_per_location", "school_per_adm_dependency", "enrollment", "enrollment_per_adm_dep", + "enrollment_per_school_level", "enrollment_per_location" ]; + const querySet = [ totalSchoolsQry, schoolsPerLocationQry, schoolsPerAdmDependencyQry, enrollmentsQry, + enrollmentsPerAdmDepQry, enrollmentsPerSchoolLevelQry, enrollmentsPerLocationQry]; + // wait until all queries finish or one of them fail + Promise.all(dbExecAll(querySet)).then((queryResults) => { + req.result = processResultSet(queryResults, queryLabels); + next(); + }).catch((error) => { + log.error(`[SQL query error] ${error}`); + next(error); + }); +}, response('spatial')); + +spatialApp.get('/educational/school_level', rqf.parse(), rqf.build(), (req, res, next) => { + const enrollmentsPerSchoolLevelYearQry = squel.select() + .field('MAX(matricula.ano_censo)', 'census_year') + .from('matricula'); + + const enrollmentsPerSchoolLevelQry = req.sql.clone() + .field('COALESCE(COUNT(matricula.id), 0)', 'total') + .field('matricula.ano_censo', 'census_year') + .field('matricula.serie_ano_id', 'school_year') + .field('etapa_ensino.desc_etapa', 'school_level') + .from('etapa_ensino') + .from('matricula') + .where(`matricula.ano_censo IN (${enrollmentsPerSchoolLevelYearQry.toString()})`) + .where('matricula.etapa_ensino_id = etapa_ensino.id') + .where('matricula.tipo <= 3') + .group('etapa_ensino.desc_etapa') + .group('etapa_ensino.id') + .group('matricula.serie_ano_id') + .group('matricula.ano_censo') + .order('etapa_ensino.id') + .order('matricula.serie_ano_id') + .order('matricula.ano_censo'); + + const queryLabels = [ 'enrollment_per_school_level', 'enrollment_census_year' ]; + const querySet = [ enrollmentsPerSchoolLevelQry, enrollmentsPerSchoolLevelYearQry ]; + // wait until all queries finish or one of them fail + Promise.all(dbExecAll(querySet, enrollmentsPerSchoolLevelYearQry)).then((queryResults) => { + const result = queryResults[0]; + const censusYear = queryResults[1][0]['census_year']; + + let school_levels = {}; + for(let i = 0; i < result.length; ++i) { + const school_year = id2str.schoolYear(result[i].school_year); + const school_level = result[i].school_level; + const census_year = result[i].census_year; + if (typeof school_levels[school_level] === 'undefined') { + school_levels[school_level] = {}; + } + school_levels[school_level][school_year] = parseInt(result[i].total, 10); + } + + let response = []; + for(let level in school_levels) { + if (school_levels.hasOwnProperty(level)) { + let sclevel = {}; + sclevel["degree"] = level; + sclevel["census_year"] = parseInt(censusYear, 10); + sclevel["table"] = []; + for(let school_year in school_levels[level]) { + if (school_levels[level].hasOwnProperty(school_year)) { + let enrollment = { 'title' : school_year, + 'value' : school_levels[level][school_year] }; + sclevel["table"].push(enrollment); + } + } + response.push(sclevel); + } + } + req.result = response; + next(); + }).catch((error) => { + log.error(`[SQL query error] ${error}`); + next(error); + }); +}, response('spatial')); + +module.exports = spatialApp; diff --git a/src/libs/routes/state.js b/src/libs/routes/state.js index 67bdfc1bfe86f6976d5af8bf6a31e32ac9dc997b..33778869342216fe40e8e5104f327d4f2de804ef 100644 --- a/src/libs/routes/state.js +++ b/src/libs/routes/state.js @@ -6,7 +6,7 @@ const libs = `${process.cwd()}/libs`; const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); diff --git a/src/libs/routes/teacher.js b/src/libs/routes/teacher.js index 1d357763c3b3be2c55996fd756258fe0e75064b9..5dd885489544239f35d067d1bd0a3aede03bdeeb 100644 --- a/src/libs/routes/teacher.js +++ b/src/libs/routes/teacher.js @@ -8,7 +8,7 @@ const log = require(`${libs}/log`)(module); const squel = require('squel'); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const response = require(`${libs}/middlewares/response`); @@ -18,7 +18,9 @@ const id2str = require(`${libs}/middlewares/id2str`); const config = require(`${libs}/config`); -const request = require(`request`); +const passport = require('passport'); + +const download = require(`${libs}/middlewares/downloadDatabase`); const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; @@ -410,42 +412,6 @@ teacherApp.get('/', rqf.parse(), (req, res, next) => { next(); }, id2str.transform(), response('teacher')); -teacherApp.get('/download', (req, res, next) => { - // first, query the mapping - req.sql.from('mapping_docente') - .field('target_name') - .field('name'); - next(); -}, query, (req, res, next) => { - req.resetSql(); - next(); -}, rqf.parse(), rqf.build(), (req, res, next) => { - let username = req.query.user; - let email = req.query.email; - - req.sql.from('docente') - .field('*'); - let header = ''; - req.result.forEach((result) => { - if(header === '') header += result.name; - else header = header + ';' + result.name; - }); - - let form = { - query: req.sql.toString(), - table: req.sql.tableFrom, - name: req.sql.tableFrom, - username, - email, - header - }; - request.post(config.cdn.url + '/api/v1/file', {form}, (err, response, body) => { - if(err) { - log.error(err); - return res.json({error: err}); - } - res.json({msg: 'Wait for download email'}); - }); -}); +teacherApp.get('/download', passport.authenticate('bearer', { session: false }), rqf.parse(), rqf.build(), download('docente', 'mapping_docente')); module.exports = teacherApp; diff --git a/src/test/query.js b/src/test/query.js index 8b6c4541859c20f3ea733046cddc8af81b01d0b3..cad0102ff882c4eb2121cb99c804b3b8b84f0fa4 100644 --- a/src/test/query.js +++ b/src/test/query.js @@ -22,7 +22,7 @@ const libs = `${process.cwd()}/libs`; const server = require(`${libs}/app`); -const query = require(`${libs}/middlewares/query`); +const query = require(`${libs}/middlewares/query`).query; const squel = require('squel');