diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js index ce905d8bd1f8476c38795a03a78347c85ed9cda3..d2119dd2694ab2aa24186a180f3b8bb67b82518f 100644 --- a/src/libs/routes/api.js +++ b/src/libs/routes/api.js @@ -6,6 +6,8 @@ const libs = `${process.cwd()}/libs`; const config = require(`${libs}/config`); +const classes = require('./class'); + const cache = require('apicache').options({ debug: config.debug }).middleware; const enrollment = require('./enrollment'); @@ -31,6 +33,7 @@ api.get('/', (req, res) => { // mount API routes api.use('/user', user); api.use('/simulation', simulation); +api.use('/class', cache('15 day'), classes); api.use('/enrollment', cache('1 day'), enrollment); api.use('/state', cache('15 day'), state); api.use('/region', cache('15 day'), region); diff --git a/src/libs/routes/class.js b/src/libs/routes/class.js new file mode 100644 index 0000000000000000000000000000000000000000..dc0f02588ef387ad7fb6d6503773754de4a54af5 --- /dev/null +++ b/src/libs/routes/class.js @@ -0,0 +1,247 @@ +const express = require('express'); + +const classApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`); + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +let rqfCount = new ReqQueryFields(); +// Complete range of the enrollments dataset. +// Returns a tuple of start and ending years of the complete enrollments dataset. +classApp.get('/year_range', (req, res, next) => { + req.sql.from('turma') + .field('MIN(turma.ano_censo)', 'start_year') + .field('MAX(turma.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +classApp.get('/location', (req, res, next) => { + req.sql = squel.select() + .field('id') + .field('descricao', 'name') + .from('localizacao'); + next(); +}, query, response('location')); + +// Returns all adm dependencies +classApp.get('/adm_dependency', (req, res, next) => { + req.sql.from('dependencia_adm') + .field('id') + .field('nome', 'name') + .where('id <= 4'); + next(); +}, query, response('adm_dependency')); + +classApp.get('/adm_dependency_detailed', (req, res, next) => { + req.sql.from('dependencia_adm') + .field('id', 'id') + .field('nome', 'name'); + next(); +}, query, response('adm_dependency_detailed')); + +// Returns all periods avaible +classApp.get('/period', (req, res, next) => { + req.sql.from('turma_turno') + .field('id') + .field('nome', 'name'); + next(); +}, query, response('period')); + +// Returns all educational levels avaible +classApp.get('/education_level', (req, res, next) => { + req.sql.from('etapas_mod_ensino_segmento') + .field('id') + .field('nome', 'name'); + next(); +}, query, response('education_level')); + +rqfCount.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'turma' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'turma' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: 'nome', + resultField: 'region_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'min_year', + table: 'turma', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'turma', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name:'adm_dependency', + table: 'dependencia_adm', + tableField: 'id', + resultField: 'adm_dependency_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'dependencia_adm_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'location', + table: 'localizacao', + tableField: 'descricao', + resultField: 'location_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'localizacao_id', + foreignTable: 'turma' + } +}).addValue({ + name:'education_level', + table: 'etapas_mod_ensino_segmento ', + tableField: 'id', + resultField: 'education_level_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'etapas_mod_ensino_segmento_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'dependencia_adm', + tableField: 'nome', + resultField: 'adm_dependency_detailed_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'dependencia_adm_priv', + foreignTable: 'turma' + } +}).addValue({ + name:'period', + table: 'turma_turno', + tableField: 'id', + resultField: 'period_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'turno', + foreignTable: 'turma' + } +}).addValue({ + name: 'school', + table: 'escola', + tableField: 'nome_escola', + resultField: 'school_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'turma' + } +}); + + +classApp.get('/', rqfCount.parse(), rqfCount.build(), (req, res, next) => { + log.debug(req.sql.toParam()); + req.sql.field('COUNT(turma.id)', 'total') + .field("'Brasil'", 'name') + .field('turma.ano_censo', 'year') + .from('turma') + .group('turma.ano_censo') + .order('turma.ano_censo') + .where('turma.tipo_turma_id = 0 OR turma.tipo_turma_id = 1 OR turma.tipo_turma_id = 2 OR turma.tipo_turma_id = 3'); + next(); +}, query, response('class')); + +module.exports = classApp; diff --git a/src/test/class.js b/src/test/class.js new file mode 100644 index 0000000000000000000000000000000000000000..3cf5f354e384a1e94e8362590d2ac0a133ee6fbe --- /dev/null +++ b/src/test/class.js @@ -0,0 +1,173 @@ +process.env.NODE_ENV = 'test'; + +const chai = require('chai'); + +const dirtyChai = require('dirty-chai'); + +chai.use(dirtyChai); + +const chaiXml = require('chai-xml'); + +chai.use(chaiXml); + +const chaiHttp = require('chai-http'); + +const assert = chai.assert; + +const expect = chai.expect; + +const should = chai.should(); // actually call the function + +const libs = `${process.cwd()}/libs`; + +const server = require(`${libs}/app`); + +chai.use(chaiHttp); +describe('request enrollments', () => { + it('should list the locations', (done) => { + chai.request(server) + .get('/api/v1/class/location') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('id'); + res.body.result[0].should.have.property('name'); + done(); + }); + }); + + it('should list the education level', (done) => { + chai.request(server) + .get('/api/v1/class/education_level') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('id'); + res.body.result[0].should.have.property('name'); + done(); + }); + }); + + it('should list the administrative dependencies', (done) => { + chai.request(server) + .get('/api/v1/class/adm_dependency_detailed') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('id'); + res.body.result[0].should.have.property('name'); + done(); + }); + }); + + it('should list the administrative dependencies detailed', (done) => { + chai.request(server) + .get('/api/v1/class/adm_dependency') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('id'); + res.body.result[0].should.have.property('name'); + done(); + }); + }); + + it('should list the periods', (done) => { + chai.request(server) + .get('/api/v1/enrollment/period') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('id'); + res.body.result[0].should.have.property('name'); + done(); + }); + }); + + it('should list class', (done) => { + chai.request(server) + .get('/api/v1/class') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('name'); + res.body.result[0].should.have.property('total'); + done(); + }); + }); + + it('should list class with valid filters', (done) => { + chai.request(server) + .get('/api/v1/class?filter=state:41') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('name'); + res.body.result[0].should.have.property('total'); + done(); + }); + }); + + it('should list class with valid dimensions', (done) => { + chai.request(server) + .get('/api/v1/class?dims=region,state,adm_dependency,location&filter=region:1') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('region_name'); + res.body.result[0].should.have.property('state_name'); + res.body.result[0].should.have.property('adm_dependency_name'); + res.body.result[0].should.have.property('location_name'); + res.body.result[0].should.have.property('total'); + done(); + }); + }); + + it('should list class with invalid dimensions', (done) => { + chai.request(server) + .get('/api/v1/class?dims=foo,bar') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('name'); + res.body.result[0].should.have.property('total'); + done(); + }); + }); + + it('should list class with valid dimensions and filters', (done) => { + chai.request(server) + .get('/api/v1/class?dims=region,state,education_level,school,period&filter=min_year:2015,max_year:2015,city:4106902') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('result'); + res.body.result.should.be.a('array'); + res.body.result[0].should.have.property('region_name'); + res.body.result[0].should.have.property('state_name'); + res.body.result[0].should.have.property('school_name'); + res.body.result[0].should.have.property('education_level_name'); + res.body.result[0].should.have.property('total'); + res.body.result[0].should.have.property('year'); + done(); + }); + }); +});