diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 90d49bbe2acae1aa3d36e0b4a42ae3cdf0ead3e2..dc8c4b6d8bd52a50299f89730400bdda9ba54e58 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ run_tests: - ping -W1 -c1 mongo - mv config.json.example config.json - sed -i -e 's/false/true/g' config.json - - sed -i -e 's/simcaq_dev/simcaq_dev2/g' config.json + - sed -i -e 's/simcaq_dev/simcaq_dev3/g' config.json - gulp build - gulp test tags: diff --git a/src/libs/convert/educationType.js b/src/libs/convert/educationType.js new file mode 100644 index 0000000000000000000000000000000000000000..99f4ddd70e8f5885c1a4a4ff4094f2fb2ca40c83 --- /dev/null +++ b/src/libs/convert/educationType.js @@ -0,0 +1,20 @@ +module.exports = function educationType(id) { + switch (id) { + case 1: + return 'Ensino Fundamental'; + case 2: + return 'Ensino Médio'; + case 3: + return 'Médio Normal ou Magistério'; + case 4: + return 'Superior'; + case 5: + return 'Superior com licenciatura'; + case 6: + return 'Especialização'; + case 7: + return 'Mestrado ou Doutorado'; + default: + return 'Não definido'; + } +}; diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js index 3abce698b58639fc17398516636b161407d4bbf1..ae9ae4634767e7a14a2ea197335d05169ea10618 100644 --- a/src/libs/middlewares/id2str.js +++ b/src/libs/middlewares/id2str.js @@ -9,6 +9,7 @@ const agreement = require(`${libs}/convert/agreement`); const booleanVariable = require(`${libs}/convert/booleanVariable`); const educationLevel = require(`${libs}/convert/educationLevel`); const educationLevelMod = require(`${libs}/convert/educationLevelMod`); +const educationType = require(`${libs}/convert/educationType`); const ids = { gender_id: gender, @@ -50,7 +51,8 @@ const ids = { library_reading_room_id: booleanVariable, library_id: booleanVariable, reading_room_id: booleanVariable, - water_id: booleanVariable + water_id: booleanVariable, + education_type_id: educationType }; function transform(removeId=false) { @@ -80,5 +82,6 @@ module.exports = { agreement, booleanVariable, educationLevel, - educationLevelMod + educationLevelMod, + educationType }; diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js index f28dc6c1aaeffd19ca257b9af51ec4510d285719..2e7c9a3efd4267a6e75f5e53ed187eebde464e2a 100644 --- a/src/libs/routes/api.js +++ b/src/libs/routes/api.js @@ -28,6 +28,8 @@ const user = require('./user'); const classroom = require('./classroom'); +const teacher = require('./teacher'); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API is running' }); }); @@ -43,5 +45,6 @@ api.use('/city', cache('15 day'), city); api.use('/school', cache('15 day'), school); api.use('/spatial', cache('1 day'), spatial); api.use('/classroom', cache('15 day'), classroom); +api.use('/teacher', cache('1 day'), teacher); module.exports = api; diff --git a/src/libs/routes/teacher.js b/src/libs/routes/teacher.js new file mode 100644 index 0000000000000000000000000000000000000000..5a70c8350b1ee1bc42336eb6f70c409757ad93d4 --- /dev/null +++ b/src/libs/routes/teacher.js @@ -0,0 +1,257 @@ +const express = require('express'); + +const teacherApp = 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`); + +const id2str = require(`${libs}/middlewares/id2str`); + +let rqf = new ReqQueryFields(); + +// Returns a tuple of start and ending years of the complete enrollments dataset. +teacherApp.get('/year_range', (req, res, next) => { + req.sql.from('docente') + .field('MIN(docente.ano_censo)', 'start_year') + .field('MAX(docente.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +teacherApp.get('/adm_dependency_detailed', (req, res, next) => { + req.sql.from('dependencia_adm') + .field('id', 'id') + .field('nome', 'name'); + next(); +}, query, response('adm_dependency_detailed')); + +teacherApp.get('/adm_dependency', (req, res, next) => { + req.sql.from('dependencia_adm') + .field('id') + .field('nome', 'name') + .where('id <= 4'); + next(); +}, query, response('adm_dependency')); + +teacherApp.get('/education_level_mod', (req, res, next) => { + req.sql.from('etapas_mod_ensino_segmento') + .field('id') + .field('nome', 'name'); + next(); +}, query, response('education_level_mod')); + +teacherApp.get('/location', (req, res, next) => { + req.sql.from('localizacao') + .field('id') + .field('descricao', 'name') + .where('id <= 2'); + next(); +}, query, response('location')); + +teacherApp.get('/education_type', (req, res, next) => { + req.sql.from('docente') + .field('DISTINCT nivel_tipo_formacao', 'id') + .order('id'); + next(); +}, query, (req, res, next) => { + req.result.forEach((result) => { + result.name = id2str.educationType(result.id); + }); + next(); +}, response('education_type')); + +teacherApp.get('/gender', (req, res, next) => { + req.result = [ + {id: 1, name: 'Masculino'}, + {id: 2, name: 'Feminino'} + ]; + next(); +}, response('gender')); + +teacherApp.get('/ethnic_group', (req, res, next) => { + req.sql.from('cor_raca') + .field('id') + .field('nome', 'name'); + next(); +}, query, response('ethnic_group')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'adm_dependency', + table: 'docente', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'docente', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'education_level_mod', + table: 'docente', + tableField: 'etapas_mod_ensino_segmento_id', + resultField: 'education_level_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'etapas_mod_ensino_segmento_id' + } +}).addValue({ + name: 'education_type', + table: 'docente', + tableField: 'nivel_tipo_formacao', + resultField: 'education_type_id', + where: { + relation: '=', + type: 'integer', + field: 'nivel_tipo_formacao' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: 'nome', + resultField: 'region_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_regiao_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_estado_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}).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: 'docente' + } +}).addValue({ + name: 'location', + table: 'docente', + tableField: 'cod_localizacao', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_localizacao' + } +}).addValue({ + name: 'min_year', + table: 'docente', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'docente', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'gender', + table: 'docente', + tableField: 'sexo', + resultField: 'gender_id', + where: { + relation: '=', + type: 'integer', + field: 'sexo' + } +}).addValue({ + name: 'ethnic_group', + table: 'docente', + tableField: 'cor_raca', + resultField: 'ethnic_group_id', + where: { + relation: '=', + type: 'integer' + } +}); + +teacherApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.field('COUNT(DISTINCT docente.id)', 'total') + .field("'Brasil'", 'name') + .field('docente.ano_censo', 'year') + .from('docente') + .join('turma', null, 'docente.turma_id=turma.id') + .group('docente.ano_censo') + .order('docente.ano_censo') + .where('(docente.tipo_docente = 1 OR docente.tipo_docente = 5) AND (turma.tipo_turma_id <= 3)'); + next(); +}, query, id2str.transform(true), response('teacher')); + +module.exports = teacherApp; diff --git a/src/test/teacher.js b/src/test/teacher.js new file mode 100644 index 0000000000000000000000000000000000000000..0b3cb7bdd528ddde998d5fc35e1aabd35e95b1c9 --- /dev/null +++ b/src/test/teacher.js @@ -0,0 +1,327 @@ +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 teachers', () => { + it('should list the year range', (done) => { + chai.request(server) + .get('/api/v1/teacher/year_range') + .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('start_year'); + res.body.result[0].should.have.property('end_year'); + done(); + }); + }); + + it('should list the locations', (done) => { + chai.request(server) + .get('/api/v1/teacher/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 mod', (done) => { + chai.request(server) + .get('/api/v1/teacher/education_level_mod') + .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 type', (done) => { + chai.request(server) + .get('/api/v1/teacher/education_type') + .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/teacher/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 administrative dependencies detailed', (done) => { + chai.request(server) + .get('/api/v1/teacher/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 genders', (done) => { + chai.request(server) + .get('/api/v1/teacher/gender') + .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 ethnic groups', (done) => { + chai.request(server) + .get('/api/v1/teacher/ethnic_group') + .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 teachers count', (done) => { + chai.request(server) + .get('/api/v1/teacher') + .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 teacher count with valid filters', (done) => { + chai.request(server) + .get('/api/v1/teacher?filter=min_year:2014,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 teacher count with invalid filters', (done) => { + chai.request(server) + .get('/api/v1/teacher?filter=foo:2010,bar: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 teacher count with valid dimensions', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=region,state,adm_dependency,location,gender,ethnic_group') + .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 teacher count with invalid dimensions', (done) => { + chai.request(server) + .get('/api/v1/teacher?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 teacher count with valid dimensions and filters', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=region,state,school,gender&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('total'); + res.body.result[0].should.have.property('year'); + done(); + }); + }); + + it('should list teacher count with dimension location', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=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('location_name'); + res.body.result[0].should.not.have.property('location_id'); + done(); + }); + }); + + it('should list teacher count with dimension education_level_mod', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=education_level_mod') + .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('education_level_mod_name'); + res.body.result[0].should.not.have.property('education_level_mod_id'); + done(); + }); + }); + + it('should list teacher count with dimension education type', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=education_type') + .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('education_type_name'); + res.body.result[0].should.not.have.property('education_type_id'); + done(); + }); + }); + + it('should list teacher count with dimension adm_dependency', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=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('adm_dependency_name'); + res.body.result[0].should.not.have.property('adm_dependency_id'); + done(); + }); + }); + + it('should list teacher count with dimension adm_dependency_detailed', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=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('adm_dependency_detailed_name'); + res.body.result[0].should.not.have.property('adm_dependency_detailed_id'); + done(); + }); + }); + + it('should list teacher count with dimension gender', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=gender') + .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('gender_name'); + res.body.result[0].should.not.have.property('gender_id'); + done(); + }); + }); + + it('should list teacher count with dimension ethnic_group', (done) => { + chai.request(server) + .get('/api/v1/teacher?dims=ethnic_group') + .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('ethnic_group_name'); + res.body.result[0].should.not.have.property('ethnic_group_id'); + done(); + }); + }); +});