From 18ac5587c658cc824745a4e30fafe5bb0bd3cd21 Mon Sep 17 00:00:00 2001 From: SimCAQ-Homologa <root@simcaqhomologa.c3sl.ufpr.br> Date: Thu, 6 Apr 2023 09:17:34 -0300 Subject: [PATCH 001/123] Inicializa migracao --- src/libs/api_mongo.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/libs/api_mongo.txt diff --git a/src/libs/api_mongo.txt b/src/libs/api_mongo.txt new file mode 100644 index 00000000..c1353348 --- /dev/null +++ b/src/libs/api_mongo.txt @@ -0,0 +1,5 @@ +*downloads.js +*resetToken.js +*simulation.js +*user.js +*verifyToken.js -- GitLab From 083b5758cd1bf26fd0b4417ef96631d56b54d75f Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 10 Apr 2023 11:44:33 -0300 Subject: [PATCH 002/123] Setting up a Sequelize --- package.json | 2 + src/libs/models/user.js | 247 +++++++++++++++++++++++----------------- 2 files changed, 147 insertions(+), 102 deletions(-) diff --git a/package.json b/package.json index 7dfdb851..672cb1d7 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,8 @@ "passport-http-bearer": "^1.0.1", "passport-oauth2-client-password": "^0.1.2", "request": "^2.88.0", + "sequelize": "^6.31.0", + "sequelize-cli": "^6.6.0", "sqlstring": "^2.3.1", "squel": "^5.12.2", "winston": "^2.4.4" diff --git a/src/libs/models/user.js b/src/libs/models/user.js index be62f4a5..d7c992f0 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -1,119 +1,162 @@ -const mongoose = require('mongoose'); +const Sequelize = require("sequelize"); const crypto = require('crypto') const libs = `${process.cwd()}/libs`; const log = require(`${libs}/log`)(module); -const Schema = mongoose.Schema; -// set up a mongoose model -var UserSchema = new Schema({ - email: { - type: String, - unique: true, - required: [true, 'O campo Email é obrigatório.'] - }, - hashedPassword: { - type: String, - required: [true, 'O campo Senha é obrigatório.'] - }, - salt: { - type: String, - required: true - }, - name: { - type: String, - required: [true, 'O campo Nome é obrigatório.'] - }, - nickname: { - type: String, - required: [true, 'O campo Apelido é obrigatório.'] - }, - cpf:{ - type: String, - unique: true, - required: [true, 'O campo CPF é obrigatório.'] - }, - cep:{ - type: String, - required: [true, 'O campo CEP é obrigatório.'] - }, - schooling: { - type: String, - required: [true, 'O campo Formação é obrigatório.'] - }, - course: { - type: String, - }, - complement: { - type: String, - }, - address: { - type: String, - }, - phone: { - type: String, - }, - segment: { - type: String, - required: [true, 'O campo Segmento é obrigatório.'] - }, - role: { - type: String, - required: [true, 'O campo Função é obrigatório.'] - }, - institutionName: { - type: String, - required: [true, 'O campo Instituição em que trabalha ou estuda é obrigatório.'] - }, - state: { - type: String, - required: [true, 'O campo Estado é obrigatório.'] - }, - city: { - type: String, - required: [true, 'O campo Cidade é obrigatório.'] - }, - receiveEmails: { - type: Boolean - }, - createdAt: { - type: Date, - default: Date.now - }, - origin: { - type: String, - enum: ['LDE', 'SimCAQ', 'MAPFOR'], - required: [true, 'O campo origem é obrigatória e aceita apenas os valores "LDE", "SimCAQ" e "MAPFOR"'] - }, - verified: { - type: Boolean, - default: false - }, - citesegment: { - type: String - }, - citerole: { - type: String - }, - admin: { - type: Boolean, - default: false - } -}); +// set up a sequelize model +var User = sequelize.define("User",{ + email: { + type: Sequelize.STRING, + allowNull: false, + unique: true, + validate: { + notNull: { msg: "O campo Email é obrigatório." }, + } + }, + hashed_password:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Senha é obrigatório." }, + } + }, + salt: { + type: Sequelize.STRING, + allowNull: false + }, + name:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Nome é obrigatório." }, + } + }, + nickname:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Apelido é obrigatório." }, + } + }, + cpf:{ + type: Sequelize.STRING, + allowNull: false, + unique: true, + validate: { + notNull: { msg: "O campo CPF é obrigatório." }, + } + }, + cep:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo CEP é obrigatório." }, + } + }, + schooling:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Formação é obrigatório." }, + } + }, + course:{ + type: Sequelize.STRING, + allowNull: false, + }, + complement:{ + type: Sequelize.STRING, + allowNull: false, + }, + address:{ + type: Sequelize.STRING, + allowNull: false, + }, + phone:{ + type: Sequelize.STRING, + allowNull: false, + }, + segment:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Segmento é obrigatório." }, + } + }, + role:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Função é obrigatório." }, + } + }, + institution_name:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Instituição em que trabalha ou estuda é obrigatório." }, + } + }, + state:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Estado é obrigatório." }, + } + }, + city:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Cidade é obrigatório." }, + } + }, + receive_email:{ + type: Sequelize.BOOLEAN, + }, + created_at:{ + type: Sequelize.DATE, + default: Date.now + }, + origin:{ + type: Sequelize.ENUM("LDE", "SimCAQ", "MAPFOR"), + allowNull:false, + validate: { + notNull: { msg: "O campo origem é obrigatória e aceita apenas os valores 'LDE', 'SimCAQ' e 'MAPFOR'."}, + } + }, + verified:{ + type: Sequelize.BOOLEAN, + default:false + }, + citesegment:{ + type: Sequelize.STRING + }, + citerole:{ + type: Sequelize.STRING + }, + admin:{ + type: Sequelize.BOOLEAN, + default:false + } + }, + {} + ); -UserSchema.methods.encryptPassword = function(password) { +User.methods.encryptPassword = function(password) { return crypto.pbkdf2Sync(password+'', this.salt, 10000, 512, 'sha512'); }; -UserSchema.virtual('password').set(function(password) { +User.virtual('password').set(function(password) { this._plainPassword = password+''; this.salt = crypto.randomBytes(128).toString('hex'); - this.hashedPassword = this.encryptPassword(password).toString('hex'); + this.hashed_password = this.encryptPassword(password).toString('hex'); }).get(function() { return this._plainPassword; }); UserSchema.methods.checkPassword = function(password) { - return this.encryptPassword(password).toString('hex') === this.hashedPassword; + return this.encryptPassword(password).toString('hex') === this.hashed_password; } -module.exports = mongoose.model('User', UserSchema); +return User; -- GitLab From 5d788385b7723bf5ac48607e93130b1e753a451e Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Tue, 11 Apr 2023 10:28:08 -0300 Subject: [PATCH 003/123] Postgres implementation --- package.json | 1 + src/libs/app.js | 2 +- src/libs/db/mongoose.js | 21 --- src/libs/db/postgres.js | 21 +++ src/libs/models/user.js | 276 ++++++++++++++++++++-------------------- 5 files changed, 161 insertions(+), 160 deletions(-) delete mode 100644 src/libs/db/mongoose.js create mode 100644 src/libs/db/postgres.js diff --git a/package.json b/package.json index 672cb1d7..54eb00db 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "passport": "^0.3.2", "passport-http-bearer": "^1.0.1", "passport-oauth2-client-password": "^0.1.2", + "pg": "^8.10.0", "request": "^2.88.0", "sequelize": "^6.31.0", "sequelize-cli": "^6.6.0", diff --git a/src/libs/app.js b/src/libs/app.js index 9f185105..9731038a 100644 --- a/src/libs/app.js +++ b/src/libs/app.js @@ -19,7 +19,7 @@ const api_v2 = require('./routes_v2/api'); const passport = require('passport'); -const mongoose = require(`${libs}/db/mongoose`); +const postgres = require(`${libs}/db/postgres`); const db = mongoose(); diff --git a/src/libs/db/mongoose.js b/src/libs/db/mongoose.js deleted file mode 100644 index f9d2ed8e..00000000 --- a/src/libs/db/mongoose.js +++ /dev/null @@ -1,21 +0,0 @@ -const libs = `${process.cwd()}/libs`; - -const config = require(`${libs}/config`); - -const log = require(`${libs}/log`)(module); - -const mongoose = require('mongoose'); - -mongoose.Promise = global.Promise; - -module.exports = () => { - // Get mongodb URI (ip and port) in config file - const mongoUri = process.env.MONGO_URI || config.mongodb.uri; - log.info(`Connecting to MongoDB on URI ${mongoUri}`); - // Connection singleton - const db = mongoose.connect(mongoUri); - - mongoose.connection.once('open', () => { log.info("MongoDB connected"); }); - - return db; -}; diff --git a/src/libs/db/postgres.js b/src/libs/db/postgres.js new file mode 100644 index 00000000..58c6d59e --- /dev/null +++ b/src/libs/db/postgres.js @@ -0,0 +1,21 @@ +const libs = `${process.cwd()}/libs`; + +const config = require(`${libs}/config`); + +const log = require(`${libs}/log`)(module); + +const { Pool} = require('pg'); + +module.exports = () => { + + const pool = new Pool({ + user: "postgres", + database: "postgres", + password: "postgres", + port: 5432, + host: "localhost", + + }); + + return pool; +}; diff --git a/src/libs/models/user.js b/src/libs/models/user.js index d7c992f0..4d40c4e2 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -5,145 +5,145 @@ const log = require(`${libs}/log`)(module); // set up a sequelize model var User = sequelize.define("User",{ - email: { - type: Sequelize.STRING, - allowNull: false, - unique: true, - validate: { - notNull: { msg: "O campo Email é obrigatório." }, - } - }, - hashed_password:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Senha é obrigatório." }, - } - }, - salt: { - type: Sequelize.STRING, - allowNull: false - }, - name:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Nome é obrigatório." }, - } - }, - nickname:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Apelido é obrigatório." }, - } - }, - cpf:{ - type: Sequelize.STRING, - allowNull: false, - unique: true, - validate: { - notNull: { msg: "O campo CPF é obrigatório." }, - } - }, - cep:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo CEP é obrigatório." }, - } - }, - schooling:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Formação é obrigatório." }, - } - }, - course:{ - type: Sequelize.STRING, - allowNull: false, - }, - complement:{ - type: Sequelize.STRING, - allowNull: false, - }, - address:{ - type: Sequelize.STRING, - allowNull: false, - }, - phone:{ - type: Sequelize.STRING, - allowNull: false, - }, - segment:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Segmento é obrigatório." }, - } - }, - role:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Função é obrigatório." }, - } - }, - institution_name:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Instituição em que trabalha ou estuda é obrigatório." }, - } - }, - state:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Estado é obrigatório." }, - } - }, - city:{ - type: Sequelize.STRING, - allowNull: false, - validate: { - notNull: { msg: "O campo Cidade é obrigatório." }, - } - }, - receive_email:{ - type: Sequelize.BOOLEAN, - }, - created_at:{ - type: Sequelize.DATE, - default: Date.now - }, - origin:{ - type: Sequelize.ENUM("LDE", "SimCAQ", "MAPFOR"), - allowNull:false, - validate: { - notNull: { msg: "O campo origem é obrigatória e aceita apenas os valores 'LDE', 'SimCAQ' e 'MAPFOR'."}, - } - }, - verified:{ - type: Sequelize.BOOLEAN, - default:false - }, - citesegment:{ - type: Sequelize.STRING - }, - citerole:{ - type: Sequelize.STRING - }, - admin:{ - type: Sequelize.BOOLEAN, - default:false + email: { + type: Sequelize.STRING, + allowNull: false, + unique: true, + validate: { + notNull: { msg: "O campo Email é obrigatório." }, } }, - {} - ); + hashed_password:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Senha é obrigatório." }, + } + }, + salt: { + type: Sequelize.STRING, + allowNull: false + }, + name:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Nome é obrigatório." }, + } + }, + nickname:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Apelido é obrigatório." }, + } + }, + cpf:{ + type: Sequelize.STRING, + allowNull: false, + unique: true, + validate: { + notNull: { msg: "O campo CPF é obrigatório." }, + } + }, + cep:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo CEP é obrigatório." }, + } + }, + schooling:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Formação é obrigatório." }, + } + }, + course:{ + type: Sequelize.STRING, + allowNull: false, + }, + complement:{ + type: Sequelize.STRING, + allowNull: false, + }, + address:{ + type: Sequelize.STRING, + allowNull: false, + }, + phone:{ + type: Sequelize.STRING, + allowNull: false, + }, + segment:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Segmento é obrigatório." }, + } + }, + role:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Função é obrigatório." }, + } + }, + institution_name:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Instituição em que trabalha ou estuda é obrigatório." }, + } + }, + state:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Estado é obrigatório." }, + } + }, + city:{ + type: Sequelize.STRING, + allowNull: false, + validate: { + notNull: { msg: "O campo Cidade é obrigatório." }, + } + }, + receive_email:{ + type: Sequelize.BOOLEAN, + }, + created_at:{ + type: Sequelize.DATE, + default: Date.now + }, + origin:{ + type: Sequelize.ENUM("LDE", "SimCAQ", "MAPFOR"), + allowNull:false, + validate: { + notNull: { msg: "O campo origem é obrigatória e aceita apenas os valores 'LDE', 'SimCAQ' e 'MAPFOR'."}, + } + }, + verified:{ + type: Sequelize.BOOLEAN, + default:false + }, + citesegment:{ + type: Sequelize.STRING + }, + citerole:{ + type: Sequelize.STRING + }, + admin:{ + type: Sequelize.BOOLEAN, + default:false + } +}, + {} +); -User.methods.encryptPassword = function(password) { +User.encryptPassword = function(password) { return crypto.pbkdf2Sync(password+'', this.salt, 10000, 512, 'sha512'); }; @@ -155,8 +155,8 @@ User.virtual('password').set(function(password) { return this._plainPassword; }); -UserSchema.methods.checkPassword = function(password) { +User.checkPassword = function(password) { return this.encryptPassword(password).toString('hex') === this.hashed_password; } -return User; +module.exports = User; -- GitLab From 6ab0f7ba930888b630edec3c1ea6ec3f59bc6036 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 13 Apr 2023 10:40:44 -0300 Subject: [PATCH 004/123] Make VerifyToken and adapta FindById to FindOne --- config.json.example | 157 --------------------------- script_req.sh | 10 ++ src/libs/app.js | 4 - src/libs/db/postgres.js | 23 +--- src/libs/middlewares/oauth2.js | 3 +- src/libs/middlewares/passport.js | 2 +- src/libs/models/user.js | 59 ++++++++-- src/libs/models/verificationToken.js | 39 +++---- src/libs/routes_v1/resetToken.js | 4 +- src/libs/routes_v1/user.js | 6 +- src/libs/routes_v1/verifyToken.js | 2 +- 11 files changed, 91 insertions(+), 218 deletions(-) delete mode 100644 config.json.example create mode 100755 script_req.sh diff --git a/config.json.example b/config.json.example deleted file mode 100644 index 1fa157c1..00000000 --- a/config.json.example +++ /dev/null @@ -1,157 +0,0 @@ -{ - "development": - { - "port": 3000, - "ip": "127.0.0.1", - "debug" : true, - "monetdb": { - "host": "simcaqdb3.c3sl.ufpr.br", - "port": 50000, - "dbname": "simcaq", - "user": "monetdb", - "password":"monetdb", - "nrConnections": "4" - }, - "cdn" : { - "url": "http://simcaqdb3.c3sl.ufpr.br:3000", - "download": "https://simcaqdev.c3sl.ufpr.br/download/" - }, - "mongodb" : { - "uri": "mongodb://localhost/dev_users" - }, - "monq": { - "uri": "mongodb://localhost/dev_monq" - }, - "default": { - "api": { - "version" : "v1" - }, - "lde": { - "url": "http://ldedev.c3sl.ufpr.br/#" - }, - "simcaq": { - "url": "http://simcaqdev.c3sl.ufpr.br/#" - } - }, - "email": { - "host": "SMTP.office365.com", - "port": 587, - "secureConnection": false, - "auth": { - "user": "dadoseducacionais@ufpr.br", - "pass": "COLOCAR_A_SENHA_AQUI" - }, - "tls": { - "ciphers": "SSLv3" - }, - "from": "\"Laboratório de Dados Educacionais\" <dadoseducacionais@ufpr.br>" - }, - "security": { - "tokenLife": 3600 - } - }, - "test": - { - "port": 3000, - "ip": "127.0.0.1", - "debug" : true, - "monetdb": { - "host": "simcaqdb3.c3sl.ufpr.br", - "port": 50000, - "dbname": "simcaq", - "user": "monetdb", - "password":"monetdb", - "nrConnections": "4" - }, - "cdn" : { - "url": "http://simcaqdb3.c3sl.ufpr.br:3000", - "download": "https://simcaqdev.c3sl.ufpr.br/download/" - }, - "mongodb" : { - "uri": "mongodb://localhost/test_users", - "secret": "SimCAQC3SL" - }, - "monq": { - "uri": "mongodb://localhost/test_monq" - }, - "default": { - "api": { - "version" : "v1" - }, - "lde": { - "url": "http://ldedev.c3sl.ufpr.br/#" - }, - "simcaq": { - "url": "http://simcaqdev.c3sl.ufpr.br/#" - } - }, - "email": { - "host": "SMTP.office365.com", - "port": 587, - "secureConnection": false, - "auth": { - "user": "dadoseducacionais@ufpr.br", - "pass": "COLOCAR_A_SENHA_AQUI" - }, - "tls": { - "ciphers": "SSLv3" - }, - "from": "\"Laboratório de Dados Educacionais\" <dadoseducacionais@ufpr.br>" - }, - "security": { - "tokenLife": 3600 - } - }, - "production": - { - "port": 3000, - "ip": "127.0.0.1", - "debug" : false, - "monetdb": { - "host": "simcaqdb3.c3sl.ufpr.br", - "port": 50000, - "dbname": "simcaq", - "user": "monetdb", - "password":"monetdb", - "nrConnections": "4" - }, - "cdn" : { - "url": "http://simcaqdb3.c3sl.ufpr.br:7000", - "download": "https://simcaq.c3sl.ufpr.br/download/" - }, - "mongodb" : { - "uri": "mongodb://localhost/users", - "secret": "SimCAQC3SL" - }, - "monq": { - "uri": "mongodb://localhost/monq" - }, - "default": { - "api": { - "version" : "v1" - }, - "lde": { - "url": "http://lde.c3sl.ufpr.br/#" - }, - "simcaq": { - "url": "http://simcaq.c3sl.ufpr.br/#" - } - }, - "email": { - "host": "SMTP.office365.com", - "port": 587, - "secureConnection": false, - "auth": { - "user": "dadoseducacionais@ufpr.br", - "pass": "COLOCAR_A_SENHA_AQUI" - }, - "tls": { - "ciphers": "SSLv3" - }, - "from": "\"Laboratório de Dados Educacionais\" <dadoseducacionais@ufpr.br>" - }, - "security": { - "tokenLife": 3600 - } - } -} diff --git a/script_req.sh b/script_req.sh new file mode 100755 index 00000000..125204b8 --- /dev/null +++ b/script_req.sh @@ -0,0 +1,10 @@ +curl -X 'POST' \ + 'http://10.254.221.20:3000/api/v1//auth/token' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "email": "eduardomsouza@ufpr.br", + "password": "teste123", + "client_secret": "LDE", + "grant_type": "password" +}' \ No newline at end of file diff --git a/src/libs/app.js b/src/libs/app.js index 9731038a..bab5e52d 100644 --- a/src/libs/app.js +++ b/src/libs/app.js @@ -19,10 +19,6 @@ const api_v2 = require('./routes_v2/api'); const passport = require('passport'); -const postgres = require(`${libs}/db/postgres`); - -const db = mongoose(); - require(`${libs}/middlewares/passport`); app.use(bodyParser.json({limit: '50mb'})); diff --git a/src/libs/db/postgres.js b/src/libs/db/postgres.js index 58c6d59e..c60d28c6 100644 --- a/src/libs/db/postgres.js +++ b/src/libs/db/postgres.js @@ -1,21 +1,8 @@ -const libs = `${process.cwd()}/libs`; +const Sequelize = require('sequelize'); -const config = require(`${libs}/config`); +// if you are using postgres, your DB URL will look like this +const DATABASE_URL = 'postgres://postgres:postgres@localhost:5432/postgres' -const log = require(`${libs}/log`)(module); +const db = new Sequelize(DATABASE_URL) -const { Pool} = require('pg'); - -module.exports = () => { - - const pool = new Pool({ - user: "postgres", - database: "postgres", - password: "postgres", - port: 5432, - host: "localhost", - - }); - - return pool; -}; +module.exports = db \ No newline at end of file diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index cc9a45ed..4cb6adcd 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -7,7 +7,6 @@ const libs = `${process.cwd()}/libs`; const config = require(`${libs}/config`); const log = require(`${libs}/log`)(module); -const db = require(`${libs}/db/mongoose`); const User = require(`${libs}/models/user`); const AccessToken = require(`${libs}/models/accessToken`); const RefreshToken = require(`${libs}/models/refreshToken`); @@ -88,7 +87,7 @@ aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, return done(null, false); } - User.findById(token.userId, (err, user) => { + User.findOne({token: token.userId} , (err, user) => { if (err) { log.error(err); return done(err); diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js index ab895a96..246a95ea 100644 --- a/src/libs/middlewares/passport.js +++ b/src/libs/middlewares/passport.js @@ -50,7 +50,7 @@ passport.use(new BearerStrategy( (accessToken, done) => { return done(null, false, { msg: 'Token expired' }); } - User.findById(token.userId, function(err, usuario) { + User.findOne({token: token.userId}, function(err, usuario) { if (err) { return done(err); } diff --git a/src/libs/models/user.js b/src/libs/models/user.js index 4d40c4e2..04fcb892 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -1,10 +1,16 @@ const Sequelize = require("sequelize"); const crypto = require('crypto') +const db = require('../db/postgres.js') const libs = `${process.cwd()}/libs`; const log = require(`${libs}/log`)(module); // set up a sequelize model -var User = sequelize.define("User",{ +var User = db.define("User",{ + id:{ + type: Sequelize.STRING, + allowNull:false, + unique: true + }, email: { type: Sequelize.STRING, allowNull: false, @@ -13,16 +19,28 @@ var User = sequelize.define("User",{ notNull: { msg: "O campo Email é obrigatório." }, } }, + password:{ + type: Sequelize.STRING, + get(){ + return () => this.getDataValue('password') + } + }, hashed_password:{ type: Sequelize.STRING, allowNull: false, validate: { notNull: { msg: "O campo Senha é obrigatório." }, + }, + get() { + return() => this.getDataValue('salt') } }, salt: { type: Sequelize.STRING, - allowNull: false + allowNull: false, + get() { + return() => this.getDataValue('salt') + } }, name:{ type: Sequelize.STRING, @@ -143,20 +161,39 @@ var User = sequelize.define("User",{ {} ); +User.generateSalt = function() { + return crypto.randomBytes(128).toString('hex'); +} + User.encryptPassword = function(password) { return crypto.pbkdf2Sync(password+'', this.salt, 10000, 512, 'sha512'); +} + +User.generateObjectId = function(){ + var timestamp = (new Date().getTime() / 1000 | 0).toString(16); + return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function() { + return (Math.random() * 16 | 0).toString(16); + }).toLowerCase(); +} + +const setSaltAndPassword = user => { + if (user.changed('password')) { + user.salt = User.generateSalt() + user.password = User.encryptPassword(user.password()) + this.hashed_password = this.encryptPassword(password).toString('hex'); + } +} + +const setObjectId = user => { + user.id = User.generateObjectId() }; -User.virtual('password').set(function(password) { - this._plainPassword = password+''; - this.salt = crypto.randomBytes(128).toString('hex'); - this.hashed_password = this.encryptPassword(password).toString('hex'); -}).get(function() { - return this._plainPassword; -}); +User.beforeCreate(setSaltAndPassword) +User.beforeCreate(setObjectId) +User.beforeUpdate(setSaltAndPassword) -User.checkPassword = function(password) { - return this.encryptPassword(password).toString('hex') === this.hashed_password; +User.prototype.checkPassword = function(enteredPassword) { + return User.encryptPassword(enteredPassword, this.salt()) === this.hashed_password() } module.exports = User; diff --git a/src/libs/models/verificationToken.js b/src/libs/models/verificationToken.js index ef7e109e..793ed56c 100644 --- a/src/libs/models/verificationToken.js +++ b/src/libs/models/verificationToken.js @@ -1,33 +1,32 @@ -const mongoose = require('mongoose'); -const Schema = mongoose.Schema; -const libs = `${process.cwd()}/libs`; +const Sequelize = require("sequelize"); +const crypto = require('crypto') +const db = require('../db/postgres.js') const log = require(`${libs}/log`)(module); const User = require(`${libs}/models/user`); const uuid = require('node-uuid'); -let VerificationToken = new Schema({ +var VerificationToken = db.define("VerificationToken",{ userId: { - type: Schema.Types.ObjectId, - required: true, - ref: 'User' + type: Sequelize.STRING, + allowNull: false }, - token: { - type: String, - required: true + token:{ + type: Sequelize.STRING, + allowNull: false }, - verified: { - type: Boolean, - required: true, + verified:{ + type: Sequelize.BOOLEAN, + allowNull: false, default: false }, - createdAt: { - type: Date, - required: true, + createdAt:{ + type: Sequelize.DATE, + allowNull: false, default: Date.now } -}); +}) -VerificationToken.methods.createVerificationToken = function(done) { +VerificationToken.createVerificationToken = function(done) { let verificationToken = this; let token = uuid.v4(); verificationToken.set('token', token); @@ -38,4 +37,6 @@ VerificationToken.methods.createVerificationToken = function(done) { }) } -module.exports = mongoose.model('VerificationToken', VerificationToken); +VerificationToken.belongsTo(User); + +module.exports = VerificationToken; diff --git a/src/libs/routes_v1/resetToken.js b/src/libs/routes_v1/resetToken.js index 34ece845..faa4caa6 100644 --- a/src/libs/routes_v1/resetToken.js +++ b/src/libs/routes_v1/resetToken.js @@ -32,7 +32,7 @@ resetTokenApp.get('/:token', (req, res, next) => { }) return next({msg: 'Token expired', status: 410}); } - User.findById(rToken.userId, (err, user) => { + User.findOne({token: rToken.userId}, (err, user) => { if(err) { log.error(err); next(err); @@ -55,7 +55,7 @@ resetTokenApp.post('/:token', (req, res, next) => { res.statusCode = 404; return next({msg: 'Token not found', status:404}); } - User.findById(rToken.userId, (err, user) => { + User.findOne({token: rToken.userId}, (err, user) => { if(err) { log.error(err); next(err); diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 7ff088ee..951717d7 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -100,7 +100,7 @@ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, re }, response('user')); userApp.get('/:id', (req, res, next) => { - User.findById(req.params.id, (err, user) => { + User.findOne({id: req.params.id}, (err, user) => { if(err) { log.error(err); return next(err); @@ -161,7 +161,7 @@ userApp.post('/', (req, res, next) => { // Create verification token let verificationToken = new VerificationToken({ - userId: user._id + userId: user.id }); verificationToken.createVerificationToken((err, token) => { @@ -195,7 +195,7 @@ userApp.post('/', (req, res, next) => { }); userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { - User.findById(req.params.id, (err, user) => { + User.findOne({id:req.params.id}, (err, user) => { if (err) { log.error(err); return next({err}); diff --git a/src/libs/routes_v1/verifyToken.js b/src/libs/routes_v1/verifyToken.js index d54f64aa..ecb834b3 100644 --- a/src/libs/routes_v1/verifyToken.js +++ b/src/libs/routes_v1/verifyToken.js @@ -22,7 +22,7 @@ verifyTokenApp.get('/:token', (req, res, next) => { res.statusCode = 404; return next({msg: 'Token not found', status:404}); } - User.findById(vToken.userId, (err, user) => { + User.findOne({token:vToken.userId}, (err, user) => { if(err) { log.error(err); next(err); -- GitLab From 9371dd1b4208be7b5ebfc74765abae9d2d90ef39 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 13 Apr 2023 11:55:08 -0300 Subject: [PATCH 005/123] Adjusting models sequelize --- src/libs/middlewares/oauth2.js | 2 +- src/libs/middlewares/passport.js | 2 +- src/libs/models/user.js | 6 +++--- src/libs/models/verificationToken.js | 6 ++---- src/libs/routes_v1/resetToken.js | 4 ++-- src/libs/routes_v1/user.js | 4 ++-- src/libs/routes_v1/verifyToken.js | 2 +- src/libs/routes_v2/resetToken.js | 4 ++-- src/libs/routes_v2/user.js | 4 ++-- src/libs/routes_v2/verifyToken.js | 2 +- 10 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 4cb6adcd..1021c58d 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -87,7 +87,7 @@ aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, return done(null, false); } - User.findOne({token: token.userId} , (err, user) => { + User.findByPk(token.userId , (err, user) => { if (err) { log.error(err); return done(err); diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js index 246a95ea..393e5c46 100644 --- a/src/libs/middlewares/passport.js +++ b/src/libs/middlewares/passport.js @@ -50,7 +50,7 @@ passport.use(new BearerStrategy( (accessToken, done) => { return done(null, false, { msg: 'Token expired' }); } - User.findOne({token: token.userId}, function(err, usuario) { + User.findByPk(token.userId, function(err, usuario) { if (err) { return done(err); } diff --git a/src/libs/models/user.js b/src/libs/models/user.js index 04fcb892..c659b6f2 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -2,14 +2,14 @@ const Sequelize = require("sequelize"); const crypto = require('crypto') const db = require('../db/postgres.js') const libs = `${process.cwd()}/libs`; -const log = require(`${libs}/log`)(module); // set up a sequelize model var User = db.define("User",{ id:{ type: Sequelize.STRING, allowNull:false, - unique: true + unique: true, + primaryKey: true }, email: { type: Sequelize.STRING, @@ -20,7 +20,7 @@ var User = db.define("User",{ } }, password:{ - type: Sequelize.STRING, + type: Sequelize.VIRTUAL, get(){ return () => this.getDataValue('password') } diff --git a/src/libs/models/verificationToken.js b/src/libs/models/verificationToken.js index 793ed56c..63b2b249 100644 --- a/src/libs/models/verificationToken.js +++ b/src/libs/models/verificationToken.js @@ -1,8 +1,6 @@ const Sequelize = require("sequelize"); -const crypto = require('crypto') const db = require('../db/postgres.js') -const log = require(`${libs}/log`)(module); -const User = require(`${libs}/models/user`); +const User = require(`./user.js`); const uuid = require('node-uuid'); var VerificationToken = db.define("VerificationToken",{ @@ -19,7 +17,7 @@ var VerificationToken = db.define("VerificationToken",{ allowNull: false, default: false }, - createdAt:{ + created_at:{ type: Sequelize.DATE, allowNull: false, default: Date.now diff --git a/src/libs/routes_v1/resetToken.js b/src/libs/routes_v1/resetToken.js index faa4caa6..3d67a1e2 100644 --- a/src/libs/routes_v1/resetToken.js +++ b/src/libs/routes_v1/resetToken.js @@ -32,7 +32,7 @@ resetTokenApp.get('/:token', (req, res, next) => { }) return next({msg: 'Token expired', status: 410}); } - User.findOne({token: rToken.userId}, (err, user) => { + User.findByPk(rToken.userId, (err, user) => { if(err) { log.error(err); next(err); @@ -55,7 +55,7 @@ resetTokenApp.post('/:token', (req, res, next) => { res.statusCode = 404; return next({msg: 'Token not found', status:404}); } - User.findOne({token: rToken.userId}, (err, user) => { + User.findByPk(rToken.userId, (err, user) => { if(err) { log.error(err); next(err); diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 951717d7..ee5793db 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -100,7 +100,7 @@ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, re }, response('user')); userApp.get('/:id', (req, res, next) => { - User.findOne({id: req.params.id}, (err, user) => { + User.findByPk(req.params.id, (err, user) => { if(err) { log.error(err); return next(err); @@ -195,7 +195,7 @@ userApp.post('/', (req, res, next) => { }); userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { - User.findOne({id:req.params.id}, (err, user) => { + User.findByPk(req.params.id, (err, user) => { if (err) { log.error(err); return next({err}); diff --git a/src/libs/routes_v1/verifyToken.js b/src/libs/routes_v1/verifyToken.js index ecb834b3..8cc9e35d 100644 --- a/src/libs/routes_v1/verifyToken.js +++ b/src/libs/routes_v1/verifyToken.js @@ -22,7 +22,7 @@ verifyTokenApp.get('/:token', (req, res, next) => { res.statusCode = 404; return next({msg: 'Token not found', status:404}); } - User.findOne({token:vToken.userId}, (err, user) => { + User.findByPk(vToken.userId, (err, user) => { if(err) { log.error(err); next(err); diff --git a/src/libs/routes_v2/resetToken.js b/src/libs/routes_v2/resetToken.js index 34ece845..3d67a1e2 100644 --- a/src/libs/routes_v2/resetToken.js +++ b/src/libs/routes_v2/resetToken.js @@ -32,7 +32,7 @@ resetTokenApp.get('/:token', (req, res, next) => { }) return next({msg: 'Token expired', status: 410}); } - User.findById(rToken.userId, (err, user) => { + User.findByPk(rToken.userId, (err, user) => { if(err) { log.error(err); next(err); @@ -55,7 +55,7 @@ resetTokenApp.post('/:token', (req, res, next) => { res.statusCode = 404; return next({msg: 'Token not found', status:404}); } - User.findById(rToken.userId, (err, user) => { + User.findByPk(rToken.userId, (err, user) => { if(err) { log.error(err); next(err); diff --git a/src/libs/routes_v2/user.js b/src/libs/routes_v2/user.js index 7ff088ee..a2ab63a5 100644 --- a/src/libs/routes_v2/user.js +++ b/src/libs/routes_v2/user.js @@ -100,7 +100,7 @@ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, re }, response('user')); userApp.get('/:id', (req, res, next) => { - User.findById(req.params.id, (err, user) => { + User.findOne({id:req.params.id}, (err, user) => { if(err) { log.error(err); return next(err); @@ -195,7 +195,7 @@ userApp.post('/', (req, res, next) => { }); userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { - User.findById(req.params.id, (err, user) => { + User.findOne({id:req.params.id}, (err, user) => { if (err) { log.error(err); return next({err}); diff --git a/src/libs/routes_v2/verifyToken.js b/src/libs/routes_v2/verifyToken.js index d54f64aa..8978cd4b 100644 --- a/src/libs/routes_v2/verifyToken.js +++ b/src/libs/routes_v2/verifyToken.js @@ -22,7 +22,7 @@ verifyTokenApp.get('/:token', (req, res, next) => { res.statusCode = 404; return next({msg: 'Token not found', status:404}); } - User.findById(vToken.userId, (err, user) => { + User.findOne({id:vToken.userId}, (err, user) => { if(err) { log.error(err); next(err); -- GitLab From fdceb2718fd88cd926f74a011f15581a795688c4 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Fri, 14 Apr 2023 09:52:30 -0300 Subject: [PATCH 006/123] Remove updateAt and createdAt --- src/libs/models/user.js | 4 ++-- src/libs/models/verificationToken.js | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libs/models/user.js b/src/libs/models/user.js index c659b6f2..1d01bcae 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -156,9 +156,9 @@ var User = db.define("User",{ admin:{ type: Sequelize.BOOLEAN, default:false - } + }, }, - {} + {timestamps: false} ); User.generateSalt = function() { diff --git a/src/libs/models/verificationToken.js b/src/libs/models/verificationToken.js index 63b2b249..f6c57a05 100644 --- a/src/libs/models/verificationToken.js +++ b/src/libs/models/verificationToken.js @@ -22,7 +22,8 @@ var VerificationToken = db.define("VerificationToken",{ allowNull: false, default: Date.now } -}) +}, +{timestamps: false}); VerificationToken.createVerificationToken = function(done) { let verificationToken = this; -- GitLab From d79515a410fd99c64ffb9a13384351f3c3ea9c9f Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Fri, 14 Apr 2023 11:18:23 -0300 Subject: [PATCH 007/123] FIX res.json --- src/libs/routes_v1/user.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index ee5793db..30691e14 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -113,9 +113,8 @@ userApp.get('/:id', (req, res, next) => { delete u.hashedPassword; delete u.salt; req.result = u; - next(); } - }); + }).then((result) => res.json(result)); }, response('user')); userApp.post('/', (req, res, next) => { -- GitLab From 0107b08d0f5555491aca41d50080b71ba3229514 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Fri, 14 Apr 2023 11:40:39 -0300 Subject: [PATCH 008/123] Fix get --- src/libs/routes_v1/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 30691e14..085b697d 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -115,7 +115,7 @@ userApp.get('/:id', (req, res, next) => { req.result = u; } }).then((result) => res.json(result)); -}, response('user')); +}); userApp.post('/', (req, res, next) => { let user = new User({ -- GitLab From e758ce8f3ff3bafd815f5021f94f8ca9a7d189ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 18 Apr 2023 10:04:09 -0300 Subject: [PATCH 009/123] Add enrollment projection route --- src/libs/routes_v2/api.js | 3 + .../routes_v2/simcaqEnrollmentProjection.js | 143 ++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 src/libs/routes_v2/simcaqEnrollmentProjection.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index f63dd586..25c829f9 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -154,6 +154,8 @@ const simcaqResult = require(`${libs}/routes_v2/simcaqResult`); const simcaqNumberOfTeachers = require(`${libs}/routes_v2/simcaqNumberOfTeachers`); +const simcaqEnrollmentProjection = require(`${libs}/routes_v2/simcaqEnrollmentProjection`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -222,5 +224,6 @@ api.use('/simcaq_number_of_employees', simcaqNumberOfEmployees); api.use('/simcaq_new_classes', simcaqNewClasses); api.use('/simcaq_result', simcaqResult); api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); +api.use('/simcaq_enrollment_projection', simcaqEnrollmentProjection); module.exports = api; diff --git a/src/libs/routes_v2/simcaqEnrollmentProjection.js b/src/libs/routes_v2/simcaqEnrollmentProjection.js new file mode 100644 index 00000000..cb472b4e --- /dev/null +++ b/src/libs/routes_v2/simcaqEnrollmentProjection.js @@ -0,0 +1,143 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqEnrollmentProjectionApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqEnrollmentProjectionApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_projecao_de_matricula', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_projecao_de_matricula' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_projecao_de_matricula' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_projecao_de_matricula' + } +}, 'dims').addValue({ + name: 'education_level_short_id', + table: 'simcaq_projecao_de_matricula', + tableField: 'etapa', + where: { + relation: '=', + type: 'integer', + field: 'etapa' + } +}).addValue({ + name: 'adm_dependency_public_id', + table: 'simcaq_projecao_de_matricula', + tableField: 'rede', + where: { + relation: '=', + type: 'integer', + field: 'rede' + } +}); + +simcaqEnrollmentProjectionApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_projecao_de_matricula') + .field('simcaq_projecao_de_matricula.ano_censo', 'year') + .field('simcaq_projecao_de_matricula.etapa', 'education_level_short_id') + .field('simcaq_projecao_de_matricula.rede', 'adm_dependency_public_id') + .field('SUM(simcaq_projecao_de_matricula.total_matriculas)', 'total_enrollments') + .field('SUM(simcaq_projecao_de_matricula.matriculas_diurno)', 'daytime_enrollments') + .field('SUM(simcaq_projecao_de_matricula.matriculas_noturno)', 'nighttime_enrollments') + .field('SUM(simcaq_projecao_de_matricula.total_tempo_integral)', 'fulltime_enrollments') + .group('simcaq_projecao_de_matricula.ano_censo') + .group('simcaq_projecao_de_matricula.etapa') + .group('simcaq_projecao_de_matricula.rede'); + next(); +}, query, id2str.transform(), response('enrollmentProjection')); + +module.exports = simcaqEnrollmentProjectionApp; -- GitLab From c28d191ff75b9598119c5c4e74c2c9a228ca455a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 24 Apr 2023 10:02:33 -0300 Subject: [PATCH 010/123] update v2 classroom route to use new aggregated table --- src/libs/routes_v2/classroom.js | 54 ++++++++++++++++----------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/libs/routes_v2/classroom.js b/src/libs/routes_v2/classroom.js index 8e2b6a7e..a3d6ec7f 100644 --- a/src/libs/routes_v2/classroom.js +++ b/src/libs/routes_v2/classroom.js @@ -50,22 +50,22 @@ let rqfCount = new ReqQueryFields(); // Complete range of the enrollments dataset. // Returns a tuple of start and ending years of the complete enrollments dataset. classroomApp.get('/year_range', (req, res, next) => { - req.sql.from('escola') - .field('MIN(escola.ano_censo)', 'start_year') - .field('MAX(escola.ano_censo)', 'end_year'); + req.sql.from('escola_agregada') + .field('MIN(escola_agregada.ano_censo)', 'start_year') + .field('MAX(escola_agregada.ano_censo)', 'end_year'); next(); }, query, response('range')); classroomApp.get('/years', (req, res, next) => { - req.sql.from('escola') - .field('DISTINCT escola.ano_censo', 'year'); + req.sql.from('escola_agregada') + .field('DISTINCT escola_agregada.ano_censo', 'year'); next(); }, query, response('years')); classroomApp.get('/source', (req, res, next) => { req.sql.from('fonte') .field('fonte', 'source') - .where('tabela = \'escola\''); + .where('tabela = \'escola_agregada\''); next(); }, query, response('source')); @@ -109,7 +109,7 @@ rqf.addField({ where: false }).addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: ['nome_escola', 'id'], resultField: ['school_name', 'school_id'], where: { @@ -119,7 +119,7 @@ rqf.addField({ } }, 'dims').addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: 'nome_escola', resultField: 'school_name', where: { @@ -136,12 +136,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'dims').addValueToField({ name: 'city', @@ -152,12 +152,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'filter').addValue({ name: 'state', @@ -168,12 +168,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'estado_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'region', @@ -188,11 +188,11 @@ rqf.addField({ join: { primary: 'id', foreign: 'regiao_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'min_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -202,7 +202,7 @@ rqf.addField({ } }).addValue({ name: 'max_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -212,7 +212,7 @@ rqf.addField({ } }).addValue({ name: 'adm_dependency', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_id', resultField: 'adm_dependency_id', where: { @@ -222,7 +222,7 @@ rqf.addField({ } }).addValue({ name: 'adm_dependency_detailed', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_priv', resultField: 'adm_dependency_detailed_id', where: { @@ -232,7 +232,7 @@ rqf.addField({ } }).addValue({ name: 'location', - table: 'escola', + table: 'escola_agregada', tableField: 'localizacao_id', resultField: 'location_id', where: { @@ -243,14 +243,14 @@ rqf.addField({ }); classroomApp.get('/', cache('15 day'), rqf.parse(), rqf.build(), (req, res, next) => { - req.sql.from('escola') - .field('SUM(escola.qtde_salas_utilizadas_dentro)', 'total') + req.sql.from('escola_agregada') + .field('SUM(escola_agregada.qtde_salas_utilizadas_dentro)', 'total') .field("'Brasil'", 'name') - .field('escola.ano_censo', 'year') - .group('escola.ano_censo') - .order('escola.ano_censo') - .where('escola.situacao_de_funcionamento = 1 AND escola.local_func_predio_escolar = 1') - .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1'); + .field('escola_agregada.ano_censo', 'year') + .group('escola_agregada.ano_censo') + .order('escola_agregada.ano_censo') + .where('escola_agregada.situacao_funcionamento_pareada = 1 AND escola_agregada.local_func_predio_escolar = 1') + .where('escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1'); next(); }, query, addMissing(rqf), id2str.transform(), (req, res, next) => { if (req.dims.location && req.result.length < 2) { // Garantimos que conterá as duas localizações no resultado para o simCAQ -- GitLab From 55c23553ab77668c746e443552c41e21f083f522 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 26 Apr 2023 10:47:56 -0300 Subject: [PATCH 011/123] FIX MongoDB to PostgresDB AccessToken, RefreshToken, Client --- src/libs/middlewares/oauth2.js | 11 +++++++-- src/libs/middlewares/passport.js | 20 ++++++++++----- src/libs/models/accessToken.js | 42 +++++++++++++++++--------------- src/libs/models/client.js | 32 +++++++++++++++--------- src/libs/models/refreshToken.js | 42 +++++++++++++++++--------------- src/libs/models/user.js | 4 +-- src/libs/routes_v1/api.js | 4 +++ src/libs/routes_v1/test.js | 33 +++++++++++++++++++++++++ src/libs/routes_v1/user.js | 5 ++-- 9 files changed, 129 insertions(+), 64 deletions(-) create mode 100644 src/libs/routes_v1/test.js diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 1021c58d..10d3278c 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -11,6 +11,7 @@ const User = require(`${libs}/models/user`); const AccessToken = require(`${libs}/models/accessToken`); const RefreshToken = require(`${libs}/models/refreshToken`); + // create OAuth 2.0 server let aserver = oauth2orize.createServer() @@ -57,7 +58,8 @@ let generateTokens = (data, done) => { // Exchange username & password for access token. aserver.exchange(oauth2orize.exchange.password((client, username, password, scope, done) => { - User.findOne({ email: username }, (err, user) => { + console.log("Exchange"); + User.findOne({where:{ email: username }}, (err, user) => { if (err) { return done(err); } @@ -78,6 +80,7 @@ aserver.exchange(oauth2orize.exchange.password((client, username, password, scop // Exchange refreshToken for access token. aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, done) =>{ + console.log("Refresha Token"); RefreshToken.findOne({ token: refreshToken, clientId: client._id }, (err, token) => { if (err) { return done(err); @@ -114,7 +117,11 @@ aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, // authenticate when making requests to this endpoint. exports.token = [ - passport.authenticate(['oauth2-client-password'], { session: false }), + // ()=>{console.log("C3sl")}, + passport.authenticate(['oauth2-client-password'], { session: false },function(err, user) { + if (err) { console.log("Erro de autenticação"); } + if (!user) { console.log("Erro de usuario ausente");} + }), aserver.token(), aserver.errorHandler() ]; diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js index 393e5c46..55e12e3c 100644 --- a/src/libs/middlewares/passport.js +++ b/src/libs/middlewares/passport.js @@ -8,41 +8,47 @@ const config = require(`${libs}/config`); const User = require(`${libs}/models/user`); const Client = require(`${libs}/models/client`); const AccessToken = require(`${libs}/models/accessToken`); -const RefreshToken = require(`${libs}/models/refreshToken`); -const email = require(`${libs}/middlewares/email`); + passport.use(new ClientPasswordStrategy( (clientId, clientSecret, done) => { - Client.findOne({ _id: clientId }, (err, client) => { + console.log("Entrei no ClientPasswordStrategy"); + Client.findOne(clientId, (err, client) => { if (err) { + console.log("Erro de requisicao"); return done(err); } if (!client) { + console.log("Erro de cliente"); return done(null, false); } if (client.clientSecret !== clientSecret) { + console.log("Erro de geracao Chave secreta"); return done(null, false); } - + console.log("Tudo certo nesse use"); return done(null, client); }) - } -)); + })); passport.use(new BearerStrategy( (accessToken, done) => { + console.log("Entrei no BearerStrategy"); AccessToken.findOne({ token: accessToken }, (err, token) => { if (err) { + console.log("ERRO AcessToken"); return done(err); } if (!token) { + console.log("ERRO Token"); return done(null, false); } if( Math.round((Date.now()-token.created)/1000) > config.security.tokenLife) { AccessToken.remove({ token: accessToken }, (err) => { if (err) { + console.log("ERRO remove Token") return done(err); } }); @@ -52,10 +58,12 @@ passport.use(new BearerStrategy( (accessToken, done) => { User.findByPk(token.userId, function(err, usuario) { if (err) { + console.log("ERRO PK"); return done(err); } if (!usuario) { + console.log("ERRO NAO USUARIO"); return done(null, false, { msg: 'Unknown user' }); } diff --git a/src/libs/models/accessToken.js b/src/libs/models/accessToken.js index daab5898..7eedfefa 100644 --- a/src/libs/models/accessToken.js +++ b/src/libs/models/accessToken.js @@ -1,29 +1,31 @@ -const mongoose = require('mongoose'); -const Schema = mongoose.Schema; +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js') const libs = `${process.cwd()}/libs`; const User = require(`${libs}/models/user`); const Client = require(`${libs}/models/client`); -let AccessToken = new Schema({ - userId: { - type: Schema.Types.ObjectId, - required: true, - ref: 'User' +var AccessToken = db.define("AccessToken",{ + user_id: { + type: Sequelize.STRING, + allowNull: false }, - clientId: { - type: Schema.Types.ObjectId, - required: true, - ref: 'Client' + client_id:{ + type: Sequelize.STRING, + allowNull: false }, - token: { - type: String, - unique: true, - required: true + token:{ + type: Sequelize.STRING, + allowNull: false, + unique: true }, - createdAt: { - type: Date, + created_at:{ + type: Sequelize.DATE, default: Date.now - } -}); + }}, + {timestamps: false} +); -module.exports = mongoose.model('AccessToken', AccessToken); +AccessToken.hasOne(User); +AccessToken.hasOne(Client); + +module.exports = AccessToken; diff --git a/src/libs/models/client.js b/src/libs/models/client.js index 8ac80d8d..10d7db87 100644 --- a/src/libs/models/client.js +++ b/src/libs/models/client.js @@ -1,17 +1,25 @@ -const mongoose = require('mongoose'); -const Schema = mongoose.Schema; +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); -let Client = new Schema({ - name: { - type: String, + +var Client = db.define("client",{ + id:{ + type: Sequelize.STRING, + allowNull:false, unique: true, - required: true + primaryKey: true }, - clientSecret: { - type: String, - required: true, + name:{ + type: Sequelize.STRING, + allowNull:false, unique: true - } -}); + }, + client_secret:{ + type: Sequelize.STRING, + allowNull:false, + unique:true + }, +}, +{timestamps: false}); -module.exports = mongoose.model('Client', Client); +module.exports = Client; \ No newline at end of file diff --git a/src/libs/models/refreshToken.js b/src/libs/models/refreshToken.js index c5f8fd63..0d59d8ad 100644 --- a/src/libs/models/refreshToken.js +++ b/src/libs/models/refreshToken.js @@ -1,30 +1,32 @@ -const mongoose = require('mongoose'); -const Schema = mongoose.Schema; +const Sequelize = require("sequelize"); const libs = `${process.cwd()}/libs`; +const db = require('../db/postgres.js'); const User = require(`${libs}/models/user`); const Client = require(`${libs}/models/client`); -let RefreshToken = new Schema({ - userId: { - type: Schema.Types.ObjectId, - required: true, - ref: 'User' +var RefreshToken = db.define("RefreshToken",{ + user_id: { + type: Sequelize.STRING, + allowNull: false }, - clientId: { - type: Schema.Types.ObjectId, - required: true, - ref: 'Client' + client_id:{ + type: Sequelize.STRING, + allowNull: false }, - token: { - type: String, - unique: true, - required: true + token:{ + type: Sequelize.STRING, + allowNull: false, + unique: true }, - createdAt: { - type: Date, + created_at:{ + type: Sequelize.DATE, default: Date.now - } -}); + }}, + {timestamps: false} +); -module.exports = mongoose.model('RefreshToken', RefreshToken); +RefreshToken.hasOne(User); +RefreshToken.hasOne(Client); + +module.exports = RefreshToken; diff --git a/src/libs/models/user.js b/src/libs/models/user.js index 1d01bcae..139f83ac 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -1,6 +1,6 @@ const Sequelize = require("sequelize"); -const crypto = require('crypto') -const db = require('../db/postgres.js') +const crypto = require('crypto'); +const db = require('../db/postgres.js'); const libs = `${process.cwd()}/libs`; // set up a sequelize model diff --git a/src/libs/routes_v1/api.js b/src/libs/routes_v1/api.js index 4b6a5630..41fe392c 100644 --- a/src/libs/routes_v1/api.js +++ b/src/libs/routes_v1/api.js @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. */ + const express = require('express'); const api = express(); @@ -26,6 +27,8 @@ const libs = `${process.cwd()}/libs`; const config = require(`${libs}/config`); +const test = require('./test'); + const classes = require('./class'); const enrollment = require('./enrollment'); @@ -139,6 +142,7 @@ api.get('/', (req, res) => { }); // mount API routes_v1 +api.use('/test', test); api.use('/user', user); api.use('/simulation', simulation); api.use('/class', classes); diff --git a/src/libs/routes_v1/test.js b/src/libs/routes_v1/test.js new file mode 100644 index 00000000..a2de966b --- /dev/null +++ b/src/libs/routes_v1/test.js @@ -0,0 +1,33 @@ +const express = require('express'); + +const testApp = express(); + +const libs = `${process.cwd()}/libs`; + +const Client = require(`${libs}/models/client`); + + +testApp.get("/client", (clientId, clientSecret, done) => { + console.log("Entrei no ClientPasswordStrategy"); + Client.findOne(clientId, (err, client) => { + if (err) { + console.log("Erro de requisicao"); + return done(err); + } + + if (!client) { + console.log("Erro de cliente"); + return done(null, false); + } + + if (client.clientSecret !== clientSecret) { + console.log("Erro de geracao Chave secreta"); + return done(null, false); + } + console.log("Tudo certo nesse use"); + return done(null, client); + }).then((result) => res.json(result)); +}) + + +module.exports = testApp; \ No newline at end of file diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 085b697d..3637e671 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -92,6 +92,7 @@ userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, n */ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => { + res.json(req.user); let user = req.user.toObject(); delete user.hashedPassword; delete user.salt; @@ -258,7 +259,7 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, r userApp.get('/reset/password', (req, res, next) => { let emailAddress = req.query.email; - User.findOne({email: emailAddress}, (err, user)=> { + User.findOne({where:{email: emailAddress}}, (err, user)=> { if(err) { log.error(err); let errors = []; @@ -298,7 +299,7 @@ userApp.get('/reset/password', (req, res, next) => { }); }) } - }) + }).then((result) => res.json(result)); }) module.exports = userApp; -- GitLab From d309942090123d909100ad4cc0999837cfd03aa3 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 27 Apr 2023 10:13:06 -0300 Subject: [PATCH 012/123] =?UTF-8?q?Momentos=20antes=20de=20toda=20mudan?= =?UTF-8?q?=C3=A7a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/middlewares/oauth2.js | 2 +- src/libs/models/resetToken.js | 44 +++++++++++++++++----------------- src/libs/models/user.js | 2 +- src/libs/routes_v1/test.js | 41 ++++++++++++++++--------------- 4 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 10d3278c..7babf1a8 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -81,7 +81,7 @@ aserver.exchange(oauth2orize.exchange.password((client, username, password, scop // Exchange refreshToken for access token. aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, done) =>{ console.log("Refresha Token"); - RefreshToken.findOne({ token: refreshToken, clientId: client._id }, (err, token) => { + RefreshToken.findOne({ token: refreshToken, client_id: client._id }, (err, token) => { if (err) { return done(err); } diff --git a/src/libs/models/resetToken.js b/src/libs/models/resetToken.js index 322d5281..540594b9 100644 --- a/src/libs/models/resetToken.js +++ b/src/libs/models/resetToken.js @@ -1,33 +1,32 @@ -const mongoose = require('mongoose'); -const Schema = mongoose.Schema; +const Sequelize = require("sequelize"); const libs = `${process.cwd()}/libs`; -const log = require(`${libs}/log`)(module); +const db = require('../db/postgres.js'); const User = require(`${libs}/models/user`); const uuid = require('node-uuid'); -let ResetToken = new Schema({ - userId: { - type: Schema.Types.ObjectId, - required: true, - ref: 'User' +var ResetToken = db.define("ResetToken",{ + user_id: { + type: Sequelize.STRING, + allowNull: false }, - token: { - type: String, - required: true + token:{ + type: Sequelize.STRING, + allowNull: false, + unique: true }, - reset: { - type: Boolean, - required: true, + reset:{ + type: Sequelize.BOOLEAN, + allowNull: false, default: false }, - createdAt: { - type: Date, - required: true, + created_at:{ + type: Sequelize.DATE, default: Date.now - } -}); + }}, + {timestamps: false} +); -ResetToken.methods.createResetToken = function (done) { +ResetToken.createResetToken = function (done) { let resetToken = this; let token = uuid.v4(); resetToken.set('token', token); @@ -38,9 +37,10 @@ ResetToken.methods.createResetToken = function (done) { return done(null, token); }) } -ResetToken.methods.hasExpired = function () { + +ResetToken.hasExpired = function () { var now = new Date(); return (now - this.createdAt) > 86400; //Expire if token is 1 day old }; -module.exports = mongoose.model('ResetToken', ResetToken); +module.exports = ResetToken diff --git a/src/libs/models/user.js b/src/libs/models/user.js index 139f83ac..a07cc68f 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -32,7 +32,7 @@ var User = db.define("User",{ notNull: { msg: "O campo Senha é obrigatório." }, }, get() { - return() => this.getDataValue('salt') + return() => this.getDataValue('hashed_password') } }, salt: { diff --git a/src/libs/routes_v1/test.js b/src/libs/routes_v1/test.js index a2de966b..2e529eaa 100644 --- a/src/libs/routes_v1/test.js +++ b/src/libs/routes_v1/test.js @@ -1,33 +1,32 @@ const express = require('express'); - +const oauth2orize = require('oauth2orize'); +const passport = require('passport'); +const ClientPasswordStrategy = require('passport-oauth2-client-password'); const testApp = express(); const libs = `${process.cwd()}/libs`; const Client = require(`${libs}/models/client`); +var server = oauth2orize.createServer(); + -testApp.get("/client", (clientId, clientSecret, done) => { - console.log("Entrei no ClientPasswordStrategy"); - Client.findOne(clientId, (err, client) => { - if (err) { - console.log("Erro de requisicao"); - return done(err); - } - - if (!client) { - console.log("Erro de cliente"); - return done(null, false); - } - - if (client.clientSecret !== clientSecret) { - console.log("Erro de geracao Chave secreta"); - return done(null, false); - } - console.log("Tudo certo nesse use"); +passport.use(new ClientPasswordStrategy( + function(clientId, clientSecret, done) { + console.log("ENTREI AQUI NO CLIENTPASSWORDSTRATEGY") + Clients.findOne({where:{client_id: clientId }}, function (err, client) { + if (err) { return done(err); } + if (!client) { return done(null, false); } + if (client.clientSecret != clientSecret) { return done(null, false); } return done(null, client); - }).then((result) => res.json(result)); -}) + }); + } + )); + + +testApp.get('/profile', + passport.authenticate(['oauth2-client-password'], { session: false }), + server.token()); module.exports = testApp; \ No newline at end of file -- GitLab From 8855ab6af8349a18448827309f6793bb7c78d4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 27 Apr 2023 11:02:11 -0300 Subject: [PATCH 013/123] Add simcaq aggregated enrollment --- src/libs/routes_v2/api.js | 3 + .../routes_v2/simcaqAggregatedEnrollment.js | 211 ++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 src/libs/routes_v2/simcaqAggregatedEnrollment.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 25c829f9..2072e864 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -156,6 +156,8 @@ const simcaqNumberOfTeachers = require(`${libs}/routes_v2/simcaqNumberOfTeachers const simcaqEnrollmentProjection = require(`${libs}/routes_v2/simcaqEnrollmentProjection`); +const simcaqAggregatedEnrollment = require(`${libs}/routes_v2/simcaqAggregatedEnrollment`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -225,5 +227,6 @@ api.use('/simcaq_new_classes', simcaqNewClasses); api.use('/simcaq_result', simcaqResult); api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); api.use('/simcaq_enrollment_projection', simcaqEnrollmentProjection); +api.use('/simcaq_aggregated_enrollment', simcaqAggregatedEnrollment); module.exports = api; diff --git a/src/libs/routes_v2/simcaqAggregatedEnrollment.js b/src/libs/routes_v2/simcaqAggregatedEnrollment.js new file mode 100644 index 00000000..7562acfa --- /dev/null +++ b/src/libs/routes_v2/simcaqAggregatedEnrollment.js @@ -0,0 +1,211 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqAggregatedEnrollmentApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqAggregatedEnrollmentApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_matricula_agregada', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_matricula_agregada' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_matricula_agregada' + } +}, 'dims').addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'simcaq_matricula_agregada' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_matricula_agregada' + } +}, 'dims').addValue({ + name: 'locale', + table: 'simcaq_matricula_agregada', + tableField: 'localizacao_id', + resultField: 'locale_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'adm_dependency_id', + table: 'simcaq_matricula_agregada', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed_id', + table: 'simcaq_matricula_agregada', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'diff_location_id', + table: 'simcaq_matricula_agregada', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).addValue({ + name: 'school_building', + table: 'simcaq_matricula_agregada', + tableField: 'local_func_predio_escolar', + where: { + relation: '=', + type: 'boolean', + field: 'local_func_predio_escolar' + } +}).addValue({ + name: 'rural_location_id', + table: 'simcaq_matricula_agregada', + tableField: 'localidade_area_rural', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'school_year_id', + table: 'simcaq_matricula_agregada', + tableField: 'serie_ano_id', + resultField: 'school_year_id', + where: { + relation: '=', + type: 'integer', + field: 'serie_ano_id' + } +}).addValue({ + name: 'education_level_short_id', + table: 'simcaq_matricula_agregada', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}); + +simcaqAggregatedEnrollmentApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_matricula_agregada') + .field('SUM(simcaq_matricula_agregada.num_matriculas)', 'num_enrollments') + .field('simcaq_matricula_agregada.ano_censo', 'year') + .group('simcaq_matricula_agregada.ano_censo'); + next(); +}, query, id2str.transform(), response('aggregatedEnrollment')); + +module.exports = simcaqAggregatedEnrollmentApp; -- GitLab From 6b93ae7e76a2327dc031273b3e29dc715dd8b068 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 28 Apr 2023 09:55:08 -0300 Subject: [PATCH 014/123] Add teacher city plan route --- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/simcaqTeacherCityPlan.js | 139 ++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/libs/routes_v2/simcaqTeacherCityPlan.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 2072e864..5c00d3fe 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -158,6 +158,8 @@ const simcaqEnrollmentProjection = require(`${libs}/routes_v2/simcaqEnrollmentPr const simcaqAggregatedEnrollment = require(`${libs}/routes_v2/simcaqAggregatedEnrollment`); +const simcaqTeacherCityPlan = require(`${libs}/routes_v2/simcaqTeacherCityPlan`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -228,5 +230,6 @@ api.use('/simcaq_result', simcaqResult); api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); api.use('/simcaq_enrollment_projection', simcaqEnrollmentProjection); api.use('/simcaq_aggregated_enrollment', simcaqAggregatedEnrollment); +api.use('/simcaq_teacher_city_plan', simcaqTeacherCityPlan); module.exports = api; diff --git a/src/libs/routes_v2/simcaqTeacherCityPlan.js b/src/libs/routes_v2/simcaqTeacherCityPlan.js new file mode 100644 index 00000000..72c19913 --- /dev/null +++ b/src/libs/routes_v2/simcaqTeacherCityPlan.js @@ -0,0 +1,139 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqTeacherCityPlanApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqTeacherCityPlanApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_docente_municipio_plano', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'simcaq_docente_municipio_plano' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_estado_id', + foreignTable: 'simcaq_docente_municipio_plano' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: ['nome', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_docente_municipio_plano' + } +}, 'dims').addValue({ + name: 'country', + table: 'simcaq_docente_municipio_plano', + tableField: ['escola_pais_nome', 'escola_pais_id'], + resultField: ['country_name', 'country_id'], + where: { + relation: '=', + type: 'integer', + field: 'escola_pais_id' + } +}).addValue({ + name: 'adm_dependency_id', + table: 'simcaq_docente_municipio_plano', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}); + +simcaqTeacherCityPlanApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_docente_municipio_plano') + .field('simcaq_docente_municipio_plano.num_docentes', 'num_teachers') + .field('simcaq_docente_municipio_plano.dependencia_adm_id', 'adm_dependency_id') + .field('simcaq_docente_municipio_plano.ano_censo', 'year'); + next(); +}, query, id2str.transform(), response('simcaqTeacherCityPlan')); + +module.exports = simcaqTeacherCityPlanApp; -- GitLab From d8e84866f6fb90dc23ef2316d0fc1a978f6176f9 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Tue, 2 May 2023 15:53:07 -0300 Subject: [PATCH 015/123] Passport not unauthorized anymore --- package.json | 1 + src/libs/middlewares/oauth2.js | 100 +++++++++++++------------------ src/libs/middlewares/passport.js | 54 +++++++---------- src/libs/models/accessToken.js | 4 +- src/libs/models/client.js | 1 - src/libs/models/refreshToken.js | 4 +- src/libs/routes_v1/test.js | 94 +++++++++++++++++++++++++---- 7 files changed, 146 insertions(+), 112 deletions(-) diff --git a/package.json b/package.json index 54eb00db..94ccf471 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "babel-core": "^6.26.3", "babel-preset-es2015": "^6.24.1", "babel-register": "^6.26.0", + "bcrypt": "^5.1.0", "bcrypt-nodejs": "0.0.3", "body-parser": "^1.18.3", "chai": "^3.5.0", diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 7babf1a8..37ac3509 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -23,88 +23,65 @@ let errFn = (cb, err) => { } // Destroys any old tokens and generates a new access and refresh token -let generateTokens = (data, done) => { +let generateTokens = (userId, clientId, done) => { // curries in `done` callback so we don't need to pass it - let errorHandler = errFn.bind(undefined, done); - let refreshToken; let refreshTokenValue; let token; let tokenValue; - RefreshToken.remove(data, errorHandler); - AccessToken.remove(data, errorHandler); + RefreshToken.destroy({where:{"user_id": userId, "client_id": clientId}}); + AccessToken.destroy({where:{"user_id": userId, "client_id": clientId}}); tokenValue = crypto.randomBytes(32).toString('hex'); refreshTokenValue = crypto.randomBytes(32).toString('hex'); - data.token = tokenValue; - token = new AccessToken(data); - - data.token = refreshTokenValue; - refreshToken = new RefreshToken(data); + AccessToken.create({ + user_id:userId, + client_id:clientId, + token:tokenValue + }) - refreshToken.save(errorHandler); + let refreshed_token = refreshTokenValue; - token.save((err) => { - if (err) { - log.error(err); - return done(err); - } - done(null, tokenValue, refreshTokenValue, { - 'expires_in': config.security.tokenLife - }); + RefreshToken.create({ + user_id:userId, + client_id:clientId, + token:refreshed_token }) }; -// Exchange username & password for access token. -aserver.exchange(oauth2orize.exchange.password((client, username, password, scope, done) => { - console.log("Exchange"); - User.findOne({where:{ email: username }}, (err, user) => { - if (err) { - return done(err); - } - - if (!user || !user.checkPassword(password)) { - return done(null, false); - } - var model = { - userId: user._id, - clientId: client._id - }; - log.info(`Gerando token para usuário ${user.name}`); - generateTokens(model, done); - }) +aserver.exchange(oauth2orize.exchange.password(function(client, username, password, scope, done) { + User.findOne({ + where: {email:username} + }).then(function(user) { + if(user == null){ + return done(null, false); + } + if(user.dataValues.origin != client.client_secret){ + console.log("Erro de client_secret"); + return done(null, false); + } + log.info(`Gerando token para usuário ${user.name}`); + generateTokens(user.dataValues.id, client.id, done); + }).catch(function(error) { + return done(error); + }); + })); -})); // Exchange refreshToken for access token. aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, done) =>{ console.log("Refresha Token"); - RefreshToken.findOne({ token: refreshToken, client_id: client._id }, (err, token) => { - if (err) { - return done(err); - } - + RefreshToken.findOne({where: {token: refreshToken, client_id: client.id }}).then(function(token){ if (!token) { return done(null, false); } - - User.findByPk(token.userId , (err, user) => { - if (err) { - log.error(err); - return done(err); - } + User.findByPk(token.user_id).then(function(user){ if (!user) { return done(null, false); } - - var model = { - userId: user._id, - clientId: client._id - }; - - generateTokens(model, done); + generateTokens(user.id, client.id, done); }) }) })) @@ -116,12 +93,15 @@ aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, // exchange middleware will be invoked to handle the request. Clients must // authenticate when making requests to this endpoint. + +// ,function(err, user) { +// if (err) { console.log("Erro de autenticação"); } +// if (!user) { console.log("Erro de usuario ausente");} +// } + exports.token = [ // ()=>{console.log("C3sl")}, - passport.authenticate(['oauth2-client-password'], { session: false },function(err, user) { - if (err) { console.log("Erro de autenticação"); } - if (!user) { console.log("Erro de usuario ausente");} - }), + passport.authenticate(['oauth2-client-password'], { session: false }), aserver.token(), aserver.errorHandler() ]; diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js index 55e12e3c..28e07e32 100644 --- a/src/libs/middlewares/passport.js +++ b/src/libs/middlewares/passport.js @@ -10,36 +10,28 @@ const Client = require(`${libs}/models/client`); const AccessToken = require(`${libs}/models/accessToken`); -passport.use(new ClientPasswordStrategy( (clientId, clientSecret, done) => { - console.log("Entrei no ClientPasswordStrategy"); - Client.findOne(clientId, (err, client) => { - if (err) { - console.log("Erro de requisicao"); - return done(err); - } - - if (!client) { - console.log("Erro de cliente"); - return done(null, false); - } - - if (client.clientSecret !== clientSecret) { - console.log("Erro de geracao Chave secreta"); - return done(null, false); - } - console.log("Tudo certo nesse use"); - return done(null, client); - }) - })); +passport.use(new ClientPasswordStrategy( + function(client_id, client_secret, done) { + Client.findOne({where: {id: client_id} + }).then(function(client) { + if(!client){ + console.log("Erro de cliente"); + return done(null, false); + } + if (client.client_secret !== client_secret){ + console.log("Erro de geracao Chave Secreta"); + return done(null, false); + } + return done(null, client); + }).catch(function(error) { + return done(error); + }); + } + )); passport.use(new BearerStrategy( (accessToken, done) => { console.log("Entrei no BearerStrategy"); - AccessToken.findOne({ token: accessToken }, (err, token) => { - if (err) { - console.log("ERRO AcessToken"); - return done(err); - } - + AccessToken.findOne({where:{token: accessToken}}, (token) => { if (!token) { console.log("ERRO Token"); return done(null, false); @@ -56,17 +48,11 @@ passport.use(new BearerStrategy( (accessToken, done) => { return done(null, false, { msg: 'Token expired' }); } - User.findByPk(token.userId, function(err, usuario) { - if (err) { - console.log("ERRO PK"); - return done(err); - } - + User.findByPk(token.userId, function(usuario) { if (!usuario) { console.log("ERRO NAO USUARIO"); return done(null, false, { msg: 'Unknown user' }); } - var info = { scope: '*' }; done(null, usuario, info); }) diff --git a/src/libs/models/accessToken.js b/src/libs/models/accessToken.js index 7eedfefa..68f6802a 100644 --- a/src/libs/models/accessToken.js +++ b/src/libs/models/accessToken.js @@ -25,7 +25,7 @@ var AccessToken = db.define("AccessToken",{ {timestamps: false} ); -AccessToken.hasOne(User); -AccessToken.hasOne(Client); +AccessToken.hasOne(User, { foreignKey: 'id' }); +AccessToken.hasOne(Client, { foreignKey: 'id' }); module.exports = AccessToken; diff --git a/src/libs/models/client.js b/src/libs/models/client.js index 10d7db87..b4eabcbc 100644 --- a/src/libs/models/client.js +++ b/src/libs/models/client.js @@ -1,7 +1,6 @@ const Sequelize = require("sequelize"); const db = require('../db/postgres.js'); - var Client = db.define("client",{ id:{ type: Sequelize.STRING, diff --git a/src/libs/models/refreshToken.js b/src/libs/models/refreshToken.js index 0d59d8ad..01b33ac8 100644 --- a/src/libs/models/refreshToken.js +++ b/src/libs/models/refreshToken.js @@ -25,8 +25,8 @@ var RefreshToken = db.define("RefreshToken",{ {timestamps: false} ); -RefreshToken.hasOne(User); -RefreshToken.hasOne(Client); +RefreshToken.hasOne(User, { foreignKey: 'id' }); +RefreshToken.hasOne(Client, { foreignKey: 'id' }); module.exports = RefreshToken; diff --git a/src/libs/routes_v1/test.js b/src/libs/routes_v1/test.js index 2e529eaa..9e8482dc 100644 --- a/src/libs/routes_v1/test.js +++ b/src/libs/routes_v1/test.js @@ -3,30 +3,98 @@ const oauth2orize = require('oauth2orize'); const passport = require('passport'); const ClientPasswordStrategy = require('passport-oauth2-client-password'); const testApp = express(); - const libs = `${process.cwd()}/libs`; const Client = require(`${libs}/models/client`); - +const User = require(`${libs}/models/user`) var server = oauth2orize.createServer(); - passport.use(new ClientPasswordStrategy( - function(clientId, clientSecret, done) { - console.log("ENTREI AQUI NO CLIENTPASSWORDSTRATEGY") - Clients.findOne({where:{client_id: clientId }}, function (err, client) { - if (err) { return done(err); } - if (!client) { return done(null, false); } - if (client.clientSecret != clientSecret) { return done(null, false); } + function(client_id, client_secret, done) { + Client.findOne({where: {client_id: client_id} + }).then(function(err, client) { + if(err){ + console.log("Erro de requisicao"); + return done(err); + } + if(!client){ + console.log("Erro de cliente"); + return done(null, false); + } + if (client.client_secret !== client_secret){ + console.log("Erro de geracao Chave Secreta"); + return done(null, false); + } + console.log("Tudo certo nesse use"); return done(null, client); - }); + }) } )); +let generateTokens = (userId, clientId, done) => { + // curries in `done` callback so we don't need to pass it + let refreshTokenValue; + let token; + let tokenValue; + + RefreshToken.destroy({where:{"user_id": userId, "client_id": clientId}}); + AccessToken.destroy({where:{"user_id": userId, "client_id": clientId}}); + + tokenValue = crypto.randomBytes(32).toString('hex'); + refreshTokenValue = crypto.randomBytes(32).toString('hex'); + + AccessToken.create({ + user_id:userId, + client_id:clientId, + token:tokenValue + }) + + let refreshed_token = refreshTokenValue; + + RefreshToken.create({ + user_id:userId, + client_id:clientId, + token:refreshed_token + }) + + token.save((err) => { + if (err) { + log.error(err); + return done(err); + } + done(null, tokenValue, refreshTokenValue, { + 'expires_in': config.security.tokenLife + }); + }) +}; + + +let entrar = function(client, username, done) { + User.findOne({ + where: {email:username} + }).then(function(user) { + console.log(user) + if(user == null){ + return done(null, false); + } + if(user.dataValues.origin != client.client_secret){ + console.log("Erro de client_secret"); + return done(null, false); + } + log.info(`Gerando token para usuário ${user.name}`); + generateTokens(user._id, client._id, done); + }).catch(function(error) { + return done(error); + }); + }; + + + + -testApp.get('/profile', - passport.authenticate(['oauth2-client-password'], { session: false }), - server.token()); +testApp.post('/', (req, res, next) =>{ + entrar(req.body, req.body.username); +}); module.exports = testApp; \ No newline at end of file -- GitLab From 87ea2747e4ffa85f797cd29d828f36da8f01f676 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 3 May 2023 09:35:19 -0300 Subject: [PATCH 016/123] Authentication ok! --- src/libs/middlewares/oauth2.js | 6 +++++- src/libs/models/accessToken.js | 3 ++- src/libs/models/refreshToken.js | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 37ac3509..775a759a 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -26,7 +26,6 @@ let errFn = (cb, err) => { let generateTokens = (userId, clientId, done) => { // curries in `done` callback so we don't need to pass it let refreshTokenValue; - let token; let tokenValue; RefreshToken.destroy({where:{"user_id": userId, "client_id": clientId}}); @@ -48,6 +47,11 @@ let generateTokens = (userId, clientId, done) => { client_id:clientId, token:refreshed_token }) + + done(null, tokenValue, refreshTokenValue, { + 'expires_in': config.security.tokenLife + }); + }; diff --git a/src/libs/models/accessToken.js b/src/libs/models/accessToken.js index 68f6802a..2970b6fa 100644 --- a/src/libs/models/accessToken.js +++ b/src/libs/models/accessToken.js @@ -16,7 +16,8 @@ var AccessToken = db.define("AccessToken",{ token:{ type: Sequelize.STRING, allowNull: false, - unique: true + unique: true, + primaryKey: true }, created_at:{ type: Sequelize.DATE, diff --git a/src/libs/models/refreshToken.js b/src/libs/models/refreshToken.js index 01b33ac8..ff73bd3e 100644 --- a/src/libs/models/refreshToken.js +++ b/src/libs/models/refreshToken.js @@ -16,7 +16,8 @@ var RefreshToken = db.define("RefreshToken",{ token:{ type: Sequelize.STRING, allowNull: false, - unique: true + unique: true, + primaryKey: true }, created_at:{ type: Sequelize.DATE, -- GitLab From cc40f21cd70435e641364a7e0b5a95e48c30b848 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 4 May 2023 11:37:05 -0300 Subject: [PATCH 017/123] [FIX] reset password path --- src/libs/middlewares/oauth2.js | 2 - src/libs/middlewares/passport.js | 6 +- src/libs/models/accessToken.js | 2 +- src/libs/models/refreshToken.js | 2 +- src/libs/models/resetToken.js | 19 +- src/libs/models/user.js | 6 +- src/libs/models/verificationToken.js | 22 +- src/libs/routes_v1/user.js | 309 ++++++++++++++------------- 8 files changed, 175 insertions(+), 193 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 775a759a..672c203e 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -76,7 +76,6 @@ aserver.exchange(oauth2orize.exchange.password(function(client, username, passwo // Exchange refreshToken for access token. aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, done) =>{ - console.log("Refresha Token"); RefreshToken.findOne({where: {token: refreshToken, client_id: client.id }}).then(function(token){ if (!token) { return done(null, false); @@ -104,7 +103,6 @@ aserver.exchange(oauth2orize.exchange.refreshToken((client, refreshToken, scope, // } exports.token = [ - // ()=>{console.log("C3sl")}, passport.authenticate(['oauth2-client-password'], { session: false }), aserver.token(), aserver.errorHandler() diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js index 28e07e32..93f5fe0a 100644 --- a/src/libs/middlewares/passport.js +++ b/src/libs/middlewares/passport.js @@ -31,14 +31,14 @@ passport.use(new ClientPasswordStrategy( passport.use(new BearerStrategy( (accessToken, done) => { console.log("Entrei no BearerStrategy"); - AccessToken.findOne({where:{token: accessToken}}, (token) => { + AccessToken.findOne({where:{token: accessToken}}).then((token) => { if (!token) { console.log("ERRO Token"); return done(null, false); } if( Math.round((Date.now()-token.created)/1000) > config.security.tokenLife) { - AccessToken.remove({ token: accessToken }, (err) => { + AccessToken.destroy({ token: accessToken }).then((err) => { if (err) { console.log("ERRO remove Token") return done(err); @@ -48,7 +48,7 @@ passport.use(new BearerStrategy( (accessToken, done) => { return done(null, false, { msg: 'Token expired' }); } - User.findByPk(token.userId, function(usuario) { + User.findByPk(token.user_id).then(function(usuario) { if (!usuario) { console.log("ERRO NAO USUARIO"); return done(null, false, { msg: 'Unknown user' }); diff --git a/src/libs/models/accessToken.js b/src/libs/models/accessToken.js index 2970b6fa..54e4a4ba 100644 --- a/src/libs/models/accessToken.js +++ b/src/libs/models/accessToken.js @@ -21,7 +21,7 @@ var AccessToken = db.define("AccessToken",{ }, created_at:{ type: Sequelize.DATE, - default: Date.now + defaultValue: Date.now }}, {timestamps: false} ); diff --git a/src/libs/models/refreshToken.js b/src/libs/models/refreshToken.js index ff73bd3e..aebdd9b2 100644 --- a/src/libs/models/refreshToken.js +++ b/src/libs/models/refreshToken.js @@ -21,7 +21,7 @@ var RefreshToken = db.define("RefreshToken",{ }, created_at:{ type: Sequelize.DATE, - default: Date.now + defaultValue: Date.now }}, {timestamps: false} ); diff --git a/src/libs/models/resetToken.js b/src/libs/models/resetToken.js index 540594b9..5398e9f4 100644 --- a/src/libs/models/resetToken.js +++ b/src/libs/models/resetToken.js @@ -12,32 +12,21 @@ var ResetToken = db.define("ResetToken",{ token:{ type: Sequelize.STRING, allowNull: false, - unique: true + unique: true, + primaryKey: true }, reset:{ type: Sequelize.BOOLEAN, allowNull: false, - default: false + defaultValue: false }, created_at:{ type: Sequelize.DATE, - default: Date.now + defaultValue: Date.now }}, {timestamps: false} ); -ResetToken.createResetToken = function (done) { - let resetToken = this; - let token = uuid.v4(); - resetToken.set('token', token); - resetToken.reset = false; - resetToken.save(function(err) { - if (err) - return done(err); - return done(null, token); - }) -} - ResetToken.hasExpired = function () { var now = new Date(); return (now - this.createdAt) > 86400; //Expire if token is 1 day old diff --git a/src/libs/models/user.js b/src/libs/models/user.js index a07cc68f..25fd8abb 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -134,7 +134,7 @@ var User = db.define("User",{ }, created_at:{ type: Sequelize.DATE, - default: Date.now + defaultValue: Date.now }, origin:{ type: Sequelize.ENUM("LDE", "SimCAQ", "MAPFOR"), @@ -145,7 +145,7 @@ var User = db.define("User",{ }, verified:{ type: Sequelize.BOOLEAN, - default:false + defaultValue:false }, citesegment:{ type: Sequelize.STRING @@ -155,7 +155,7 @@ var User = db.define("User",{ }, admin:{ type: Sequelize.BOOLEAN, - default:false + defaultValue:false }, }, {timestamps: false} diff --git a/src/libs/models/verificationToken.js b/src/libs/models/verificationToken.js index f6c57a05..9038cac1 100644 --- a/src/libs/models/verificationToken.js +++ b/src/libs/models/verificationToken.js @@ -4,38 +4,28 @@ const User = require(`./user.js`); const uuid = require('node-uuid'); var VerificationToken = db.define("VerificationToken",{ - userId: { + user_id: { type: Sequelize.STRING, allowNull: false }, token:{ type: Sequelize.STRING, - allowNull: false + allowNull: false, + primaryKey: true }, verified:{ type: Sequelize.BOOLEAN, allowNull: false, - default: false + defaultValue: false }, created_at:{ type: Sequelize.DATE, allowNull: false, - default: Date.now + defaultValue: Date.now } }, {timestamps: false}); -VerificationToken.createVerificationToken = function(done) { - let verificationToken = this; - let token = uuid.v4(); - verificationToken.set('token', token); - verificationToken.verified = false; - verificationToken.save(function(err) { - if (err) return done(err); - return done(null, token); - }) -} - -VerificationToken.belongsTo(User); +VerificationToken.hasOne(User,{ foreignKey: 'id' }); module.exports = VerificationToken; diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 3637e671..ebe3191a 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -20,6 +20,8 @@ const email = require(`${libs}/middlewares/email`); const passport = require('passport'); +const uuid = require('node-uuid'); + function emailSyntax(email) { const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; return regex.test(email); @@ -56,16 +58,16 @@ userApp.get('/segment', (req, res, next) => { userApp.get('/role', (req, res, next) => { req.result = [ - {"Gestores e equipe gestora das secretarias e ministério da Educação" : ["Dirigente municipal, estadual e federal", "Secretário do MEC", "Servidor da área de planejamento educacional", "Membro de associação de gestores (Ex. Undime, Consed, etc)", "Outro [citar função]"]}, - {"Gestores dos órgãos de planejamento e finanças (das três esferas de governo)" : ["Equipe gestora dos órgãos de planejamento", "Equipe gestora dos órgãos de finanças", "Outro [citar função]"]}, - {"Agentes do poder legislativo" : ["Parlamentar", "Assessor/a parlamentar", "Auditor/a dos tribunais de conta", "Conselheiro/a de tribunais de conta.", "Outro [citar função]"]}, - {"Agentes dos conselhos de educação" : ["Conselheiro/a municipais, estaduais e federais", "Conselheiro/a do Fundeb", "Outro [citar função]"]}, - {"Profissionais da educação" : ["Professor/a da Educação Básica", "Profissional da educação não-docente", "Outro [citar função]"]}, - {"Sindicato" : ["Agente de sindicatos"]}, - {"Sociedade civil interessada no financiamento da Educação Básica de qualidade" : ["Membro de fóruns educacionais", "Membro de ONGs e demais entidades sem fins lucrativos", "Estudante da educação básica e membro de entidades estudantis", "Pais e membros de entidades de pais", "Outro [citar função]"]}, - {"Comunidade acadêmica" : ["Pesquisador/a", "Estudantes de graduação e pós-graduação", "Representantes de entidades de pesquisa (Ex.: ANPED, ANPAE e FINEDUCA)", "Outro [citar função]"]}, - {"Imprensa" : ["Jornalista", "Outro [citar função]"]}, - {"Outro [citar segmento]" : []} + { "Gestores e equipe gestora das secretarias e ministério da Educação": ["Dirigente municipal, estadual e federal", "Secretário do MEC", "Servidor da área de planejamento educacional", "Membro de associação de gestores (Ex. Undime, Consed, etc)", "Outro [citar função]"] }, + { "Gestores dos órgãos de planejamento e finanças (das três esferas de governo)": ["Equipe gestora dos órgãos de planejamento", "Equipe gestora dos órgãos de finanças", "Outro [citar função]"] }, + { "Agentes do poder legislativo": ["Parlamentar", "Assessor/a parlamentar", "Auditor/a dos tribunais de conta", "Conselheiro/a de tribunais de conta.", "Outro [citar função]"] }, + { "Agentes dos conselhos de educação": ["Conselheiro/a municipais, estaduais e federais", "Conselheiro/a do Fundeb", "Outro [citar função]"] }, + { "Profissionais da educação": ["Professor/a da Educação Básica", "Profissional da educação não-docente", "Outro [citar função]"] }, + { "Sindicato": ["Agente de sindicatos"] }, + { "Sociedade civil interessada no financiamento da Educação Básica de qualidade": ["Membro de fóruns educacionais", "Membro de ONGs e demais entidades sem fins lucrativos", "Estudante da educação básica e membro de entidades estudantis", "Pais e membros de entidades de pais", "Outro [citar função]"] }, + { "Comunidade acadêmica": ["Pesquisador/a", "Estudantes de graduação e pós-graduação", "Representantes de entidades de pesquisa (Ex.: ANPED, ANPAE e FINEDUCA)", "Outro [citar função]"] }, + { "Imprensa": ["Jornalista", "Outro [citar função]"] }, + { "Outro [citar segmento]": [] } ] next(); }, response('role')); @@ -101,111 +103,101 @@ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, re }, response('user')); userApp.get('/:id', (req, res, next) => { - User.findByPk(req.params.id, (err, user) => { - if(err) { - log.error(err); - return next(err); - } - if(!user) { - req.statusCode = 404; - next({msg: 'User not found'}); + User.findByPk(req.params.id).then((user) => { + if (!user) { + res.statusCode = 404; + res.json({ msg: "O usuário não está cadastrado" }); } else { let u = user.toObject; delete u.hashedPassword; delete u.salt; req.result = u; } - }).then((result) => res.json(result)); -}); - -userApp.post('/', (req, res, next) => { - let user = new User({ - email: req.body.email, - password: req.body.password, - name: req.body.name, - nickname: req.body.nickname, - cpf: req.body.cpf, - cep: req.body.cep, - complement: req.body.complement, - address: req.body.address, - phone: req.body.phone, - schooling: req.body.schooling, - course: req.body.course, - segment: req.body.segment, - role: req.body.role, - institutionName: req.body.institutionName, - state: req.body.state, - city: req.body.city, - receiveEmails: false || req.body.receiveEmails, - origin: req.body.origin, - citesegment: req.body.citesegment, - citerole: req.body.citerole, - admin: false + }).catch(function (err) { + log.error(err); + return next(err); }); +}); +userApp.post('/', async (req, res, next) => { if (typeof req.body.password === 'undefined' || !req.body.password) { res.statusCode = 400; - return res.json({errors: ["O campo senha é obrigatório"]}); + return res.json({ errors: ["O campo senha é obrigatório"] }); } else { - user.save((err) => { - if(err) { + let user = await User.create({ + email: req.body.email, + password: req.body.password, + name: req.body.name, + nickname: req.body.nickname, + cpf: req.body.cpf, + cep: req.body.cep, + complement: req.body.complement, + address: req.body.address, + phone: req.body.phone, + schooling: req.body.schooling, + course: req.body.course, + segment: req.body.segment, + role: req.body.role, + institutionName: req.body.institutionName, + state: req.body.state, + city: req.body.city, + receiveEmails: false || req.body.receiveEmails, + origin: req.body.origin, + citesegment: req.body.citesegment, + citerole: req.body.citerole, + admin: false + }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); + res.statusCode = 400; + return res.json({ err, errors }); + // handle error; + }); + let tokenValue = uuid.v4(); + const verificationToken = VerificationToken.create({ + user_id: user.id, + token: tokenValue, + verified: false + }); + if (!verificationToken) { + res.statusCode = 404; + return res.json({ msg: "Couldn't create Verification Token" }); + } + let url = config.default.lde.url + '/verify'; + let text = `Olá, ${user.name}, seja bem vindo/a ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${tokenValue}`; + // Send confirmation email + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Confirme seu cadastro - Laboratório de Dados Educacionais", + text + } + email(mailOptions, (err, info) => { + if (err) { log.error(err); - let errors = []; - for(let errName in err.errors) { - errors.push(err.errors[errName].message); - } - log.error(errors); - res.statusCode = 400; - return res.json({err, errors}); + res.json({ msg: 'Message not delivered, user created but not confirmed' }); } - - // Create verification token - let verificationToken = new VerificationToken({ - userId: user.id - }); - - verificationToken.createVerificationToken((err, token) => { - if(err) { - log.error(err); - return next(err); - } - let url = config.default.lde.url + '/verify'; - let text = `Olá, ${user.name}, seja bem vindo/a ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${token}`; - // Send confirmation email - let mailOptions = { - to: `"${user.name} <${user.email}>"`, - subject: "Confirme seu cadastro - Laboratório de Dados Educacionais", - text - } - email(mailOptions, (err, info) => { - if(err) { - log.error(err); - res.json({msg: 'User created'}); - } - if(info) { - log.info(`Message ${info.messageId} sent: ${info.response}`); - log.info(`Usuário ${user.email} foi criado`); - } - res.json({msg: 'User created'}); - }); - }); + if (info) { + log.info(`Message ${info.messageId} sent: ${info.response}`); + log.info(`Usuário ${user.email} foi criado`); + } + res.json({ msg: 'User created' }); }); } - }); userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { - User.findByPk(req.params.id, (err, user) => { - if (err) { - log.error(err); - return next({err}); - } - - if(!user) { + User.findByPk(req.params.id).then((user) => { + if (!user) { res.statusCode = 404; - return next({err: { - message: 'Usuário não encontrado' - }}); + return next({ + err: { + message: 'Usuário não encontrado' + } + }); } user.email = req.body.email || user.email; @@ -227,79 +219,92 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, r user.citerole = req.body.citerole || user.citerole; if ((req.body.password) && (req.body.newpassword)) { - if (req.body.password != req.body.newpassword) { - if (user.checkPassword(req.body.password)) { - user.password = req.body.newpassword; - } else { - res.statusCode = 500; - return res.json({error: { - message: 'A senha atual está incorreta' - }}); - } + if (req.body.password != req.body.newpassword) { + if (user.checkPassword(req.body.password)) { + user.password = req.body.newpassword; } else { - res.statusCode = 500; - return res.json({error: { - message: 'A nova senha é a mesma da senha atual' - }}); + res.statusCode = 500; + return res.json({ + error: { + message: 'A senha atual está incorreta' + } + }); } + } else { + res.statusCode = 500; + return res.json({ + error: { + message: 'A nova senha é a mesma da senha atual' + } + }); + } } - user.save(err => { - if(err) { + user.save().catch(err => { + if (err) { log.error(err); - return next({message: 'Erro ao atualizar usuário'}); + return next({ message: 'Erro ao atualizar usuário' }); } let u = user.toObject(); delete u.hashedPassword; delete u.salt; - res.json({user: u}); + res.json({ user: u }); }) + }).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } }) }); -userApp.get('/reset/password', (req, res, next) => { + +userApp.get('/reset/password', async (req, res, next) => { let emailAddress = req.query.email; - User.findOne({where:{email: emailAddress}}, (err, user)=> { - if(err) { - log.error(err); - let errors = []; - for(let errName in err.errors) { - errors.push(err.errors[errName].message); - } - res.statusCode = 400; - return res.json({err, errors}); + let user = await User.findOne({ where: { email: emailAddress } }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); } - if (!user) { + log.error(errors); + res.statusCode = 400; + return res.json({ err, errors }); + // handle error; + }); + if (!user) { + res.statusCode = 404; + res.json({ msg: "O usuário não está cadastrado" }); + } + else { + let tokenValue = uuid.v4(); + const rt = await ResetToken.create({ + user_id: user.id, + token: tokenValue, + reset: false + }); + if (!rt) { res.statusCode = 404; - res.json({msg: "O usuário não está cadastrado"}); + return res.json({ msg: "Couldn't create Reset Password Token" }); } - else { - let resetToken = new ResetToken({ - userId: user._id - }); - resetToken.createResetToken((err, token) => { - if (err) { - log.error(err); - return next(err); - } - let url = config.default.lde.url + '/reset-password'; - let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${token}`; - let mailOptions = { - to: `"${user.name} <${user.email}>"`, - subject: "Redefinição de Senha - Laboratório de Dados Educacionais", - text - } - email(mailOptions, (err, info) => { - if(err) { - log.error(err); - res.json({msg: 'Undelivered Reset Password Mail'}); - } - log.info(`Message ${info.messageId} sent: ${info.response}`); - res.json({msg: 'Reset Password Mail Successfully Delivered'}); - }); - }) + let url = config.default.lde.url + '/reset-password'; + let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${tokenValue}`; + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Redefinição de Senha - Laboratório de Dados Educacionais", + text } - }).then((result) => res.json(result)); -}) + console.log(mailOptions); + email(mailOptions, (err, info) => { + if (err) { + console.log(err); + log.error(err); + res.json({ msg: 'Undelivered Reset Password Mail' }); + } + log.info(`Message ${info.messageId} sent: ${info.response}`); + res.json({ msg: 'Reset Password Mail Successfully Delivered' }); + }); + } +}); module.exports = userApp; -- GitLab From dff177b1fdb057528e1cfcabb30472e658531cb9 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 10 May 2023 11:41:53 -0300 Subject: [PATCH 018/123] [FIX] User put /:id --- src/libs/middlewares/passport.js | 79 +++++++++---------- src/libs/models/user.js | 22 ++---- src/libs/routes_v1/user.js | 125 +++++++++++++++--------------- src/libs/routes_v1/verifyToken.js | 54 ++++++------- 4 files changed, 135 insertions(+), 145 deletions(-) diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js index 93f5fe0a..82f21de5 100644 --- a/src/libs/middlewares/passport.js +++ b/src/libs/middlewares/passport.js @@ -11,51 +11,48 @@ const AccessToken = require(`${libs}/models/accessToken`); passport.use(new ClientPasswordStrategy( - function(client_id, client_secret, done) { - Client.findOne({where: {id: client_id} - }).then(function(client) { - if(!client){ - console.log("Erro de cliente"); - return done(null, false); - } - if (client.client_secret !== client_secret){ - console.log("Erro de geracao Chave Secreta"); - return done(null, false); - } - return done(null, client); - }).catch(function(error) { - return done(error); - }); - } - )); - -passport.use(new BearerStrategy( (accessToken, done) => { - console.log("Entrei no BearerStrategy"); - AccessToken.findOne({where:{token: accessToken}}).then((token) => { - if (!token) { - console.log("ERRO Token"); + function (client_id, client_secret, done) { + Client.findOne({ + where: { id: client_id } + }).then(function (client) { + if (!client) { + console.log("Erro de cliente"); + return done(null, false); + } + if (client.client_secret !== client_secret) { + console.log("Erro de geracao Chave Secreta"); return done(null, false); } + return done(null, client); + }).catch(function (error) { + return done(error); + }); + } +)); - if( Math.round((Date.now()-token.created)/1000) > config.security.tokenLife) { - AccessToken.destroy({ token: accessToken }).then((err) => { - if (err) { - console.log("ERRO remove Token") - return done(err); - } - }); +passport.use(new BearerStrategy(async (accessToken, done) => { + const token = await AccessToken.findOne({ where: { token: accessToken } }) + if (!token) { + console.log("ERRO Token"); + return done(null, false); + } - return done(null, false, { msg: 'Token expired' }); + if (Math.round((Date.now() - token.created) / 1000) > config.security.tokenLife) { + AccessToken.destroy({ token: accessToken }).then((err) => { + if (err) { + console.log("ERRO remove Token") + return done(err); } + }); - User.findByPk(token.user_id).then(function(usuario) { - if (!usuario) { - console.log("ERRO NAO USUARIO"); - return done(null, false, { msg: 'Unknown user' }); - } - var info = { scope: '*' }; - done(null, usuario, info); - }) - }) + return done(null, false, { msg: 'Token expired' }); } -)); + User.findByPk(token.user_id).then(function (usuario) { + if (!usuario) { + console.log("ERRO NAO USUARIO"); + return done(null, false, { msg: 'Unknown user' }); + } + var info = { scope: '*' }; + done(null, usuario, info); + }) +})); diff --git a/src/libs/models/user.js b/src/libs/models/user.js index 25fd8abb..5da038dd 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -20,27 +20,18 @@ var User = db.define("User",{ } }, password:{ - type: Sequelize.VIRTUAL, - get(){ - return () => this.getDataValue('password') - } + type: Sequelize.VIRTUAL }, hashed_password:{ type: Sequelize.STRING, allowNull: false, validate: { notNull: { msg: "O campo Senha é obrigatório." }, - }, - get() { - return() => this.getDataValue('hashed_password') } }, salt: { type: Sequelize.STRING, allowNull: false, - get() { - return() => this.getDataValue('salt') - } }, name:{ type: Sequelize.STRING, @@ -165,8 +156,8 @@ User.generateSalt = function() { return crypto.randomBytes(128).toString('hex'); } -User.encryptPassword = function(password) { - return crypto.pbkdf2Sync(password+'', this.salt, 10000, 512, 'sha512'); +User.encryptPassword = function(password, salt) { + return crypto.pbkdf2Sync(password+'', salt, 10000, 512, 'sha512').toString('hex'); } User.generateObjectId = function(){ @@ -179,8 +170,7 @@ User.generateObjectId = function(){ const setSaltAndPassword = user => { if (user.changed('password')) { user.salt = User.generateSalt() - user.password = User.encryptPassword(user.password()) - this.hashed_password = this.encryptPassword(password).toString('hex'); + user.hashed_password = User.encryptPassword(user.password, user.salt).toString('hex'); } } @@ -192,8 +182,8 @@ User.beforeCreate(setSaltAndPassword) User.beforeCreate(setObjectId) User.beforeUpdate(setSaltAndPassword) -User.prototype.checkPassword = function(enteredPassword) { - return User.encryptPassword(enteredPassword, this.salt()) === this.hashed_password() +User.prototype.checkPassword = function(user, enteredPassword) { + return User.encryptPassword(enteredPassword, user.salt) === user.hashed_password } module.exports = User; diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index ebe3191a..d53d2748 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -94,11 +94,10 @@ userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, n */ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => { - res.json(req.user); - let user = req.user.toObject(); - delete user.hashedPassword; - delete user.salt; - req.result = user; + let u = req.user; + delete u.hashedPassword; + delete u.salt; + req.result = u; next(); }, response('user')); @@ -108,16 +107,17 @@ userApp.get('/:id', (req, res, next) => { res.statusCode = 404; res.json({ msg: "O usuário não está cadastrado" }); } else { - let u = user.toObject; + let u = user; delete u.hashedPassword; delete u.salt; req.result = u; + next(); } }).catch(function (err) { log.error(err); return next(err); }); -}); +}, response('user')); userApp.post('/', async (req, res, next) => { if (typeof req.body.password === 'undefined' || !req.body.password) { @@ -189,73 +189,76 @@ userApp.post('/', async (req, res, next) => { } }); -userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { - User.findByPk(req.params.id).then((user) => { - if (!user) { - res.statusCode = 404; - return next({ - err: { - message: 'Usuário não encontrado' - } - }); +userApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + let user = await User.findByPk(req.params.id).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); } + }) + if (!user) { + res.statusCode = 404; + return next({ + err: { + message: 'Usuário não encontrado' + } + }); + } - user.email = req.body.email || user.email; - user.name = req.body.name || user.name; - user.nickname = req.body.nickname || user.nickname || user.name; - user.cep = req.body.cep || user.cep; - user.complement = req.body.complement || user.complement; - user.address = req.body.address || user.address; - user.phone = req.body.phone || user.phone; - user.schooling = req.body.schooling || user.schooling; - user.course = req.body.course || user.course; - user.segment = req.body.segment || user.segment; - user.role = req.body.role || user.role; - user.institutionName = req.body.institutionName || user.institutionName; - user.state = req.body.state || user.state; - user.city = req.body.city || user.city; - user.receiveEmails = req.body.receiveEmails || user.receiveEmails; - user.citesegment = req.body.citesegment || user.citesegment; - user.citerole = req.body.citerole || user.citerole; + user.email = req.body.email || user.email; + user.name = req.body.name || user.name; + user.nickname = req.body.nickname || user.nickname || user.name; + user.cep = req.body.cep || user.cep; + user.complement = req.body.complement || user.complement; + user.address = req.body.address || user.address; + user.phone = req.body.phone || user.phone; + user.schooling = req.body.schooling || user.schooling; + user.course = req.body.course || user.course; + user.segment = req.body.segment || user.segment; + user.role = req.body.role || user.role; + user.institutionName = req.body.institutionName || user.institutionName; + user.state = req.body.state || user.state; + user.city = req.body.city || user.city; + user.receiveEmails = req.body.receiveEmails || user.receiveEmails; + user.citesegment = req.body.citesegment || user.citesegment; + user.citerole = req.body.citerole || user.citerole; - if ((req.body.password) && (req.body.newpassword)) { - if (req.body.password != req.body.newpassword) { - if (user.checkPassword(req.body.password)) { - user.password = req.body.newpassword; - } else { - res.statusCode = 500; - return res.json({ - error: { - message: 'A senha atual está incorreta' - } - }); - } - } else { + + + if ((req.body.password) && (req.body.newpassword)) { + if (req.body.password != req.body.newpassword) { + if (user.checkPassword(user, req.body.password)) { + await user.update({password:req.body.newpassword}); + } + else { res.statusCode = 500; return res.json({ error: { - message: 'A nova senha é a mesma da senha atual' + message: 'A senha atual está incorreta' } }); } + } else { + res.statusCode = 500; + return res.json({ + error: { + message: 'A nova senha é a mesma da senha atual' + } + }); } + } - user.save().catch(err => { - if (err) { - log.error(err); - return next({ message: 'Erro ao atualizar usuário' }); - } - let u = user.toObject(); - delete u.hashedPassword; - delete u.salt; - res.json({ user: u }); - }) - }).catch(function (err) { + user.save().catch(err => { if (err) { log.error(err); - return next({ err }); - } - }) + return next({ message: 'Erro ao atualizar usuário' }); + }}) + let u = user; + delete u.hashedPassword; + delete u.salt; + delete u.password; + res.json({ user: u }); + }); diff --git a/src/libs/routes_v1/verifyToken.js b/src/libs/routes_v1/verifyToken.js index 8cc9e35d..e69e4761 100644 --- a/src/libs/routes_v1/verifyToken.js +++ b/src/libs/routes_v1/verifyToken.js @@ -12,40 +12,40 @@ const User = require(`${libs}/models/user`); verifyTokenApp.get('/:token', (req, res, next) => { let token = req.params.token; - VerificationToken.findOne({token: token}, (err, vToken) => { - if(err) { + let vToken = VerificationToken.findOne({ where: { token: token } }).catch(function (err) { + if (err) { log.error(err); - return next(err); + return next({ err }); } - if(!vToken) { - // TODO: generate new verification token - res.statusCode = 404; - return next({msg: 'Token not found', status:404}); + }) + if (!vToken) { + // TODO: generate new verification token + res.statusCode = 404; + return next({ msg: 'Token not found', status: 404 }); + } + User.findByPk(vToken.userId, (user) => { + if (err) { + log.error(err); + next(err); } - User.findByPk(vToken.userId, (err, user) => { - if(err) { + user.verified = true; + user.save((err) => { + if (err) { + log.error(err); + next(err); + } + }); + let u = user.toObject(); + delete u.salt; + delete u.hashedPassword; + vToken.verified = true; + vToken.save((err) => { + if (err) { log.error(err); next(err); } - user.verified = true; - user.save((err) => { - if(err) { - log.error(err); - next(err); - } - }); - let u = user.toObject(); - delete u.salt; - delete u.hashedPassword; - vToken.verified = true; - vToken.save((err) => { - if(err) { - log.error(err); - next(err); - } - }); - res.json({msg: 'User verified', user: u}); }); + res.json({ msg: 'User verified', user: u }); }); }); -- GitLab From 669005f86c5ad9ba2407114cc817400cb53aba51 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Fri, 12 May 2023 10:24:53 -0300 Subject: [PATCH 019/123] FIX user POST --- src/libs/models/user.js | 11 ++++++----- src/libs/routes_v1/user.js | 5 ++++- src/libs/routes_v1/verifyToken.js | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libs/models/user.js b/src/libs/models/user.js index 5da038dd..3f0421b8 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -139,7 +139,7 @@ var User = db.define("User",{ defaultValue:false }, citesegment:{ - type: Sequelize.STRING + type: Sequelize.STRING, }, citerole:{ type: Sequelize.STRING @@ -168,13 +168,14 @@ User.generateObjectId = function(){ } const setSaltAndPassword = user => { - if (user.changed('password')) { - user.salt = User.generateSalt() - user.hashed_password = User.encryptPassword(user.password, user.salt).toString('hex'); - } + // if (user.changed('password')) { + user.salt = User.generateSalt() + user.hashed_password = User.encryptPassword(user.password, user.salt).toString('hex'); + // } } const setObjectId = user => { + console.log("I'm in") user.id = User.generateObjectId() }; diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index d53d2748..cc45d7ff 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -125,8 +125,11 @@ userApp.post('/', async (req, res, next) => { return res.json({ errors: ["O campo senha é obrigatório"] }); } else { let user = await User.create({ + id: 0, email: req.body.email, password: req.body.password, + hashed_password: 0, + salt: 0, name: req.body.name, nickname: req.body.nickname, cpf: req.body.cpf, @@ -138,7 +141,7 @@ userApp.post('/', async (req, res, next) => { course: req.body.course, segment: req.body.segment, role: req.body.role, - institutionName: req.body.institutionName, + institution_name: req.body.institutionName, state: req.body.state, city: req.body.city, receiveEmails: false || req.body.receiveEmails, diff --git a/src/libs/routes_v1/verifyToken.js b/src/libs/routes_v1/verifyToken.js index e69e4761..5cef8311 100644 --- a/src/libs/routes_v1/verifyToken.js +++ b/src/libs/routes_v1/verifyToken.js @@ -35,7 +35,7 @@ verifyTokenApp.get('/:token', (req, res, next) => { next(err); } }); - let u = user.toObject(); + let u = user; delete u.salt; delete u.hashedPassword; vToken.verified = true; -- GitLab From bc9ed9d89dd4d08ce31b4181c0b65377479f8cd7 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Fri, 12 May 2023 11:50:11 -0300 Subject: [PATCH 020/123] verifyToken adapted --- src/libs/api_mongo.txt | 2 +- src/libs/routes_v1/user.js | 4 +-- src/libs/routes_v1/verifyToken.js | 44 ++++++++++++++++--------------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/libs/api_mongo.txt b/src/libs/api_mongo.txt index c1353348..d43ea00a 100644 --- a/src/libs/api_mongo.txt +++ b/src/libs/api_mongo.txt @@ -1,5 +1,5 @@ *downloads.js *resetToken.js *simulation.js -*user.js +*user.js (V) *verifyToken.js diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index cc45d7ff..53f3ef54 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -95,7 +95,7 @@ userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, n userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => { let u = req.user; - delete u.hashedPassword; + delete u.hashed_password; delete u.salt; req.result = u; next(); @@ -108,7 +108,7 @@ userApp.get('/:id', (req, res, next) => { res.json({ msg: "O usuário não está cadastrado" }); } else { let u = user; - delete u.hashedPassword; + delete u.hashed_password; delete u.salt; req.result = u; next(); diff --git a/src/libs/routes_v1/verifyToken.js b/src/libs/routes_v1/verifyToken.js index 5cef8311..d1c75b5f 100644 --- a/src/libs/routes_v1/verifyToken.js +++ b/src/libs/routes_v1/verifyToken.js @@ -10,9 +10,9 @@ const VerificationToken = require(`${libs}/models/verificationToken`); const User = require(`${libs}/models/user`); -verifyTokenApp.get('/:token', (req, res, next) => { +verifyTokenApp.get('/:token', async (req, res, next) => { let token = req.params.token; - let vToken = VerificationToken.findOne({ where: { token: token } }).catch(function (err) { + let vToken = await VerificationToken.findOne({ where: { token: token } }).catch(function (err) { if (err) { log.error(err); return next({ err }); @@ -23,30 +23,32 @@ verifyTokenApp.get('/:token', (req, res, next) => { res.statusCode = 404; return next({ msg: 'Token not found', status: 404 }); } - User.findByPk(vToken.userId, (user) => { + let _user = await User.findByPk(vToken.user_id).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + }) + if(!_user){ + return done(null, false); + } + await _user.update({verified:true}); + await _user.save().catch(err => { + if (err) { + log.error(err); + return next({ message: 'Erro ao atualizar usuário' }); + }}) + vToken.verified = true; + await vToken.save().catch(err => { if (err) { log.error(err); next(err); } - user.verified = true; - user.save((err) => { - if (err) { - log.error(err); - next(err); - } - }); - let u = user; - delete u.salt; - delete u.hashedPassword; - vToken.verified = true; - vToken.save((err) => { - if (err) { - log.error(err); - next(err); - } - }); - res.json({ msg: 'User verified', user: u }); }); + let u = _user; + delete u['salt']; + delete u['hashed_password']; + res.json({ msg: 'User verified', u }); }); module.exports = verifyTokenApp; -- GitLab From d8f7962a458b4a30ae8ea5c4234aa43781f42105 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 15 May 2023 11:57:36 -0300 Subject: [PATCH 021/123] [ADD] ResetToken Postgres methods --- src/libs/api_mongo.txt | 5 +- src/libs/middlewares/passport.js | 6 +- src/libs/models/resetToken.js | 2 +- src/libs/routes_v1/resetToken.js | 114 +++++++++++++++--------------- src/libs/routes_v1/user.js | 8 +-- src/libs/routes_v1/verifyToken.js | 2 +- 6 files changed, 69 insertions(+), 68 deletions(-) diff --git a/src/libs/api_mongo.txt b/src/libs/api_mongo.txt index d43ea00a..58f65965 100644 --- a/src/libs/api_mongo.txt +++ b/src/libs/api_mongo.txt @@ -1,5 +1,6 @@ *downloads.js -*resetToken.js +*resetToken.js (V) +*pqr.js *simulation.js *user.js (V) -*verifyToken.js +*verifyToken.js (V) diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js index 82f21de5..a63cd150 100644 --- a/src/libs/middlewares/passport.js +++ b/src/libs/middlewares/passport.js @@ -38,10 +38,10 @@ passport.use(new BearerStrategy(async (accessToken, done) => { } if (Math.round((Date.now() - token.created) / 1000) > config.security.tokenLife) { - AccessToken.destroy({ token: accessToken }).then((err) => { + AccessToken.destroy({where:{ token: accessToken} }).catch(function (err) { if (err) { - console.log("ERRO remove Token") - return done(err); + log.error(err); + return next({ err }); } }); diff --git a/src/libs/models/resetToken.js b/src/libs/models/resetToken.js index 5398e9f4..21e5915e 100644 --- a/src/libs/models/resetToken.js +++ b/src/libs/models/resetToken.js @@ -27,7 +27,7 @@ var ResetToken = db.define("ResetToken",{ {timestamps: false} ); -ResetToken.hasExpired = function () { +ResetToken.prototype.hasExpired = function () { var now = new Date(); return (now - this.createdAt) > 86400; //Expire if token is 1 day old }; diff --git a/src/libs/routes_v1/resetToken.js b/src/libs/routes_v1/resetToken.js index 3d67a1e2..7c758410 100644 --- a/src/libs/routes_v1/resetToken.js +++ b/src/libs/routes_v1/resetToken.js @@ -10,72 +10,72 @@ const ResetToken = require(`${libs}/models/resetToken`); const User = require(`${libs}/models/user`); -resetTokenApp.get('/:token', (req, res, next) => { +resetTokenApp.get('/:token', async (req, res, next) => { let token = req.params.token; - ResetToken.findOne({token: token}, (err, rToken) => { - if(err) { + let rToken = await ResetToken.findOne({where:{ token: token} }).catch(function (err) { + if (err) { log.error(err); - return next(err); + return next({ err }); } - if(!rToken) { - // TODO: generate new reset token - res.statusCode = 404; - return next({msg: 'Token not found', status:404}); - } - if (rToken.hasExpired()) { - res.statusCode = 410; - ResetToken.remove({token: token}, (err) => { - if(err) { - log.error(err); - next(err); - } - }) - return next({msg: 'Token expired', status: 410}); - } - User.findByPk(rToken.userId, (err, user) => { - if(err) { + }) + if (!rToken) { + res.statusCode = 404; + return next({ msg: 'Token not found', status: 404 }); + } + if (rToken.hasExpired()) { + res.statusCode = 410; + await ResetToken.remove({where:{ token: token}}).catch(function (err) { + if (err) { log.error(err); - next(err); + return next({ err }); } - let u = user.toObject(); - delete u.salt; - delete u.hashedPassword; - res.json({user: u}); - }); - }); + }) + return next({ msg: 'Token expired', status: 410 }); + } + let _user = await User.findByPk(rToken.user_id).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + }) + let u = _user.toJSON(); + delete u.salt; + delete u.hashed_password; + res.json({ user: u }); }); -resetTokenApp.post('/:token', (req, res, next) => { + +resetTokenApp.post('/:token', async (req, res, next) => { let token = req.params.token; - ResetToken.findOne({token: token}, (err, rToken) => { - if(err) { + let rToken = await ResetToken.findOne({where:{ token: token}}).catch(function (err) { + if (err) { log.error(err); - return next(err); + return next({ err }); } - if(!rToken) { - res.statusCode = 404; - return next({msg: 'Token not found', status:404}); + }) + if (!rToken) { + res.statusCode = 404; + return next({ msg: 'Token not found', status: 404 }); + } + let _user = await User.findByPk(rToken.user_id).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); } - User.findByPk(rToken.userId, (err, user) => { - if(err) { - log.error(err); - next(err); - } - user.password = req.body.password; - user.save((err) => { - if(err) { - log.error(err); - next(err); - } - ResetToken.remove({token: token}, (err) => { - if(err) { - log.error(err); - next(err); - } - }) - res.json({msg: "Senha alterada com sucesso"}); - }) - }); - }); -}) + }) + await _user.update({password:req.body.password}); + _user.save().catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + }) + await ResetToken.destroy({where:{token: token} }).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + }) + res.json({ msg: "Senha alterada com sucesso" }); +}); module.exports = resetTokenApp; diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 53f3ef54..d02edd84 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -94,7 +94,7 @@ userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, n */ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => { - let u = req.user; + let u = req.user.toJSON(); delete u.hashed_password; delete u.salt; req.result = u; @@ -107,7 +107,7 @@ userApp.get('/:id', (req, res, next) => { res.statusCode = 404; res.json({ msg: "O usuário não está cadastrado" }); } else { - let u = user; + let u = user.toJSON(); delete u.hashed_password; delete u.salt; req.result = u; @@ -256,8 +256,8 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), async ( log.error(err); return next({ message: 'Erro ao atualizar usuário' }); }}) - let u = user; - delete u.hashedPassword; + let u = user.toJSON(); + delete u.hashed_password; delete u.salt; delete u.password; res.json({ user: u }); diff --git a/src/libs/routes_v1/verifyToken.js b/src/libs/routes_v1/verifyToken.js index d1c75b5f..81731fe3 100644 --- a/src/libs/routes_v1/verifyToken.js +++ b/src/libs/routes_v1/verifyToken.js @@ -45,7 +45,7 @@ verifyTokenApp.get('/:token', async (req, res, next) => { next(err); } }); - let u = _user; + let u = _user.toJSON(); delete u['salt']; delete u['hashed_password']; res.json({ msg: 'User verified', u }); -- GitLab From 7a8281ea03f064362ffe2746d52907e47ee6f1eb Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 17 May 2023 11:33:26 -0300 Subject: [PATCH 022/123] [ADD] Simulation and pqr --- src/libs/models/pqr.js | 27 +++--- src/libs/models/simulation.js | 51 ++++++----- src/libs/models/user.js | 1 - src/libs/routes_v1/simulation.js | 153 ++++++++++++++----------------- 4 files changed, 113 insertions(+), 119 deletions(-) diff --git a/src/libs/models/pqr.js b/src/libs/models/pqr.js index f9270318..2a9fb9dd 100644 --- a/src/libs/models/pqr.js +++ b/src/libs/models/pqr.js @@ -1,16 +1,19 @@ -const mongoose = require('mongoose') +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); -const libs = `${process.cwd()}/libs`; -const log = require(`${libs}/log`)(module); -const User = require(`${libs}/models/user`); - -const Schema = mongoose.Schema; - -let PQRSchema = new Schema({ +var PQR = db.define("pqr",{ + id:{ + type: Sequelize.INTEGER, + allowNull: false, + unique: true, + primaryKey: true + }, content: { - type: String, - required: true, + type: Sequelize.STRING, + allowNull: false } -}); +}, +{timestamps: false}); + -module.exports = mongoose.model('PQR', PQRSchema); +module.exports = PQR; diff --git a/src/libs/models/simulation.js b/src/libs/models/simulation.js index f1d3b0bd..21d2de89 100644 --- a/src/libs/models/simulation.js +++ b/src/libs/models/simulation.js @@ -1,34 +1,39 @@ -const mongoose = require('mongoose') +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js') +const User = require(`./user.js`); -const libs = `${process.cwd()}/libs`; -const log = require(`${libs}/log`)(module); -const User = require(`${libs}/models/user`); - -const Schema = mongoose.Schema; - -let SimulationSchema = new Schema({ - userId: { - type: Schema.Types.ObjectId, - required: true, - ref: 'User' +var Simulation = db.define("Simulation",{ + id:{ + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + unique: true, + primaryKey: true }, - content: { - type: String, - required: true, + user_id: { + type: Sequelize.STRING, + allowNull: false + }, + content:{ + type: Sequelize.STRING, + allowNull: false }, name: { - type: String + type: Sequelize.STRING, }, - createdAt: { - type: Date, - required: true, - default: Date.now + created_at:{ + type: Sequelize.DATE, + allowNull: false, + defaultValue: Date.now }, - updatedAt: { + updated_at: { type: Date, required: true, default: Date.now } -}); +}, +{timestamps: false}); + +Simulation.hasOne(User,{ foreignKey: 'id' }); -module.exports = mongoose.model('Simulation', SimulationSchema); +module.exports = Simulation; diff --git a/src/libs/models/user.js b/src/libs/models/user.js index 3f0421b8..a1ab8e27 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -175,7 +175,6 @@ const setSaltAndPassword = user => { } const setObjectId = user => { - console.log("I'm in") user.id = User.generateObjectId() }; diff --git a/src/libs/routes_v1/simulation.js b/src/libs/routes_v1/simulation.js index 4b2e40c3..ea9921d3 100644 --- a/src/libs/routes_v1/simulation.js +++ b/src/libs/routes_v1/simulation.js @@ -6,12 +6,6 @@ const libs = `${process.cwd()}/libs`; const log = require(`${libs}/log`)(module); -const squel = require('squel'); - -const query = require(`${libs}/middlewares/query`).query; - -const response = require(`${libs}/middlewares/response`); - const Simulation = require(`${libs}/models/simulation`); const PQR = require(`${libs}/models/pqr`); @@ -20,7 +14,7 @@ const passport = require('passport'); simulationApp.get('/time', (req, res, next) => { const maxTime = parseInt(req.query.max_time, 10); - if(isNaN(maxTime)) { + if (isNaN(maxTime)) { res.status(400); next({ status: 400, @@ -28,57 +22,54 @@ simulationApp.get('/time', (req, res, next) => { }); } res.json({ - result: Array.apply(null, {length: maxTime}).map(Number.call, Number).map((i)=>i+1) + result: Array.apply(null, { length: maxTime }).map(Number.call, Number).map((i) => i + 1) }); }); -simulationApp.get('/pqr', (req, res) => { - PQR.findOne((err, pqr) => { - if(err) { +simulationApp.get('/pqr', async (req, res) => { + let pqr = await PQR.findOne({ attributes: ['content'] }).catch(function (err) { + if (err) { log.error(err); - return next({err}); + return next({ err }); } - - res.json(pqr); }); + if (pqr) + res.json(pqr); }); -simulationApp.put('/pqr', passport.authenticate('bearer', { session: false }), (req, res, next) => { +simulationApp.put('/pqr', passport.authenticate('bearer', { session: false }), async (req, res, next) => { let user = req.user.toObject(); - - PQR.findOne((err, pqr) => { - if(err) { - log.error(err) - return next({err}); + let pqr = await PQR.findOne({ attributes: ['content'] }).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); } - - if(!user.admin) { - log.info(`Usuário ${user.email} tentou alterar o PQR, mas não tem privilégio`); - res.statusCode = 401; - return next({err: { msg: 'Unauthorized'}}); + }); + if (!user.admin) { + log.info(`Usuário ${user.email} tentou alterar o PQR, mas não tem privilégio`); + res.statusCode = 401; + return next({ err: { msg: 'Unauthorized' } }); + } + pqr.content = req.body.content || pqr.content; + pqr.save().catch(function (err) { + if (err) { + log.error(err); + return next({ err }); } - pqr.content = req.body.content || pqr.content; - pqr.save((err) => { - if(err) { - log.error(err); - return next({err}); - } - res.json({msg: 'PQR updated'}) - }); }); + res.json({ msg: 'PQR updated' }) + }); -simulationApp.get('/', passport.authenticate('bearer', { session: false }), (req, res) => { +simulationApp.get('/', passport.authenticate('bearer', { session: false }), async (req, res) => { let user = req.user.toObject(); - let query = Simulation.find({userId: user._id}).select('userId name createdAt updatedAt'); - query.exec((err, simulations) => { - if(err) { + let simulations = await Simulation.findAll({ where: { user_id: user.id } }, { attributes: ['user_id', 'name', 'created_at', 'updated_at'] }).catch(function (err) { + if (err) { log.error(err); - return next({err}); + return next({ err }); } - - res.json(simulations); - }); + }) + res.json(simulations); // Simulation.find({userId: user._id}, (err, simulations) => { // if(err) { @@ -90,78 +81,74 @@ simulationApp.get('/', passport.authenticate('bearer', { session: false }), (req // }); }); -simulationApp.post('/', passport.authenticate('bearer', { session: false }), (req, res, next) => { +simulationApp.post('/', passport.authenticate('bearer', { session: false }), async (req, res, next) => { let user = req.user.toObject(); - let simulation = new Simulation({ - userId: user._id, + let simulation = await Simulation.create({ + user_id: user.id, content: req.body.content, name: req.body.name }); - simulation.save((err) => { - if(err) { + await simulation.save().catch(function (err) { + if (err) { log.error(err); - return next({err}); + return next({ err }); } + }); - res.json({msg: 'Simulation created', simulation}); - }) -}); + res.json({ msg: 'Simulation created', simulation }); +}) -simulationApp.get('/:id', passport.authenticate('bearer', { session: false }), (req, res) => { +simulationApp.get('/:id', passport.authenticate('bearer', { session: false }), async (req, res) => { let user = req.user.toObject(); - Simulation.findOne({_id: req.params.id, userId: user._id}, (err, simulation) => { - if(err) { + let simulation = await Simulation.findOne({where:{id: req.params.id, userId: user._id }}).catch(function (err) { + if (err) { log.error(err); - return next({err}); + return next({ err }); } - - res.json(simulation); }); + res.json(simulation); + }); -simulationApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { +simulationApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { let user = req.user.toObject(); - Simulation.findOne({_id: req.params.id, userId: user._id}, (err, simulation) => { - if(err) { + let simulation = await Simulation.findOne({ where: { id: req.params.id, user_id: user.id } }).catch(function (err) { + if (err) { log.error(err); - return next({err}); - } - - if(!simulation) { - res.statusCode = 404; - return next({err: { msg: 'Simulation not found'}}); + return next({ err }); } + }); - simulation.content = req.body.content || simulation.content; - simulation.name = req.body.name || simulation.name; - simulation.updatedAt = Date.now(); - - simulation.save((err) => { - if(err) { - log.error(err); - return next(err); - } + if (!simulation) { + res.statusCode = 404; + return next({ err: { msg: 'Simulation not found' } }); + } - res.json(simulation); - }); + simulation.content = req.body.content || simulation.content; + simulation.name = req.body.name || simulation.name; + simulation.updated_at = Date.now(); + simulation.save().catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } }); + res.json(simulation); }); -simulationApp.delete('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { +simulationApp.delete('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { let user = req.user.toObject(); - - Simulation.remove({_id: req.params.id, userId: user._id}, (err, simulation) => { - if(err) { + await Simulation.destroy({ where: { "id": req.params.id, "user_id": user._id } }).catch(function (err) { + if (err) { log.error(err); - return next({err}); + return next({ err }); } - - res.json({msg: 'Simulation removed'}); }); + res.json({ msg: 'Simulation removed' }); }); module.exports = simulationApp; -- GitLab From c755ce9a25fe7407f6b233c6d0b1c22d40ef0876 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 18 May 2023 11:52:17 -0300 Subject: [PATCH 023/123] [FIX] PUT Simulation --- src/libs/routes_v1/simulation.js | 46 +++++++++++++++++++------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/src/libs/routes_v1/simulation.js b/src/libs/routes_v1/simulation.js index ea9921d3..11ff69d3 100644 --- a/src/libs/routes_v1/simulation.js +++ b/src/libs/routes_v1/simulation.js @@ -38,37 +38,45 @@ simulationApp.get('/pqr', async (req, res) => { }); simulationApp.put('/pqr', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let user = req.user.toObject(); - let pqr = await PQR.findOne({ attributes: ['content'] }).catch(function (err) { + let user = req.user; + let pqr = await PQR.findOne().catch(function (err) { if (err) { log.error(err); return next({ err }); } }); + res.json(pqr); if (!user.admin) { log.info(`Usuário ${user.email} tentou alterar o PQR, mas não tem privilégio`); res.statusCode = 401; return next({ err: { msg: 'Unauthorized' } }); } - pqr.content = req.body.content || pqr.content; - pqr.save().catch(function (err) { - if (err) { - log.error(err); - return next({ err }); - } - }); + + if(pqr){ + let _content = req.body.content || pqr.content; + pqr.content = _content; + await pqr.save({fields:['content']}).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + });} + res.json({ msg: 'PQR updated' }) }); simulationApp.get('/', passport.authenticate('bearer', { session: false }), async (req, res) => { - let user = req.user.toObject(); + let user = req.user; let simulations = await Simulation.findAll({ where: { user_id: user.id } }, { attributes: ['user_id', 'name', 'created_at', 'updated_at'] }).catch(function (err) { if (err) { log.error(err); return next({ err }); } }) + if (!simulations){ + res.json("Simulations not found"); + } res.json(simulations); // Simulation.find({userId: user._id}, (err, simulations) => { @@ -82,7 +90,7 @@ simulationApp.get('/', passport.authenticate('bearer', { session: false }), asyn }); simulationApp.post('/', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let user = req.user.toObject(); + let user = req.user; let simulation = await Simulation.create({ user_id: user.id, @@ -101,9 +109,9 @@ simulationApp.post('/', passport.authenticate('bearer', { session: false }), asy }) simulationApp.get('/:id', passport.authenticate('bearer', { session: false }), async (req, res) => { - let user = req.user.toObject(); + let user = req.user; - let simulation = await Simulation.findOne({where:{id: req.params.id, userId: user._id }}).catch(function (err) { + let simulation = await Simulation.findOne({where:{id: req.params.id, user_id: user.id }}).catch(function (err) { if (err) { log.error(err); return next({ err }); @@ -114,7 +122,7 @@ simulationApp.get('/:id', passport.authenticate('bearer', { session: false }), a }); simulationApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let user = req.user.toObject(); + let user = req.user; let simulation = await Simulation.findOne({ where: { id: req.params.id, user_id: user.id } }).catch(function (err) { if (err) { @@ -130,19 +138,19 @@ simulationApp.put('/:id', passport.authenticate('bearer', { session: false }), a simulation.content = req.body.content || simulation.content; simulation.name = req.body.name || simulation.name; - simulation.updated_at = Date.now(); - simulation.save().catch(function (err) { + simulation.updated_at = new Date(); + await simulation.save({fields:['content','name','updated_at']}).catch(function (err) { if (err) { log.error(err); return next({ err }); } }); - res.json(simulation); + res.json({msg: 'Simulation updated'}); }); simulationApp.delete('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let user = req.user.toObject(); - await Simulation.destroy({ where: { "id": req.params.id, "user_id": user._id } }).catch(function (err) { + let user = req.user; + await Simulation.destroy({where: { "id": req.params.id, "user_id": user.id } }).catch(function (err) { if (err) { log.error(err); return next({ err }); -- GitLab From 1e98205f1788c966b3a8908e6a5e596d72dde768 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Fri, 19 May 2023 11:00:16 -0300 Subject: [PATCH 024/123] [ADD] Downloads --- src/libs/middlewares/downloadDatabase.js | 78 +++++++++++----------- src/libs/models/download.js | 83 +++++++++++++----------- src/libs/models/resetToken.js | 3 + src/libs/routes_v1/downloads.js | 53 +++++++-------- src/libs/routes_v1/simulation.js | 3 +- 5 files changed, 112 insertions(+), 108 deletions(-) diff --git a/src/libs/middlewares/downloadDatabase.js b/src/libs/middlewares/downloadDatabase.js index c4672ff0..6f2dec6f 100644 --- a/src/libs/middlewares/downloadDatabase.js +++ b/src/libs/middlewares/downloadDatabase.js @@ -10,11 +10,11 @@ const config = require(`${libs}/config`); const Download = require(`${libs}/models/download`); -module.exports = function download(table, mappingTable) { +module.exports = function download(table, mapping_table) { return (req, res, next) => { // First, query the mapping - execute(`SELECT target_name, name FROM ${mappingTable}`, undefined, (err, result) => { - if(err) { + execute(`SELECT target_name, name FROM ${mapping_table}`, undefined, (err, result) => { + if (err) { log.error(err.stack); next(new Error('Request could not be satisfied due to a database error.')); } else { @@ -23,7 +23,7 @@ module.exports = function download(table, mappingTable) { result.forEach((field) => { req.sql.field(`CASE ${table}.${field.name} WHEN true THEN 1 WHEN false THEN 0 ELSE ${table}.${field.name} END AS ${field.target_name}`); // req.sql.field(table + '.' + field.name, field.target_name); - if(header === '') header += field.target_name; + if (header === '') header += field.target_name; else header = header + ';' + field.target_name; }); @@ -36,53 +36,51 @@ module.exports = function download(table, mappingTable) { header }; - request.post(config.cdn.url + '/api/v1/file', {form}, (err, response, body) => { - if(err) { + request.post(config.cdn.url + '/api/v1/file', { form }, async (err, response, body) => { + if (err) { log.error(err); - return res.json({error: err}); + return res.json({ error: err }); } - Download.findOne({query: req.sql.toString()}, (err, download) => { - if(download) { - download.updatedAt = Date.now(); - if(download.userId != req.user._id) { - let dl = new Download({ - userId: req.user._id, - table, - name: req.query.name, - mappingTable, - query: req.sql.toString(), - status: 'Enviando', - expired: false - }); - console.log(dl); - dl.save((err) => { - if(err) log.error(err); - }); - } - } else { - download = new Download({ - userId: req.user._id, + let download = await Download.findOne({ where: { query: req.sql.toString() } }).catch(function (err) { + if (err) { + log.error(err); + } + }) + if (download) { + download.updated_at = new Date(); + if (download.user_id != req.user.id) { + let dl = await Download.create({ + user_id: req.user.id, table, name: req.query.name, - mappingTable, - query: req.sql.toString(), + mapping_table, query: req.sql.toString(), status: 'Enviando', expired: false }); - console.log(download); + console.log(dl); + dl.save().catch(function (err) { + if (err) log.error(err); + }); } - - download.save((err) => { - if(err) { - log.error(err); - } - res.json({msg: 'Wait for download email', waitForIt: true}); + } else { + download = await Download.create({ + user_id: req.user.id, + table, + name: req.query.name, + mapping_table, + query: req.sql.toString(), + status: 'Enviando', + expired: false }); - }); + console.log(download); + } + + await download.save() + res.json({ msg: 'Wait for download email', waitForIt: true }); }); - } + }; }); } -}; \ No newline at end of file +} \ No newline at end of file diff --git a/src/libs/models/download.js b/src/libs/models/download.js index 989896d9..3d59249a 100644 --- a/src/libs/models/download.js +++ b/src/libs/models/download.js @@ -1,53 +1,60 @@ -const mongoose = require('mongoose'); -const Schema = mongoose.Schema; +const Sequelize = require("sequelize"); +const crypto = require('crypto'); +const db = require('../db/postgres.js'); 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 - }, - name: { - type: String, - required: true - }, - mappingTable: { - type: String, - required: true +var Download = db.define("Download",{ + id:{ + type: Sequelize.INTEGER, + allowNull: false, + autoIncrement: true, + unique: true, + primaryKey: true + }, + user_id: { + type: Sequelize.STRING, + allowNull: false + }, + table:{ + type: Sequelize.STRING, + allowNull: false, + }, + name:{ + type: Sequelize.STRING, + allowNull: false, + }, + mapping_table:{ + type: Sequelize.STRING, + allowNull:false }, query: { - type: String, - required: true + type: Sequelize.STRING, + allowNull:false }, - createdAt: { - type: Date, - required: true, - default: Date.now - }, - updatedAt: { - type: Date, - required: true, - default: Date.now + created_at:{ + type: Sequelize.DATE, + defaultValue: Date.now + }, + updated_at: { + type: Sequelize.DATE, + defaultValue: Date.now }, status: { - type: String + type: Sequelize.STRING }, size: { - type: Number + type: Sequelize.NUMBER }, expired: { - type: Boolean + type: Sequelize.BOOLEAN }, link: { - type: String - } -}); + type: Sequelize.STRING, + }}, + {timestamps: false} +); + +Download.hasOne(User,{ foreignKey: 'id' }); -module.exports = mongoose.model('Download', Download); +module.exports = Download diff --git a/src/libs/models/resetToken.js b/src/libs/models/resetToken.js index 21e5915e..dca5488a 100644 --- a/src/libs/models/resetToken.js +++ b/src/libs/models/resetToken.js @@ -32,4 +32,7 @@ ResetToken.prototype.hasExpired = function () { return (now - this.createdAt) > 86400; //Expire if token is 1 day old }; +ResetToken.hasOne(User,{ foreignKey: 'id' }); + + module.exports = ResetToken diff --git a/src/libs/routes_v1/downloads.js b/src/libs/routes_v1/downloads.js index 2ec83b9e..cd6cad0b 100644 --- a/src/libs/routes_v1/downloads.js +++ b/src/libs/routes_v1/downloads.js @@ -8,46 +8,43 @@ const log = require(`${libs}/log`)(module); const Download = require(`${libs}/models/download`); -const User = require(`${libs}/models/user`); - const passport = require('passport'); const request = require(`request`); const config = require(`${libs}/config`); -downloadApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, next) => { - request.get(config.cdn.url + '/api/v1/file', (err, response, body) => { +downloadApp.get('/', passport.authenticate('bearer', { session: false }), (req, res, next) => { + request.get(config.cdn.url + '/api/v1/file', async (err, response, body) => { let cdn = JSON.parse(body); - Download.find({userId: req.user._id}, (err, downloads) => { + const downloads = await Download.findAll({ where: { user_id: req.user.id } }).catch(function (err) { if (err) { log.error(err); return next(err); } - - if(!downloads) { - res.statusCode = 404; - return res.json({msg: 'Nenhum download encontrado'}); - } else { - downloads.forEach((dl) => { - for(let i = 0; i < cdn.length; ++i) { - if(cdn[i].query == dl.query) { - dl.status = cdn[i].expired ? 'Expirado' : 'Enviado'; - dl.size = cdn[i].size; - dl.expired = cdn[i].expired; - dl.updatedAt = cdn[i].lastAccess; - dl.link = config.cdn.download + '/' + cdn[i]._id; - - dl.save((err) => { - if(err) log.error(err); - }); - return; - } - } - }); - } - res.json(downloads); }); + if (!downloads) { + res.statusCode = 404; + return res.json({ msg: 'Nenhum download encontrado' }); + } else { + downloads.forEach((dl) => { + for (let i = 0; i < cdn.length; ++i) { + if (cdn[i].query == dl.query) { + dl.status = cdn[i].expired ? 'Expirado' : 'Enviado'; + dl.size = cdn[i].size; + dl.expired = cdn[i].expired; + dl.updatedAt = cdn[i].lastAccess; + dl.link = config.cdn.download + '/' + cdn[i]._id; + + dl.save((err) => { + if (err) log.error(err); + }); + return; + } + } + }); + } + res.json(downloads); }); }); diff --git a/src/libs/routes_v1/simulation.js b/src/libs/routes_v1/simulation.js index 11ff69d3..cc0ab380 100644 --- a/src/libs/routes_v1/simulation.js +++ b/src/libs/routes_v1/simulation.js @@ -45,7 +45,6 @@ simulationApp.put('/pqr', passport.authenticate('bearer', { session: false }), a return next({ err }); } }); - res.json(pqr); if (!user.admin) { log.info(`Usuário ${user.email} tentou alterar o PQR, mas não tem privilégio`); res.statusCode = 401; @@ -145,7 +144,7 @@ simulationApp.put('/:id', passport.authenticate('bearer', { session: false }), a return next({ err }); } }); - res.json({msg: 'Simulation updated'}); + res.json({ msg: 'Simulation created', simulation }); }); simulationApp.delete('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { -- GitLab From 173e946cad4e61764504c77ec502801cf37222c1 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Tue, 23 May 2023 11:29:55 -0300 Subject: [PATCH 025/123] [ADD] New Tables and Relations in Postgres --- src/libs/models/Permission.js | 0 src/libs/models/PermissionRole.js | 0 src/libs/models/Role.js | 0 src/libs/models/user.js | 5 +++++ 4 files changed, 5 insertions(+) create mode 100644 src/libs/models/Permission.js create mode 100644 src/libs/models/PermissionRole.js create mode 100644 src/libs/models/Role.js diff --git a/src/libs/models/Permission.js b/src/libs/models/Permission.js new file mode 100644 index 00000000..e69de29b diff --git a/src/libs/models/PermissionRole.js b/src/libs/models/PermissionRole.js new file mode 100644 index 00000000..e69de29b diff --git a/src/libs/models/Role.js b/src/libs/models/Role.js new file mode 100644 index 00000000..e69de29b diff --git a/src/libs/models/user.js b/src/libs/models/user.js index a1ab8e27..f4a9d626 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -148,6 +148,11 @@ var User = db.define("User",{ type: Sequelize.BOOLEAN, defaultValue:false }, + role_id:{ + type: Sequelize.NUMBER, + allowNull:false, + defaultValue: 0 + } }, {timestamps: false} ); -- GitLab From 22047d80f4c5054d65229e4d659f9916aceedd28 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Tue, 23 May 2023 11:50:45 -0300 Subject: [PATCH 026/123] [ADD] Models --- src/libs/models/Permission.js | 0 src/libs/models/PermissionRole.js | 0 src/libs/models/Role.js | 0 src/libs/models/permission.js | 25 +++++++++++++++++++++++++ src/libs/models/permissionRole.js | 29 +++++++++++++++++++++++++++++ src/libs/models/role.js | 19 +++++++++++++++++++ src/libs/models/user.js | 3 +++ 7 files changed, 76 insertions(+) delete mode 100644 src/libs/models/Permission.js delete mode 100644 src/libs/models/PermissionRole.js delete mode 100644 src/libs/models/Role.js create mode 100644 src/libs/models/permission.js create mode 100644 src/libs/models/permissionRole.js create mode 100644 src/libs/models/role.js diff --git a/src/libs/models/Permission.js b/src/libs/models/Permission.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/libs/models/PermissionRole.js b/src/libs/models/PermissionRole.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/libs/models/Role.js b/src/libs/models/Role.js deleted file mode 100644 index e69de29b..00000000 diff --git a/src/libs/models/permission.js b/src/libs/models/permission.js new file mode 100644 index 00000000..917b5197 --- /dev/null +++ b/src/libs/models/permission.js @@ -0,0 +1,25 @@ +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); +const libs = `${process.cwd()}/libs`; +const Role = require(`${libs}/models/role`); + +var Permission = db.define("PermissionRole",{ + id:{ + type: Sequelize.INTEGER, + allowNull:false, + unique: true, + primaryKey: true + }, + permission_name:{ + type: Sequelize.STRING, + allowNull:false, + }, + permission_description:{ + type: Sequelize.STRING, + allowNull:false + } +}, +{timestamps: false}); + +module.exports = PermissionRole; + diff --git a/src/libs/models/permissionRole.js b/src/libs/models/permissionRole.js new file mode 100644 index 00000000..441b4345 --- /dev/null +++ b/src/libs/models/permissionRole.js @@ -0,0 +1,29 @@ +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); +const libs = `${process.cwd()}/libs`; +const Role = require(`${libs}/models/role`); +const Permission = require(`${libs}/models/permission`); + +var PermissionRole = db.define("PermissionRole",{ + id:{ + type: Sequelize.INTEGER, + allowNull:false, + unique: true, + primaryKey: true + }, + role_id:{ + type: Sequelize.INTEGER, + allowNull:false, + }, + permission_id:{ + type: Sequelize.INTEGER, + allowNull:false + } +}, +{timestamps: false}); + +PermissionRole.hasOne(Role, {foreignKey: 'id'}); +PermissionRole.hasOne(Permission, {foreignKey: 'id'}); + +module.exports = PermissionRole; + diff --git a/src/libs/models/role.js b/src/libs/models/role.js new file mode 100644 index 00000000..dc30e09e --- /dev/null +++ b/src/libs/models/role.js @@ -0,0 +1,19 @@ +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); + +var Role = db.define("Role",{ + id:{ + type: Sequelize.INTEGER, + allowNull:false, + unique: true, + primaryKey: true + }, + role_name:{ + type: Sequelize.STRING, + allowNull:false, + } +}, +{timestamps: false}); + +module.exports = Role; + diff --git a/src/libs/models/user.js b/src/libs/models/user.js index f4a9d626..ce65500a 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -2,6 +2,7 @@ const Sequelize = require("sequelize"); const crypto = require('crypto'); const db = require('../db/postgres.js'); const libs = `${process.cwd()}/libs`; +const Role = require(`${libs}/models/role`); // set up a sequelize model var User = db.define("User",{ @@ -157,6 +158,8 @@ var User = db.define("User",{ {timestamps: false} ); +User.hasOne(Role, {foreignKey: 'id'}); + User.generateSalt = function() { return crypto.randomBytes(128).toString('hex'); } -- GitLab From ecec214d999b5d2ef3f15a6e41ee426fd72bbbc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Wed, 24 May 2023 11:08:00 -0300 Subject: [PATCH 027/123] Initiate changes to aggregated classroom_count, not ready yet --- src/libs/middlewares/query.js | 2 + src/libs/routes_v2/aux | 1 + src/libs/routes_v2/classroomCount.js | 145 +++++++++++---------------- 3 files changed, 61 insertions(+), 87 deletions(-) create mode 100644 src/libs/routes_v2/aux diff --git a/src/libs/middlewares/query.js b/src/libs/middlewares/query.js index b724d93d..3b734957 100644 --- a/src/libs/middlewares/query.js +++ b/src/libs/middlewares/query.js @@ -10,6 +10,8 @@ function query(req, res, next) { execute(sql.text, sql.values, (err, result) => { if(err) { log.error(err.stack); + console.log(sql.text); + console.log(sql.values); next(new Error('Request could not be satisfied due to a database error.')); } else { req.result = result; diff --git a/src/libs/routes_v2/aux b/src/libs/routes_v2/aux new file mode 100644 index 00000000..c0b4cc5f --- /dev/null +++ b/src/libs/routes_v2/aux @@ -0,0 +1 @@ +SELECT COUNT(*) AS "total", simcaq_matricula_agregada.ano_censo AS "year", estado.nome AS "state_name", estado.id AS "state_id", municipio.nome AS "city_name", municipio.id AS "city_id", simcaq_matricula_agregada.etapa_resumida AS "education_level_short_id", simcaq_matricula_agregada.tempo_integral AS "integral_time_id" FROM simcaq_matricula_agregada INNER JOIN estado ON (simcaq_matricula_agregada.estado_id=estado.id) INNER JOIN municipio ON (simcaq_matricula_agregada.municipio_id=municipio.id) WHERE (simcaq_matricula_agregada.ano_censo >= 2021 ) AND (simcaq_matricula_agregada.ano_censo <= 2021 ) GROUP BY simcaq_matricula_agregada.ano_censo, estado.nome, estado.id, municipio.nome, municipio.id, simcaq_matricula_agregada.etapa_resumida, simcaq_matricula_agregada.tempo_integral ORDER BY simcaq_matricula_agregada.ano_censo ASC, estado.nome ASC, estado.id ASC, municipio.nome ASC, municipio.id ASC, simcaq_matricula_agregada.etapa_resumida ASC, simcaq_matricula_agregada.tempo_integral ASC diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 4f76bed3..34c8b33f 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -54,21 +54,20 @@ rqf.addField({ }).addValueToField({ name: 'city', table: 'municipio', - tableField: 'nome', - resultField: 'city_name', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], where: { relation: '=', type: 'integer', - field: 'municipio_id', - table: '@' + field: 'id' }, join: { primary: 'id', foreign: 'municipio_id', foreignTable: '@' } -}, 'filter').addValueToField({ - name: 'city', +}, 'dims').addValueToField({ + name: 'cityTeacher', table: 'municipio', tableField: ['nome', 'id'], resultField: ['city_name', 'city_id'], @@ -79,26 +78,10 @@ rqf.addField({ }, join: { primary: 'id', - foreign: 'municipio_id', + foreign: 'escola_cidade_id', foreignTable: '@' } }, 'dims').addValueToField({ - name: 'state', - table: 'estado', - tableField: 'nome', - resultField: 'state_name', - where: { - relation: '=', - type: 'integer', - field: 'estado_id', - table: '@' - }, - join: { - primary: 'id', - foreign: 'estado_id', - foreignTable: '@' - } -}, 'filter').addValueToField({ name: 'state', table: 'estado', tableField: ['nome', 'id'], @@ -115,7 +98,7 @@ rqf.addField({ } }, 'dims').addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: ['nome_escola', 'id'], resultField: ['school_name', 'school_id'], where: { @@ -163,39 +146,9 @@ rqf.addField({ type: 'integer', field: 'ano_censo' } -}).addValue({ - name: 'school_year', - table: '@', - tableField: 'serie_ano_id', - resultField: 'school_year_id', - where: { - relation: '=', - type: 'integer', - field: 'serie_ano_id' - } -}).addValue({ - name: 'location', - table: '@', - tableField: 'localizacao_id', - resultField: 'location_id', - where: { - relation: '=', - type: 'integer', - field: 'localizacao_id' - } -}).addValue({ - name: 'period', - table: '@', - tableField: 'turma_turno_id', - resultField: 'period_id', - where: { - relation: '=', - type: 'integer', - field: 'turma_turno_id' - } }).addValue({ name: 'school_building', - table: 'escola', + table: '@', tableField: 'local_func_predio_escolar', resultField: 'school_building', where: { @@ -205,7 +158,7 @@ rqf.addField({ } }).addValue({ name: 'night_time', - table: 'matricula', + table: '@', tableField: 'periodo_noturno', resultField: 'night_time', where: { @@ -215,7 +168,7 @@ rqf.addField({ } }).addValue({ name: 'formation_level', - table: 'docente_por_formacao', + table: '@', tableField: 'tipo_formacao', resultField: 'formation_level', where: { @@ -235,7 +188,7 @@ rqf.addField({ } }, 'filter') .addValue({ name: 'integral_time', - table: 'matricula', + table: '@', tableField: 'tempo_integral', resultField: 'integral_time_id', where: { @@ -245,7 +198,7 @@ rqf.addField({ } }).addValue({ name: 'education_level_short', - table: 'matricula', + table: '@', tableField: 'etapa_resumida', resultField: 'education_level_short_id', where: { @@ -253,6 +206,26 @@ rqf.addField({ type: 'integer', field: 'etapa_resumida' } +}).addValue({ + name: 'location', + table: '@', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'school_year', + table: '@', + tableField: 'ano_censo', + resultField: 'school_year', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } }); classroomCountApp.post('/', rqf.parse(), (req, res, next) => { @@ -276,11 +249,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.sql.field('sum(dia_total)', 'total_day') .field('sum(noite_total)', 'total_night') .field("'Brasil'", 'name') - .field('matricula_por_localizacao.ano_censo', 'year') - .from('matricula_por_localizacao') - .where('matricula_por_localizacao.serie_ano_id < 15') - .group('matricula_por_localizacao.ano_censo') - .order('matricula_por_localizacao.ano_censo') + .field('simcaq_matricula_por_localizacao.ano_censo', 'year') + .from('simcaq_matricula_por_localizacao') + .where('simcaq_matricula_por_localizacao.serie_ano_id < 15') + .group('simcaq_matricula_por_localizacao.ano_censo') + .order('simcaq_matricula_por_localizacao.ano_censo') next(); }, rqf.build(), query, id2str.transform(), (req, res, next) => { @@ -310,7 +283,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }; } } - + delete req.dims; delete req.filter; req.resetSql(); @@ -322,15 +295,15 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.location = true; req.dims.school_building = true; - req.sql.field('SUM(escola.qtde_salas_utilizadas_dentro)', 'total') + req.sql.field('SUM(escola_agregada.qtde_salas_utilizadas_dentro)', 'total') .field("'Brasil'", 'name') - .field('escola.ano_censo', 'year') - .from('escola') - .group('escola.ano_censo') - .order('escola.ano_censo') - .where('escola.situacao_de_funcionamento = 1') - .where('escola.dependencia_adm_id < 4') - .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1'); + .field('escola_agregada.ano_censo', 'year') + .from('escola_agregada') + .group('escola_agregada.ano_censo') + .order('escola_agregada.ano_censo') + .where('escola_agregada.situacao_funcionamento_pareada = 1') + .where('escola_agregada.dependencia_adm_id < 4') + .where('escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1'); next(); }, rqf.build(), query, id2str.transform(), (req, res, next) => { @@ -379,15 +352,14 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.teacherCalc = true; } - req.dims.state = true; - req.dims.city = true; + req.dims.cityTeacher = true; req.dims.formation_level = true; - req.sql.field('count(distinct docente_por_formacao.id_docente)', 'total') + req.sql.field('SUM(simcaq_docente_agregada.num_docentes)', 'total') .field("'Brasil'", 'name') - .field('docente_por_formacao.ano_censo', 'year') - .from('docente_por_formacao') - .group('docente_por_formacao.ano_censo') - .order('docente_por_formacao.ano_censo'); + .field('simcaq_docente_agregada.ano_censo', 'year') + .from('simcaq_docente_agregada') + .group('simcaq_docente_agregada.ano_censo') + .order('simcaq_docente_agregada.ano_censo'); next(); }, rqf.build(), query, id2str.transform(), (req, res, next) => { @@ -401,13 +373,13 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.state = true; req.dims.city = true; req.dims.education_level_short = true; - req.dims.integral_time = true; + //req.dims.integral_time = true; req.sql.field('COUNT(*)', 'total') - .field('matricula.ano_censo', 'year') - .from('matricula') - .group('matricula.ano_censo') - .order('matricula.ano_censo') - .where('((matricula.tipo<=3 OR matricula.tipo IS NULL) AND (matricula.tipo_atendimento_turma IS NULL OR matricula.tipo_atendimento_turma <= 2) AND matricula.turma_turno_id <> 99)'); + .field('simcaq_matricula_agregada.ano_censo', 'year') + .from('simcaq_matricula_agregada') + .group('simcaq_matricula_agregada.ano_censo') + .order('simcaq_matricula_agregada.ano_censo'); + //.where('((simcaq_matricula_agregada.tipo<=3 OR simcaq_matricula_agregada.tipo IS NULL) AND (simcaq_matricula_agregada.tipo_atendimento_turma IS NULL OR simcaq_matricula_agregada.tipo_atendimento_turma <= 2) AND simcaq_matricula_agregada.turma_turno_id <> 99)'); next(); }, rqf.build() ,query, id2str.transform(), (req, res, next) => { // constrói objeto de tempo integral e calcula diagnósticos @@ -562,7 +534,6 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { ti++; if (ti === req.teacher.length) { - console.log(classroom[id_attribute], "not found") while (classroom[id_attribute] === enrollments[j][id_attribute]) enrollments.splice(j, 1) ti = old_ti; -- GitLab From 04449c13aa6ea709ef3d5133c93b6e8028a8eee5 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 25 May 2023 11:56:36 -0300 Subject: [PATCH 028/123] [ADD] Models Publication, userPublication --- src/libs/models/permissionRole.js | 4 +- src/libs/models/publication.js | 57 +++++++ src/libs/models/userPublication.js | 29 ++++ src/libs/routes_v1/publication.js | 266 +++++++++++++++++++++++++++++ src/libs/routes_v1/user.js | 3 +- 5 files changed, 356 insertions(+), 3 deletions(-) create mode 100644 src/libs/models/publication.js create mode 100644 src/libs/models/userPublication.js create mode 100644 src/libs/routes_v1/publication.js diff --git a/src/libs/models/permissionRole.js b/src/libs/models/permissionRole.js index 441b4345..e415acc6 100644 --- a/src/libs/models/permissionRole.js +++ b/src/libs/models/permissionRole.js @@ -22,8 +22,8 @@ var PermissionRole = db.define("PermissionRole",{ }, {timestamps: false}); -PermissionRole.hasOne(Role, {foreignKey: 'id'}); -PermissionRole.hasOne(Permission, {foreignKey: 'id'}); +PermissionRole.hasMany(Role, {foreignKey: 'id'}); +PermissionRole.hasMany(Permission, {foreignKey: 'id'}); module.exports = PermissionRole; diff --git a/src/libs/models/publication.js b/src/libs/models/publication.js new file mode 100644 index 00000000..03b3f0f4 --- /dev/null +++ b/src/libs/models/publication.js @@ -0,0 +1,57 @@ +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); +const libs = `${process.cwd()}/libs`; + +var Publication = db.define("Publication",{ + id:{ + type: Sequelize.INTEGER, + allowNull:false, + unique: true, + primaryKey: true + }, + filter:{ + type: Sequelize.ENUM("Artigo", "Tese", "Dissertação", "Relatório", "Periódico"), + allowNull:false, + validate: { + notNull: { msg: "O campo categoria é obrigatória e aceita apenas os valores 'Artigo', 'Tese', 'Dissertação', 'Relatório', 'Periódico."}, + } + }, + title:{ + type: Sequelize.STRING, + allowNull:false, + }, + authors:{ + type: Sequelize.STRING, + allowNull:false + }, + organization:{ + type: Sequelize.STRING, + allowNull:false + }, + year:{ + type:Sequelize.STRING, + allowNull:false + }, + text:{ + type: Sequelize.ENUM("Baixar","Acessar"), + allowNull:false, + validate: { + notNull: { msg: "O campo origem é obrigatória e aceita apenas os valores 'Baixar', 'Acessar'."}, + } + }, + link:{ + type: Sequelize.STRING + }, + upload:{ + type: Sequelize.STRING + }, + is_draft:{ + type:Sequelize.BOOLEAN, + allowNull:false, + defaultValue: true + } + +}, +{timestamps: false}); + +module.exports = Publication; \ No newline at end of file diff --git a/src/libs/models/userPublication.js b/src/libs/models/userPublication.js new file mode 100644 index 00000000..43417ffe --- /dev/null +++ b/src/libs/models/userPublication.js @@ -0,0 +1,29 @@ +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); +const libs = `${process.cwd()}/libs`; +const User = require(`${libs}/models/user`); +const Publication = require(`${libs}/models/publication`); + +var userPublication = db.define("userPublication",{ + id:{ + type: Sequelize.INTEGER, + allowNull:false, + unique: true, + primaryKey: true + }, + user_id:{ + type: Sequelize.STRING, + allowNull:false, + }, + publication_id:{ + type: Sequelize.INTEGER, + allowNull:false + } +}, +{timestamps: false}); + +userPublication.hasMany(User, {foreignKey: 'id'}); +userPublication.hasMany(Publication, {foreignKey: 'id'}); + +module.exports = userPublication; + diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js new file mode 100644 index 00000000..dc6d6471 --- /dev/null +++ b/src/libs/routes_v1/publication.js @@ -0,0 +1,266 @@ +const express = require('express'); + +const pubApp = express(); + +const libs = `${process.cwd()}/libs`; + +const config = require(`${libs}/config`); + +const log = require(`${libs}/log`)(module); + +const VerificationToken = require(`${libs}/models/verificationToken`); + +const Publication = require(`${libs}/models/publication`); + +const UserPublication = require(`${libs}/models/userPublication`); + +const ResetToken = require(`${libs}/models/resetToken`); + +const response = require(`${libs}/middlewares/response`); + +const email = require(`${libs}/middlewares/email`); + +const passport = require('passport'); + +const uuid = require('node-uuid'); + +function emailSyntax(email) { + const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + return regex.test(email); +} + +pubApp.get('/', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + let up = await UserPublication.findAll({where:{user_id:req.user.id}}).catch(function(err){ + if(err){ + log.error(err); + return next(err); + } + }); + console.log(up); + let publications = []; + for(let _id in up.publication_id){ + let pb = await Publication.findByPk(_id).catch(function(err){ + if(err){ + log.error(err); + return next(err); + } + }); + publications.push(pb); + } + next(); +}, response('user')); + +pubApp.get('/:id', (req, res, next) => { + UserPublication.findByPk(req.params.id).then((user) => { + if (!user) { + res.statusCode = 404; + res.json({ msg: "O usuário não está cadastrado" }); + } else { + let u = user.toJSON(); + delete u.hashed_password; + delete u.salt; + req.result = u; + next(); + } + }).catch(function (err) { + log.error(err); + return next(err); + }); +}, response('publication')); + +pubApp.post('/', async (req, res, next) => { + if (typeof req.body.password === 'undefined' || !req.body.password) { + res.statusCode = 400; + return res.json({ errors: ["O campo senha é obrigatório"] }); + } else { + let user = await User.create({ + id: 0, + email: req.body.email, + password: req.body.password, + hashed_password: 0, + salt: 0, + name: req.body.name, + nickname: req.body.nickname, + cpf: req.body.cpf, + cep: req.body.cep, + complement: req.body.complement, + address: req.body.address, + phone: req.body.phone, + schooling: req.body.schooling, + course: req.body.course, + segment: req.body.segment, + role: req.body.role, + institution_name: req.body.institutionName, + state: req.body.state, + city: req.body.city, + receiveEmails: false || req.body.receiveEmails, + origin: req.body.origin, + citesegment: req.body.citesegment, + citerole: req.body.citerole, + admin: false, + role_id: 0 + }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); + res.statusCode = 400; + return res.json({ err, errors }); + // handle error; + }); + let tokenValue = uuid.v4(); + const verificationToken = VerificationToken.create({ + user_id: user.id, + token: tokenValue, + verified: false + }); + if (!verificationToken) { + res.statusCode = 404; + return res.json({ msg: "Couldn't create Verification Token" }); + } + let url = config.default.lde.url + '/verify'; + let text = `Olá, ${user.name}, seja bem vindo/a ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${tokenValue}`; + // Send confirmation email + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Confirme seu cadastro - Laboratório de Dados Educacionais", + text + } + email(mailOptions, (err, info) => { + if (err) { + log.error(err); + res.json({ msg: 'Message not delivered, user created but not confirmed' }); + } + if (info) { + log.info(`Message ${info.messageId} sent: ${info.response}`); + log.info(`Usuário ${user.email} foi criado`); + } + res.json({ msg: 'User created' }); + }); + } +}); + +pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + let user = await User.findByPk(req.params.id).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + }) + if (!user) { + res.statusCode = 404; + return next({ + err: { + message: 'Usuário não encontrado' + } + }); + } + + user.email = req.body.email || user.email; + user.name = req.body.name || user.name; + user.nickname = req.body.nickname || user.nickname || user.name; + user.cep = req.body.cep || user.cep; + user.complement = req.body.complement || user.complement; + user.address = req.body.address || user.address; + user.phone = req.body.phone || user.phone; + user.schooling = req.body.schooling || user.schooling; + user.course = req.body.course || user.course; + user.segment = req.body.segment || user.segment; + user.role = req.body.role || user.role; + user.institutionName = req.body.institutionName || user.institutionName; + user.state = req.body.state || user.state; + user.city = req.body.city || user.city; + user.receiveEmails = req.body.receiveEmails || user.receiveEmails; + user.citesegment = req.body.citesegment || user.citesegment; + user.citerole = req.body.citerole || user.citerole; + + + + if ((req.body.password) && (req.body.newpassword)) { + if (req.body.password != req.body.newpassword) { + if (user.checkPassword(user, req.body.password)) { + await user.update({password:req.body.newpassword}); + } + else { + res.statusCode = 500; + return res.json({ + error: { + message: 'A senha atual está incorreta' + } + }); + } + } else { + res.statusCode = 500; + return res.json({ + error: { + message: 'A nova senha é a mesma da senha atual' + } + }); + } + } + + user.save().catch(err => { + if (err) { + log.error(err); + return next({ message: 'Erro ao atualizar usuário' }); + }}) + let u = user.toJSON(); + delete u.hashed_password; + delete u.salt; + delete u.password; + res.json({ user: u }); + +}); + + +pubApp.get('/reset/password', async (req, res, next) => { + let emailAddress = req.query.email; + let user = await User.findOne({ where: { email: emailAddress } }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); + res.statusCode = 400; + return res.json({ err, errors }); + // handle error; + }); + if (!user) { + res.statusCode = 404; + res.json({ msg: "O usuário não está cadastrado" }); + } + else { + let tokenValue = uuid.v4(); + const rt = await ResetToken.create({ + user_id: user.id, + token: tokenValue, + reset: false + }); + if (!rt) { + res.statusCode = 404; + return res.json({ msg: "Couldn't create Reset Password Token" }); + } + let url = config.default.lde.url + '/reset-password'; + let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${tokenValue}`; + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Redefinição de Senha - Laboratório de Dados Educacionais", + text + } + console.log(mailOptions); + email(mailOptions, (err, info) => { + if (err) { + console.log(err); + log.error(err); + res.json({ msg: 'Undelivered Reset Password Mail' }); + } + log.info(`Message ${info.messageId} sent: ${info.response}`); + res.json({ msg: 'Reset Password Mail Successfully Delivered' }); + }); + } +}); + +module.exports = pubApp; diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index d02edd84..eedf07b5 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -148,7 +148,8 @@ userApp.post('/', async (req, res, next) => { origin: req.body.origin, citesegment: req.body.citesegment, citerole: req.body.citerole, - admin: false + admin: false, + role_id: 0 }).catch(function (err) { log.error(err); let errors = []; -- GitLab From e0ecd70789841eca4fbcfeeca6760561081af1fb Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Fri, 26 May 2023 11:48:36 -0300 Subject: [PATCH 029/123] [FIX] ID Type --- src/libs/models/permission.js | 16 +++- src/libs/models/publication.js | 15 ++- src/libs/models/userPublication.js | 2 +- src/libs/routes_v1/publication.js | 144 ++++++++++++++--------------- 4 files changed, 98 insertions(+), 79 deletions(-) diff --git a/src/libs/models/permission.js b/src/libs/models/permission.js index 917b5197..9d827d30 100644 --- a/src/libs/models/permission.js +++ b/src/libs/models/permission.js @@ -5,7 +5,7 @@ const Role = require(`${libs}/models/role`); var Permission = db.define("PermissionRole",{ id:{ - type: Sequelize.INTEGER, + type: Sequelize.STRING, allowNull:false, unique: true, primaryKey: true @@ -21,5 +21,19 @@ var Permission = db.define("PermissionRole",{ }, {timestamps: false}); +Permission.generateObjectId = function(){ + var timestamp = (new Date().getTime() / 1000 | 0).toString(16); + return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function() { + return (Math.random() * 16 | 0).toString(16); + }).toLowerCase(); +} + +const setObjectId = permission => { + permission.id = Permission.generateObjectId() +}; + +Permission.beforeCreate(setObjectId); + + module.exports = PermissionRole; diff --git a/src/libs/models/publication.js b/src/libs/models/publication.js index 03b3f0f4..1b19ceb7 100644 --- a/src/libs/models/publication.js +++ b/src/libs/models/publication.js @@ -4,7 +4,7 @@ const libs = `${process.cwd()}/libs`; var Publication = db.define("Publication",{ id:{ - type: Sequelize.INTEGER, + type: Sequelize.STRING, allowNull:false, unique: true, primaryKey: true @@ -54,4 +54,17 @@ var Publication = db.define("Publication",{ }, {timestamps: false}); +Publication.generateObjectId = function(){ + var timestamp = (new Date().getTime() / 1000 | 0).toString(16); + return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function() { + return (Math.random() * 16 | 0).toString(16); + }).toLowerCase(); +} + +const setObjectId = pb => { + pb.id = Publication.generateObjectId() +}; + +Publication.beforeCreate(setObjectId); + module.exports = Publication; \ No newline at end of file diff --git a/src/libs/models/userPublication.js b/src/libs/models/userPublication.js index 43417ffe..654dd3c3 100644 --- a/src/libs/models/userPublication.js +++ b/src/libs/models/userPublication.js @@ -16,7 +16,7 @@ var userPublication = db.define("userPublication",{ allowNull:false, }, publication_id:{ - type: Sequelize.INTEGER, + type: Sequelize.STRING, allowNull:false } }, diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index dc6d6471..442af7ec 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -48,18 +48,15 @@ pubApp.get('/', passport.authenticate('bearer', { session: false }), async (req, publications.push(pb); } next(); -}, response('user')); +}, response('publications')); pubApp.get('/:id', (req, res, next) => { - UserPublication.findByPk(req.params.id).then((user) => { - if (!user) { + Publication.findByPk(req.params.id).then((pb) => { + if (!pb) { res.statusCode = 404; - res.json({ msg: "O usuário não está cadastrado" }); + res.json({ msg: "A publicação não está cadastrada" }); } else { - let u = user.toJSON(); - delete u.hashed_password; - delete u.salt; - req.result = u; + req.result = pb.toJSON(); next(); } }).catch(function (err) { @@ -68,78 +65,73 @@ pubApp.get('/:id', (req, res, next) => { }); }, response('publication')); -pubApp.post('/', async (req, res, next) => { - if (typeof req.body.password === 'undefined' || !req.body.password) { +pubApp.post('/', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + let pb = await Publication.create({ + id: 0, + email: req.body.email, + password: req.body.password, + hashed_password: 0, + salt: 0, + name: req.body.name, + nickname: req.body.nickname, + cpf: req.body.cpf, + cep: req.body.cep, + complement: req.body.complement, + address: req.body.address, + phone: req.body.phone, + schooling: req.body.schooling, + course: req.body.course, + segment: req.body.segment, + role: req.body.role, + institution_name: req.body.institutionName, + state: req.body.state, + city: req.body.city, + receiveEmails: false || req.body.receiveEmails, + origin: req.body.origin, + citesegment: req.body.citesegment, + citerole: req.body.citerole, + admin: false, + role_id: 0 + }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); res.statusCode = 400; - return res.json({ errors: ["O campo senha é obrigatório"] }); - } else { - let user = await User.create({ - id: 0, - email: req.body.email, - password: req.body.password, - hashed_password: 0, - salt: 0, - name: req.body.name, - nickname: req.body.nickname, - cpf: req.body.cpf, - cep: req.body.cep, - complement: req.body.complement, - address: req.body.address, - phone: req.body.phone, - schooling: req.body.schooling, - course: req.body.course, - segment: req.body.segment, - role: req.body.role, - institution_name: req.body.institutionName, - state: req.body.state, - city: req.body.city, - receiveEmails: false || req.body.receiveEmails, - origin: req.body.origin, - citesegment: req.body.citesegment, - citerole: req.body.citerole, - admin: false, - role_id: 0 - }).catch(function (err) { + return res.json({ err, errors }); + // handle error; + }); + let tokenValue = uuid.v4(); + const verificationToken = VerificationToken.create({ + user_id: user.id, + token: tokenValue, + verified: false + }); + if (!verificationToken) { + res.statusCode = 404; + return res.json({ msg: "Couldn't create Verification Token" }); + } + let url = config.default.lde.url + '/verify'; + let text = `Olá, ${user.name}, seja bem vindo/a ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${tokenValue}`; + // Send confirmation email + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Confirme seu cadastro - Laboratório de Dados Educacionais", + text + } + email(mailOptions, (err, info) => { + if (err) { log.error(err); - let errors = []; - for (let errName in err.errors) { - errors.push(err.errors[errName].message); - } - log.error(errors); - res.statusCode = 400; - return res.json({ err, errors }); - // handle error; - }); - let tokenValue = uuid.v4(); - const verificationToken = VerificationToken.create({ - user_id: user.id, - token: tokenValue, - verified: false - }); - if (!verificationToken) { - res.statusCode = 404; - return res.json({ msg: "Couldn't create Verification Token" }); + res.json({ msg: 'Message not delivered, user created but not confirmed' }); } - let url = config.default.lde.url + '/verify'; - let text = `Olá, ${user.name}, seja bem vindo/a ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${tokenValue}`; - // Send confirmation email - let mailOptions = { - to: `"${user.name} <${user.email}>"`, - subject: "Confirme seu cadastro - Laboratório de Dados Educacionais", - text + if (info) { + log.info(`Message ${info.messageId} sent: ${info.response}`); + log.info(`Usuário ${user.email} foi criado`); } - email(mailOptions, (err, info) => { - if (err) { - log.error(err); - res.json({ msg: 'Message not delivered, user created but not confirmed' }); - } - if (info) { - log.info(`Message ${info.messageId} sent: ${info.response}`); - log.info(`Usuário ${user.email} foi criado`); - } - res.json({ msg: 'User created' }); - }); - } + res.json({ msg: 'User created' }); + }); }); pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { -- GitLab From 63ee99422fcf801a928913e2fb00f772728fe887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Wed, 31 May 2023 09:43:09 -0300 Subject: [PATCH 030/123] Add changes to classroom count v2 --- src/libs/routes_v2/aux | 1 - src/libs/routes_v2/classroomCount.js | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 src/libs/routes_v2/aux diff --git a/src/libs/routes_v2/aux b/src/libs/routes_v2/aux deleted file mode 100644 index c0b4cc5f..00000000 --- a/src/libs/routes_v2/aux +++ /dev/null @@ -1 +0,0 @@ -SELECT COUNT(*) AS "total", simcaq_matricula_agregada.ano_censo AS "year", estado.nome AS "state_name", estado.id AS "state_id", municipio.nome AS "city_name", municipio.id AS "city_id", simcaq_matricula_agregada.etapa_resumida AS "education_level_short_id", simcaq_matricula_agregada.tempo_integral AS "integral_time_id" FROM simcaq_matricula_agregada INNER JOIN estado ON (simcaq_matricula_agregada.estado_id=estado.id) INNER JOIN municipio ON (simcaq_matricula_agregada.municipio_id=municipio.id) WHERE (simcaq_matricula_agregada.ano_censo >= 2021 ) AND (simcaq_matricula_agregada.ano_censo <= 2021 ) GROUP BY simcaq_matricula_agregada.ano_censo, estado.nome, estado.id, municipio.nome, municipio.id, simcaq_matricula_agregada.etapa_resumida, simcaq_matricula_agregada.tempo_integral ORDER BY simcaq_matricula_agregada.ano_censo ASC, estado.nome ASC, estado.id ASC, municipio.nome ASC, municipio.id ASC, simcaq_matricula_agregada.etapa_resumida ASC, simcaq_matricula_agregada.tempo_integral ASC diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 34c8b33f..fbac836a 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -250,9 +250,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { .field('sum(noite_total)', 'total_night') .field("'Brasil'", 'name') .field('simcaq_matricula_por_localizacao.ano_censo', 'year') + .field('simcaq_matricula_por_localizacao.serie_ano_id', 'school_year_id') .from('simcaq_matricula_por_localizacao') .where('simcaq_matricula_por_localizacao.serie_ano_id < 15') .group('simcaq_matricula_por_localizacao.ano_censo') + .group('simcaq_matricula_por_localizacao.serie_ano_id') .order('simcaq_matricula_por_localizacao.ano_censo') next(); @@ -387,7 +389,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.integral_time = {} for (let i = 0; i < integral_time_result.length; ++i){ // Se cidade não foi criada, cria - let integral_time = integral_time_result[i]; + let integral_time = integral_time_result[i] let code = '' + integral_time.year + integral_time.city_id if (req.dims.school) code = code + integral_time.school_id @@ -587,13 +589,12 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let enrollmentEducationLevel = req.educationSchoolYear[enrollment.school_year_id]; // Se não há um número de alunos por turna para a etapa de ensino, ignoramos a entrada - if(enrollmentEducationLevel.numberStudentClass == null) continue; + if(typeof enrollmentEducationLevel.numberStudentClass == 'undefined' || enrollmentEducationLevel.numberStudentClass == null) continue; // Adiciona nÃvel de educação para municÃpio/escola let educationLevel = null; if(!educationLevelSet.has(enrollmentEducationLevel.id)) { // cria e insere ordenadamente novo education level educationLevelSet.add(enrollmentEducationLevel.id); - let itHash = '' + enrollment.year + enrollment.city_id if (req.dims.school) itHash += enrollment.school_id @@ -660,7 +661,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let currentSchoolYear = null; if(enrollmentEducationLevel.id == 1){ let schoolYearHash = '' + enrollment.year + enrollment.city_id + enrollment.location_id + enrollment.school_year_id; - if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.shcool_id + if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.school_id if(schoolYearSet.has(schoolYearHash)) { // Busca a série escolar let k = 0; -- GitLab From 0e82c90bd8ebbafc9052aaa8390d617d33ad32d9 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 31 May 2023 10:23:06 -0300 Subject: [PATCH 031/123] [ADD] Publication POST --- src/libs/models/publication.js | 5 ++ src/libs/routes_v1/api.js | 5 ++ src/libs/routes_v1/publication.js | 93 +++++++++---------------------- 3 files changed, 36 insertions(+), 67 deletions(-) diff --git a/src/libs/models/publication.js b/src/libs/models/publication.js index 1b19ceb7..ec3ed5c0 100644 --- a/src/libs/models/publication.js +++ b/src/libs/models/publication.js @@ -49,6 +49,11 @@ var Publication = db.define("Publication",{ type:Sequelize.BOOLEAN, allowNull:false, defaultValue: true + }, + is_headline:{ + type:Sequelize.BOOLEAN, + allowNull: false, + defaultValue: true } }, diff --git a/src/libs/routes_v1/api.js b/src/libs/routes_v1/api.js index 41fe392c..50941a94 100644 --- a/src/libs/routes_v1/api.js +++ b/src/libs/routes_v1/api.js @@ -137,6 +137,8 @@ const message = require(`${libs}/routes_v1/message`); const courseStudents = require(`${libs}/routes_v1/courseStudents`); +const publication = require(`${libs}/routes_v1/publication`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v1 is running' }); }); @@ -197,4 +199,7 @@ api.use('/universityLocalOffer', universityLocalOffer); api.use('/message', message); api.use('/course_students', courseStudents); +//Publication +api.use('/publication', publication); + module.exports = api; diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 442af7ec..dcb02ce5 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -30,21 +30,21 @@ function emailSyntax(email) { } pubApp.get('/', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let up = await UserPublication.findAll({where:{user_id:req.user.id}}).catch(function(err){ - if(err){ - log.error(err); - return next(err); + let up = await UserPublication.findAll({ where: { user_id: req.user.id } }).catch(function (err) { + if (err) { + log.error(err); + return next(err); } }); console.log(up); let publications = []; - for(let _id in up.publication_id){ - let pb = await Publication.findByPk(_id).catch(function(err){ - if(err){ - log.error(err); - return next(err); - } - }); + for (let _id in up.publication_id) { + let pb = await Publication.findByPk(_id).catch(function (err) { + if (err) { + log.error(err); + return next(err); + } + }); publications.push(pb); } next(); @@ -68,30 +68,15 @@ pubApp.get('/:id', (req, res, next) => { pubApp.post('/', passport.authenticate('bearer', { session: false }), async (req, res, next) => { let pb = await Publication.create({ id: 0, - email: req.body.email, - password: req.body.password, - hashed_password: 0, - salt: 0, - name: req.body.name, - nickname: req.body.nickname, - cpf: req.body.cpf, - cep: req.body.cep, - complement: req.body.complement, - address: req.body.address, - phone: req.body.phone, - schooling: req.body.schooling, - course: req.body.course, - segment: req.body.segment, - role: req.body.role, - institution_name: req.body.institutionName, - state: req.body.state, - city: req.body.city, - receiveEmails: false || req.body.receiveEmails, - origin: req.body.origin, - citesegment: req.body.citesegment, - citerole: req.body.citerole, - admin: false, - role_id: 0 + filter: req.body.categoria, + title: req.body.title, + authors: req.body.autores, + organization: req.body.organizacao, + year: req.body.ano, + text: req.body.texto, + link: req.body.link, + upload: req.body.upload, + is_homepage: req.body.homepage }).catch(function (err) { log.error(err); let errors = []; @@ -103,35 +88,8 @@ pubApp.post('/', passport.authenticate('bearer', { session: false }), async (req return res.json({ err, errors }); // handle error; }); - let tokenValue = uuid.v4(); - const verificationToken = VerificationToken.create({ - user_id: user.id, - token: tokenValue, - verified: false - }); - if (!verificationToken) { - res.statusCode = 404; - return res.json({ msg: "Couldn't create Verification Token" }); - } - let url = config.default.lde.url + '/verify'; - let text = `Olá, ${user.name}, seja bem vindo/a ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${tokenValue}`; - // Send confirmation email - let mailOptions = { - to: `"${user.name} <${user.email}>"`, - subject: "Confirme seu cadastro - Laboratório de Dados Educacionais", - text - } - email(mailOptions, (err, info) => { - if (err) { - log.error(err); - res.json({ msg: 'Message not delivered, user created but not confirmed' }); - } - if (info) { - log.info(`Message ${info.messageId} sent: ${info.response}`); - log.info(`Usuário ${user.email} foi criado`); - } - res.json({ msg: 'User created' }); - }); + console.log(pb); + next(); }); pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { @@ -173,8 +131,8 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (r if ((req.body.password) && (req.body.newpassword)) { if (req.body.password != req.body.newpassword) { if (user.checkPassword(user, req.body.password)) { - await user.update({password:req.body.newpassword}); - } + await user.update({ password: req.body.newpassword }); + } else { res.statusCode = 500; return res.json({ @@ -197,7 +155,8 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (r if (err) { log.error(err); return next({ message: 'Erro ao atualizar usuário' }); - }}) + } + }) let u = user.toJSON(); delete u.hashed_password; delete u.salt; -- GitLab From 07be2051441a3cea3d3d99625dd3044d54e3c00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Wed, 31 May 2023 11:36:17 -0300 Subject: [PATCH 032/123] update classroomcount v2 --- src/libs/routes_v2/classroomCount.js | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index fbac836a..b7a0ec7e 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -66,21 +66,6 @@ rqf.addField({ foreign: 'municipio_id', foreignTable: '@' } -}, 'dims').addValueToField({ - name: 'cityTeacher', - table: 'municipio', - tableField: ['nome', 'id'], - resultField: ['city_name', 'city_id'], - where: { - relation: '=', - type: 'integer', - field: 'id' - }, - join: { - primary: 'id', - foreign: 'escola_cidade_id', - foreignTable: '@' - } }, 'dims').addValueToField({ name: 'state', table: 'estado', @@ -354,7 +339,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.teacherCalc = true; } - req.dims.cityTeacher = true; + req.dims.city = true; req.dims.formation_level = true; req.sql.field('SUM(simcaq_docente_agregada.num_docentes)', 'total') .field("'Brasil'", 'name') @@ -530,11 +515,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { currentClassroomObj = obj; var id_attribute = req.dims.school ? "school_id" : "city_id" - var old_ti = ti; - while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) // match da tabela de professores. + while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) { // match da tabela de professores. ti++; - + } + if (ti === req.teacher.length) { while (classroom[id_attribute] === enrollments[j][id_attribute]) enrollments.splice(j, 1) @@ -1137,6 +1122,8 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }) } + console.log('fim') + next(); }, response('classroom_count')); -- GitLab From 7fd2579bd3e2e1611a67f24ef5f9cf2b3aee2a4d Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 31 May 2023 11:45:35 -0300 Subject: [PATCH 033/123] [ADD] Routes --- src/libs/models/publication.js | 2 +- src/libs/routes_v1/publication.js | 160 +++++++++++------------------- 2 files changed, 57 insertions(+), 105 deletions(-) diff --git a/src/libs/models/publication.js b/src/libs/models/publication.js index ec3ed5c0..5b324e72 100644 --- a/src/libs/models/publication.js +++ b/src/libs/models/publication.js @@ -53,7 +53,7 @@ var Publication = db.define("Publication",{ is_headline:{ type:Sequelize.BOOLEAN, allowNull: false, - defaultValue: true + defaultValue: false } }, diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index dcb02ce5..2a439104 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -76,6 +76,7 @@ pubApp.post('/', passport.authenticate('bearer', { session: false }), async (req text: req.body.texto, link: req.body.link, upload: req.body.upload, + is_draft: false, is_homepage: req.body.homepage }).catch(function (err) { log.error(err); @@ -88,130 +89,81 @@ pubApp.post('/', passport.authenticate('bearer', { session: false }), async (req return res.json({ err, errors }); // handle error; }); - console.log(pb); + let up = await Publication.create({ + user_id: req.user.id, + publication_id: pb.id + }) + req.result = pb.toJSON(); + next(); +}); + +pubApp.post('/rascunho', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + let pb = await Publication.create({ + id: 0, + filter: req.body.categoria, + title: req.body.title, + authors: req.body.autores, + organization: req.body.organizacao, + year: req.body.ano, + text: req.body.texto, + link: req.body.link, + upload: req.body.upload, + is_draft: true, + is_homepage: req.body.homepage + }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); + res.statusCode = 400; + return res.json({ err, errors }); + // handle error; + }); + let up = await Publication.create({ + user_id: req.user.id, + publication_id: pb.id + }) + req.result = pb.toJSON(); + next(); }); pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let user = await User.findByPk(req.params.id).catch(function (err) { + let pb = await Publication.findByPk(req.params.id).catch(function (err) { if (err) { log.error(err); return next({ err }); } }) - if (!user) { + if (!pb) { res.statusCode = 404; return next({ err: { - message: 'Usuário não encontrado' + message: 'Publicação não encontrada' } }); } - - user.email = req.body.email || user.email; - user.name = req.body.name || user.name; - user.nickname = req.body.nickname || user.nickname || user.name; - user.cep = req.body.cep || user.cep; - user.complement = req.body.complement || user.complement; - user.address = req.body.address || user.address; - user.phone = req.body.phone || user.phone; - user.schooling = req.body.schooling || user.schooling; - user.course = req.body.course || user.course; - user.segment = req.body.segment || user.segment; - user.role = req.body.role || user.role; - user.institutionName = req.body.institutionName || user.institutionName; - user.state = req.body.state || user.state; - user.city = req.body.city || user.city; - user.receiveEmails = req.body.receiveEmails || user.receiveEmails; - user.citesegment = req.body.citesegment || user.citesegment; - user.citerole = req.body.citerole || user.citerole; - - - - if ((req.body.password) && (req.body.newpassword)) { - if (req.body.password != req.body.newpassword) { - if (user.checkPassword(user, req.body.password)) { - await user.update({ password: req.body.newpassword }); - } - else { - res.statusCode = 500; - return res.json({ - error: { - message: 'A senha atual está incorreta' - } - }); - } - } else { - res.statusCode = 500; - return res.json({ - error: { - message: 'A nova senha é a mesma da senha atual' - } - }); - } - } - - user.save().catch(err => { + pb.filter = req.body.categoria || pb.filter; + pb.title = req.body.title || pb.title; + pb.authors = req.body.autores || pb.authors; + pb.organization= req.body.organizacao || pb.organization; + pb.year= req.body.ano || pb.year; + pb.text= req.body.texto || pb.text; + pb.link= req.body.link || pb.link; + pb.upload= req.body.upload || pb.upload; + pb.is_homepage= req.body.homepage || pb.is_homepage; + + pb.save().catch(err => { if (err) { log.error(err); - return next({ message: 'Erro ao atualizar usuário' }); + return next({ message: 'Erro ao atualizar publicacao' }); } }) - let u = user.toJSON(); - delete u.hashed_password; - delete u.salt; - delete u.password; - res.json({ user: u }); - -}); - + let p = p.toJSON(); + res.json({ publication: p }); -pubApp.get('/reset/password', async (req, res, next) => { - let emailAddress = req.query.email; - let user = await User.findOne({ where: { email: emailAddress } }).catch(function (err) { - log.error(err); - let errors = []; - for (let errName in err.errors) { - errors.push(err.errors[errName].message); - } - log.error(errors); - res.statusCode = 400; - return res.json({ err, errors }); - // handle error; - }); - if (!user) { - res.statusCode = 404; - res.json({ msg: "O usuário não está cadastrado" }); - } - else { - let tokenValue = uuid.v4(); - const rt = await ResetToken.create({ - user_id: user.id, - token: tokenValue, - reset: false - }); - if (!rt) { - res.statusCode = 404; - return res.json({ msg: "Couldn't create Reset Password Token" }); - } - let url = config.default.lde.url + '/reset-password'; - let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${tokenValue}`; - let mailOptions = { - to: `"${user.name} <${user.email}>"`, - subject: "Redefinição de Senha - Laboratório de Dados Educacionais", - text - } - console.log(mailOptions); - email(mailOptions, (err, info) => { - if (err) { - console.log(err); - log.error(err); - res.json({ msg: 'Undelivered Reset Password Mail' }); - } - log.info(`Message ${info.messageId} sent: ${info.response}`); - res.json({ msg: 'Reset Password Mail Successfully Delivered' }); - }); - } }); module.exports = pubApp; -- GitLab From 8adeedb4a28b6e64dfa0894842247914193c6ec5 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 1 Jun 2023 10:31:14 -0300 Subject: [PATCH 034/123] [FIX] Publication & ResetToken --- src/libs/routes_v1/publication.js | 14 ++++++++++---- src/libs/routes_v1/resetToken.js | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 2a439104..46b0574d 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -8,14 +8,10 @@ const config = require(`${libs}/config`); const log = require(`${libs}/log`)(module); -const VerificationToken = require(`${libs}/models/verificationToken`); - const Publication = require(`${libs}/models/publication`); const UserPublication = require(`${libs}/models/userPublication`); -const ResetToken = require(`${libs}/models/resetToken`); - const response = require(`${libs}/middlewares/response`); const email = require(`${libs}/middlewares/email`); @@ -166,4 +162,14 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (r }); +pubApp.delete('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + await Publication.destroy({where:{id:req.params.id}}).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } +}); + return next({ msg: 'Publication Deleted', status: 200 }); +}); + module.exports = pubApp; diff --git a/src/libs/routes_v1/resetToken.js b/src/libs/routes_v1/resetToken.js index 7c758410..579bec0b 100644 --- a/src/libs/routes_v1/resetToken.js +++ b/src/libs/routes_v1/resetToken.js @@ -24,7 +24,7 @@ resetTokenApp.get('/:token', async (req, res, next) => { } if (rToken.hasExpired()) { res.statusCode = 410; - await ResetToken.remove({where:{ token: token}}).catch(function (err) { + await ResetToken.destroy({where:{ token: token}}).catch(function (err) { if (err) { log.error(err); return next({ err }); -- GitLab From 8630790d7552c22f08cb5444531588271af9b4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 2 Jun 2023 11:02:59 -0300 Subject: [PATCH 035/123] rewrite queries for classroom_count --- src/libs/routes_v2/classroomCount.js | 94 +++++++++++++++++++++++++--- src/libs/routes_v2/infrastructure.js | 29 +++++---- 2 files changed, 102 insertions(+), 21 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index b7a0ec7e..4e5c0dbd 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -228,9 +228,32 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.state = true; req.dims.city = true; - req.dims.school_year = true; + //req.dims.school_year = true; req.dims.location = true; + /* + select + sum(dia_total), + sum(noite_total), + 'Brasil' as name, + ano_censo, + serie_ano_id, + estado_id, + municipio_id, + localizacao_id + from + simcaq_matricula_por_localizacao + where + serie_ano_id < 15 + group by + name, + ano_censo, + serie_ano_id, + estado_id, + municipio_id, + localizacao_id + */ + req.sql.field('sum(dia_total)', 'total_day') .field('sum(noite_total)', 'total_night') .field("'Brasil'", 'name') @@ -277,19 +300,42 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { next(); }, rqf.parse(), (req, res, next) => { + /* + select + sum(escola_agregada.num_salas_utilizadas) as soma, + 'Brasil' as name, + ano_censo, + estado_id, + municipio_id, + localizacao_id, + local_func_predio_escolar + from escola_agregada + where + situacao_de_funcionamento = 1 and + dependencia_adm_id IN (2, 3) and + escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1 + group by + name, + ano_censo, + estado_id, + municipio_id, + localizacao_id, + local_func_predio_escolar + */ + req.dims.state = true; req.dims.city = true; req.dims.location = true; req.dims.school_building = true; - - req.sql.field('SUM(escola_agregada.qtde_salas_utilizadas_dentro)', 'total') + + req.sql.field('SUM(escola_agregada.num_salas_utilizadas)', 'total') .field("'Brasil'", 'name') .field('escola_agregada.ano_censo', 'year') .from('escola_agregada') .group('escola_agregada.ano_censo') .order('escola_agregada.ano_censo') - .where('escola_agregada.situacao_funcionamento_pareada = 1') - .where('escola_agregada.dependencia_adm_id < 4') + .where('escola_agregada.situacao_de_funcionamento = 1') + .where('escola_agregada.dependencia_adm_id IN (2,3)') .where('escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1'); next(); @@ -339,11 +385,22 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.teacherCalc = true; } - req.dims.city = true; - req.dims.formation_level = true; - req.sql.field('SUM(simcaq_docente_agregada.num_docentes)', 'total') + /* + select num_docentes, + 'Brasil' as name, + ano_censo, + escola_estado_id, + municipio_id + from simcaq_docente_agregada + */ + + //req.dims.city = true; + //req.dims.state = true; + req.sql.field('simcaq_docente_agregada.num_docentes', 'total') .field("'Brasil'", 'name') .field('simcaq_docente_agregada.ano_censo', 'year') + .field('escola_estado_id', 'state_id') + .field('municipio_id', 'city_id') .from('simcaq_docente_agregada') .group('simcaq_docente_agregada.ano_censo') .order('simcaq_docente_agregada.ano_censo'); @@ -357,16 +414,33 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.resetSql(); next(); }, rqf.parse(), (req, res, next) => { + /* + select + SUM(num_matriculas) as num_matriculas, + ano_censo, + estado_id, + municipio_id, + etapa_resumida, + tempo_integral + from simcaq_matricula_agregada + group by + ano_censo, + estado_id, + municipio_id, + etapa_resumida, + tempo_integral + */ req.dims.state = true; req.dims.city = true; req.dims.education_level_short = true; //req.dims.integral_time = true; - req.sql.field('COUNT(*)', 'total') + req.sql.field('SUM(num_matriculas)', 'total') .field('simcaq_matricula_agregada.ano_censo', 'year') + .field('simcaq_matricula_agregada.tempo_integral', 'integral_time') .from('simcaq_matricula_agregada') .group('simcaq_matricula_agregada.ano_censo') + .group('simcaq_matricula_agregada.tempo_integral') .order('simcaq_matricula_agregada.ano_censo'); - //.where('((simcaq_matricula_agregada.tipo<=3 OR simcaq_matricula_agregada.tipo IS NULL) AND (simcaq_matricula_agregada.tipo_atendimento_turma IS NULL OR simcaq_matricula_agregada.tipo_atendimento_turma <= 2) AND simcaq_matricula_agregada.turma_turno_id <> 99)'); next(); }, rqf.build() ,query, id2str.transform(), (req, res, next) => { // constrói objeto de tempo integral e calcula diagnósticos diff --git a/src/libs/routes_v2/infrastructure.js b/src/libs/routes_v2/infrastructure.js index cc4c5931..01cc9264 100644 --- a/src/libs/routes_v2/infrastructure.js +++ b/src/libs/routes_v2/infrastructure.js @@ -335,7 +335,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Laboratório de informática let allInfLab = allSchools.clone(); allInfLab.where('escola_agregada.func_predio_escolar = 1') - .where('escola_agregada.reg_fund_ai = 1 OR escola_agregada.reg_fund_af = 1 OR escola_agregada.reg_medio_medio = 1 OR escola_agregada.reg_medio_integrado = 1 OR escola_agregada.reg_medio_normal = 1 OR escola_agregada.ensino_eja_fund = 1 OR escola_agregada.ensino_eja_medio = 1 OR escola_agregada.ensino_eja_prof = 1'); + .where('etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1'); req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1; let haveInfLab = allInfLab.clone(); @@ -347,13 +347,13 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1; let haveScienceLab = allScienceLab.clone(); - haveScienceLab.where('escola_agregada.lab_ciencias = 1'); + haveScienceLab.where('escola_agregada.lab_ciencias = 1 AND (etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1; // Parque infantil let allKidsPark = allSchools.clone(); allKidsPark.where('escola_agregada.func_predio_escolar = 1') - .where('escola_agregada.reg_infantil_creche = 1 OR escola_agregada.reg_infantil_preescola = 1 OR escola_agregada.reg_fund_ai = 1 OR escola_agregada.esp_infantil_creche = 1 OR escola_agregada.esp_exclusiva_creche = 1 OR escola_agregada.reg_esp_exclusiva_fund_ai = 1'); + .where('escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1'); req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1; let haveKidsPark = allKidsPark.clone(); @@ -372,27 +372,27 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Quadra let allSportsCourt = allScienceLab.clone(); - allSportsCourt.where('escola_agregada.localizacao_id = 1'); + allSportsCourt.where('escola_agregada.localizacao_id = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1; let haveSportsCourt = allSportsCourt.clone(); - haveSportsCourt.where('escola_agregada.quadra_esportes = 1'); + haveSportsCourt.where('escola_agregada.quadra_esportes = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1; // Quadra coberta req.queryIndex.allCoveredSportsCourt = req.queryIndex.allSportsCourt; let haveCoveredSportsCourt = allSportsCourt.clone(); - haveCoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 1'); + haveCoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveCoveredSportsCourt = req.querySet.push(haveCoveredSportsCourt) - 1; // Quadra Descoberta let allUncoveredSportsCourt = allSportsCourt.clone(); - allUncoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 0'); + allUncoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 0 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.allUncoveredSportsCourt = req.querySet.push(allUncoveredSportsCourt) - 1; let haveUncoveredSportsCourt = allUncoveredSportsCourt.clone(); - haveUncoveredSportsCourt.where('escola_agregada.quadra_esportes_descoberta = 1'); + haveUncoveredSportsCourt.where('escola_agregada.quadra_esportes_descoberta = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveUncoveredSportsCourt = req.querySet.push(haveUncoveredSportsCourt) - 1; // Sala de direção @@ -445,14 +445,14 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInternet = req.queryIndex.allLibrariesReadingRoom; let haveInternet = allLibrariesReadingRoom.clone(); - haveInternet.where('escola_agregada.internet = 1'); + haveInternet.where('escola_agregada.internet = 1 AND localizacao_id = 2'); req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1; // Internet banda larga req.queryIndex.allBroadbandInternet = req.queryIndex.allLibraries; let haveBroadbandInternet = allLibraries.clone(); - haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1'); + haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1 AND localizacao_id = 1'); req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1; // Banheiro dentro do prédio @@ -466,7 +466,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInsideKidsBathroom = req.queryIndex.allKidsPark; let haveInsideKidsBathroom = allKidsPark.clone(); - haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1'); + haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1 AND (escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1) AND localizacao_id IN (1, 2)'); req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1; // Fornecimento de energia @@ -518,6 +518,13 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { haveAdaptedBuilding.where('escola_agregada.dependencias_pne = 1'); req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1; + // Adicionar pátio + /* + patio = 1 ou 2 -- patio existe, 1 -- a ser coberto, 2 -- é coberto + func_predio_escolar = 1 + localizacao_id = 1 ou 2 + */ + next(); }, multiQuery, (req, res, next) => { // Faz o matching entre os resultados -- GitLab From 522e92ece0bc9a47a6d6df8916063a8f3647623c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 5 Jun 2023 10:20:18 -0300 Subject: [PATCH 036/123] classroom count v2 working but does not return data --- src/libs/routes_v2/classroomCount.js | 41 +++++----------------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 4e5c0dbd..be2c8645 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -231,28 +231,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { //req.dims.school_year = true; req.dims.location = true; - /* - select - sum(dia_total), - sum(noite_total), - 'Brasil' as name, - ano_censo, - serie_ano_id, - estado_id, - municipio_id, - localizacao_id - from - simcaq_matricula_por_localizacao - where - serie_ano_id < 15 - group by - name, - ano_censo, - serie_ano_id, - estado_id, - municipio_id, - localizacao_id - */ + req.sql.field('sum(dia_total)', 'total_day') .field('sum(noite_total)', 'total_night') @@ -386,21 +365,19 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { } /* - select num_docentes, + select sum(num_docentes), 'Brasil' as name, ano_censo, - escola_estado_id, + estado_id, municipio_id from simcaq_docente_agregada */ - //req.dims.city = true; - //req.dims.state = true; - req.sql.field('simcaq_docente_agregada.num_docentes', 'total') + req.dims.city = true; + req.dims.state = true; + req.sql.field('SUM(simcaq_docente_agregada.num_docentes)', 'total') .field("'Brasil'", 'name') .field('simcaq_docente_agregada.ano_censo', 'year') - .field('escola_estado_id', 'state_id') - .field('municipio_id', 'city_id') .from('simcaq_docente_agregada') .group('simcaq_docente_agregada.ano_censo') .order('simcaq_docente_agregada.ano_censo'); @@ -433,13 +410,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.state = true; req.dims.city = true; req.dims.education_level_short = true; - //req.dims.integral_time = true; + req.dims.integral_time = true; req.sql.field('SUM(num_matriculas)', 'total') .field('simcaq_matricula_agregada.ano_censo', 'year') - .field('simcaq_matricula_agregada.tempo_integral', 'integral_time') .from('simcaq_matricula_agregada') .group('simcaq_matricula_agregada.ano_censo') - .group('simcaq_matricula_agregada.tempo_integral') .order('simcaq_matricula_agregada.ano_censo'); next(); }, rqf.build() ,query, id2str.transform(), (req, res, next) => { @@ -1196,8 +1171,6 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }) } - console.log('fim') - next(); }, response('classroom_count')); -- GitLab From 8c4cc3ca5060fb51752c2a7daf95b970bd6ba690 Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Mon, 5 Jun 2023 10:28:57 -0300 Subject: [PATCH 037/123] trying to use the old version of classroom count --- src/libs/routes_v2/classroomCount.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index be2c8645..ea649bbf 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -228,7 +228,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.state = true; req.dims.city = true; - //req.dims.school_year = true; + req.dims.school_year = true; req.dims.location = true; @@ -423,7 +423,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.integral_time = {} for (let i = 0; i < integral_time_result.length; ++i){ // Se cidade não foi criada, cria - let integral_time = integral_time_result[i] + let integral_time = integral_time_result[i]; let code = '' + integral_time.year + integral_time.city_id if (req.dims.school) code = code + integral_time.school_id @@ -440,6 +440,8 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { if (req.dims.school){ obj.school_id = integral_time.school_id obj.school_name = integral_time.school_name + obj.adm_dependency_id = integral_time.adm_dependency_id + obj.adm_dependency_name = integral_time.adm_dependency_name } req.integral_time[code] = obj currentCodeObj = obj; @@ -525,7 +527,9 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }; if (req.dims.school){ obj.school_id = classroom.school_id, - obj.school_name = classroom.school_name + obj.school_name = classroom.school_name, + obj.adm_dependency_id = classroom.adm_dependency_id, + obj.adm_dependency_name = classroom.adm_dependency_name } if (req.teacherCalc) obj.percentage_teacher_career = []; @@ -564,12 +568,13 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { currentClassroomObj = obj; var id_attribute = req.dims.school ? "school_id" : "city_id" + var old_ti = ti; - while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) { // match da tabela de professores. + while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) // match da tabela de professores. ti++; - } - + if (ti === req.teacher.length) { + console.log(classroom[id_attribute], "not found") while (classroom[id_attribute] === enrollments[j][id_attribute]) enrollments.splice(j, 1) ti = old_ti; @@ -623,12 +628,13 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let enrollmentEducationLevel = req.educationSchoolYear[enrollment.school_year_id]; // Se não há um número de alunos por turna para a etapa de ensino, ignoramos a entrada - if(typeof enrollmentEducationLevel.numberStudentClass == 'undefined' || enrollmentEducationLevel.numberStudentClass == null) continue; + if(enrollmentEducationLevel.numberStudentClass == null) continue; // Adiciona nÃvel de educação para municÃpio/escola let educationLevel = null; if(!educationLevelSet.has(enrollmentEducationLevel.id)) { // cria e insere ordenadamente novo education level educationLevelSet.add(enrollmentEducationLevel.id); + let itHash = '' + enrollment.year + enrollment.city_id if (req.dims.school) itHash += enrollment.school_id @@ -695,7 +701,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let currentSchoolYear = null; if(enrollmentEducationLevel.id == 1){ let schoolYearHash = '' + enrollment.year + enrollment.city_id + enrollment.location_id + enrollment.school_year_id; - if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.school_id + if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.shcool_id if(schoolYearSet.has(schoolYearHash)) { // Busca a série escolar let k = 0; -- GitLab From 03a18a3a3487436d690ace9c2a80c1aa5fc2a594 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 5 Jun 2023 11:36:46 -0300 Subject: [PATCH 038/123] [ADD] Integration with multer --- package.json | 1 + src/libs/middlewares/multer.config.js | 6 ++++ src/libs/models/file.js | 39 +++++++++++++++++++++++++ src/libs/routes_v1/file.controller.js | 41 +++++++++++++++++++++++++++ src/libs/routes_v1/publication.js | 40 ++++++++++++++------------ 5 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 src/libs/middlewares/multer.config.js create mode 100644 src/libs/models/file.js create mode 100644 src/libs/routes_v1/file.controller.js diff --git a/package.json b/package.json index 94ccf471..ee496631 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "mocha": "^3.5.3", "monetdb-pool": "0.0.8", "mongoose": "^4.13.17", + "multer": "^1.4.5-lts.1", "natives": "^1.1.6", "nconf": "^0.8.5", "node-uuid": "^1.4.8", diff --git a/src/libs/middlewares/multer.config.js b/src/libs/middlewares/multer.config.js new file mode 100644 index 00000000..d4c7263f --- /dev/null +++ b/src/libs/middlewares/multer.config.js @@ -0,0 +1,6 @@ +const multer = require('multer'); + +var storage = multer.memoryStorage() +var upload = multer({storage: storage}); + +module.exports = upload; diff --git a/src/libs/models/file.js b/src/libs/models/file.js new file mode 100644 index 00000000..aa6ba077 --- /dev/null +++ b/src/libs/models/file.js @@ -0,0 +1,39 @@ + +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); +const libs = `${process.cwd()}/libs`; + +var File = db.define("File",{ + id: { + type: Sequelize.STRING, + allowNull:false, + unique: true, + primaryKey: true + }, + type:{ + type: Sequelize.STRING + }, + name: { + type: Sequelize.STRING + }, + data: { + type: Sequelize.BLOB('long') + } +}, +{timestamps: false}); + +File.generateObjectId = function(){ + var timestamp = (new Date().getTime() / 1000 | 0).toString(16); + return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function() { + return (Math.random() * 16 | 0).toString(16); + }).toLowerCase(); +} + +const setObjectId = file => { + file.id = File.generateObjectId() +}; + +File.beforeCreate(setObjectId); + +module.exports=File; + diff --git a/src/libs/routes_v1/file.controller.js b/src/libs/routes_v1/file.controller.js new file mode 100644 index 00000000..06464342 --- /dev/null +++ b/src/libs/routes_v1/file.controller.js @@ -0,0 +1,41 @@ +var stream = require('stream'); +const libs = `${process.cwd()}/libs`; +const File = require(`${libs}/models/file`); + +exports.uploadFile = async (_file) => { + let file = await File.create({ + id: 0, + type: _file.mimetype, + name: _file.originalname, + data: _file.buffer + }).catch(err => { + console.log(err); + res.json({msg: 'Error', detail: err}); + }); + return file.id; +} + +exports.listAllFiles = (req, res) => { + File.findAll({attributes: ['id', 'name']}).then(files => { + res.json(files); + }).catch(err => { + console.log(err); + res.json({msg: 'Error', detail: err}); + }); +} + +exports.downloadFile = (req, res) => { + File.findByPk(req.params.id).then(file => { + var fileContents = Buffer.from(file.data, "base64"); + var readStream = new stream.PassThrough(); + readStream.end(fileContents); + + res.set('Content-disposition', 'attachment; filename=' + file.name); + res.set('Content-Type', file.type); + + readStream.pipe(res); + }).catch(err => { + console.log(err); + res.json({msg: 'Error', detail: err}); + }); +} diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 46b0574d..81341f32 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -18,7 +18,9 @@ const email = require(`${libs}/middlewares/email`); const passport = require('passport'); -const uuid = require('node-uuid'); +const fileWorker = require('./file.controller.js'); + +let upload = require('../middlewares/multer.config.js'); function emailSyntax(email) { const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; @@ -61,19 +63,26 @@ pubApp.get('/:id', (req, res, next) => { }); }, response('publication')); -pubApp.post('/', passport.authenticate('bearer', { session: false }), async (req, res, next) => { +pubApp.post('/', upload.single('file'), async (req, res, next) => { + let _file_id = null + if(req.file){ + _file_id = await fileWorker.uploadFile(req.file); + if(!_file_id) + console.log("NAO ARQUIVO");} + let data = JSON.parse(req.body.data); + console.log(data); let pb = await Publication.create({ id: 0, - filter: req.body.categoria, - title: req.body.title, - authors: req.body.autores, - organization: req.body.organizacao, - year: req.body.ano, - text: req.body.texto, - link: req.body.link, - upload: req.body.upload, + filter: data.categoria, + title: data.title, + authors: data.autores, + organization: data.organizacao, + year: data.ano, + text: data.texto, + link: data.link, + upload: _file_id, is_draft: false, - is_homepage: req.body.homepage + is_homepage: data.homepage }).catch(function (err) { log.error(err); let errors = []; @@ -85,13 +94,8 @@ pubApp.post('/', passport.authenticate('bearer', { session: false }), async (req return res.json({ err, errors }); // handle error; }); - let up = await Publication.create({ - user_id: req.user.id, - publication_id: pb.id - }) - req.result = pb.toJSON(); - next(); -}); + req.result = pb.toJSON; +}, response('publication')); pubApp.post('/rascunho', passport.authenticate('bearer', { session: false }), async (req, res, next) => { let pb = await Publication.create({ -- GitLab From 4476d73afcd9a3dde83c4765aab5c0cfd4d6bab7 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 5 Jun 2023 11:51:07 -0300 Subject: [PATCH 039/123] [ADD] Rascunho --- src/libs/routes_v1/publication.js | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 81341f32..972928c7 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -70,7 +70,6 @@ pubApp.post('/', upload.single('file'), async (req, res, next) => { if(!_file_id) console.log("NAO ARQUIVO");} let data = JSON.parse(req.body.data); - console.log(data); let pb = await Publication.create({ id: 0, filter: data.categoria, @@ -97,19 +96,25 @@ pubApp.post('/', upload.single('file'), async (req, res, next) => { req.result = pb.toJSON; }, response('publication')); -pubApp.post('/rascunho', passport.authenticate('bearer', { session: false }), async (req, res, next) => { +pubApp.post('/rascunho', upload.single('file'), passport.authenticate('bearer', { session: false }), async (req, res, next) => { + let _file_id = null + if(req.file){ + _file_id = await fileWorker.uploadFile(req.file); + if(!_file_id) + console.log("NAO ARQUIVO");} + let data = JSON.parse(req.body.data); let pb = await Publication.create({ id: 0, - filter: req.body.categoria, - title: req.body.title, - authors: req.body.autores, - organization: req.body.organizacao, - year: req.body.ano, - text: req.body.texto, - link: req.body.link, - upload: req.body.upload, + filter: data.categoria, + title: data.title, + authors: data.autores, + organization: data.organizacao, + year: data.ano, + text: data.texto, + link: data.link, + upload: _file_id, is_draft: true, - is_homepage: req.body.homepage + is_homepage: data.homepage }).catch(function (err) { log.error(err); let errors = []; @@ -128,7 +133,7 @@ pubApp.post('/rascunho', passport.authenticate('bearer', { session: false }), as req.result = pb.toJSON(); next(); -}); +},response('rascunho')); pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { let pb = await Publication.findByPk(req.params.id).catch(function (err) { -- GitLab From d127da953aa76802df74f53254a5035739b4b116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 6 Jun 2023 11:52:12 -0300 Subject: [PATCH 040/123] update filters of school_infrastructure --- src/libs/routes_v2/infrastructure.js | 6 ----- src/libs/routes_v2/schoolInfrastructure.js | 28 +++++++++++----------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/libs/routes_v2/infrastructure.js b/src/libs/routes_v2/infrastructure.js index 01cc9264..89d7e278 100644 --- a/src/libs/routes_v2/infrastructure.js +++ b/src/libs/routes_v2/infrastructure.js @@ -518,12 +518,6 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { haveAdaptedBuilding.where('escola_agregada.dependencias_pne = 1'); req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1; - // Adicionar pátio - /* - patio = 1 ou 2 -- patio existe, 1 -- a ser coberto, 2 -- é coberto - func_predio_escolar = 1 - localizacao_id = 1 ou 2 - */ next(); }, multiQuery, (req, res, next) => { diff --git a/src/libs/routes_v2/schoolInfrastructure.js b/src/libs/routes_v2/schoolInfrastructure.js index da4d4593..00b87e03 100644 --- a/src/libs/routes_v2/schoolInfrastructure.js +++ b/src/libs/routes_v2/schoolInfrastructure.js @@ -387,7 +387,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // ( reg_fund_ai_t1=1 | reg_fund_af_t1=1 | reg_medio_medio_t1=1 | ensino_eja_fund= 1 | ensino_eja_medio= 1 | ensino_eja_prof= 1 | esp_eja_fund=1 | // esp_eja_medio=1 | ensino_esp_exclusiva_eja_prof=1) então conta id let allInfLab = allSchools.clone(); - allInfLab.where('reg_fund_ai_t1=1 OR reg_fund_af_t1=1 OR reg_medio_medio_t1=1 OR ensino_eja_fund=1 OR ensino_eja_medio=1 OR ensino_eja_prof=1 OR esp_eja_fund=1 OR esp_eja_medio=1 OR ensino_esp_exclusiva_eja_prof=1'); + allInfLab.where('etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1'); req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1; let haveInfLab = allInfLab.clone(); @@ -404,7 +404,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1; let haveScienceLab = allScienceLab.clone(); - haveScienceLab.where('escola_agregada.lab_ciencias = true'); + haveScienceLab.where('escola_agregada.lab_ciencias = 1 AND (etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1; let needScienceLab = allScienceLab.clone(); @@ -415,7 +415,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Se (situacao_de_funcionamento=1) and (ensino_regular=1 OR ensino_eja=1 OR educacao_profissional=1) and // (local_func_predio_escolar=1) and (dependencia_adm_id<=3) and (reg_infantil_creche_t1=1 or reg_infantil_preescola_t1=1 or reg_fund_ai_t1=1) então conta id let allKidsPark = allSchools.clone(); - allKidsPark.where('reg_infantil_creche_t1=1 OR reg_infantil_preescola_t1=1 OR reg_fund_ai_t1=1'); + allKidsPark.where('escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1'); req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1; let haveKidsPark = allKidsPark.clone(); @@ -441,15 +441,15 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Quadra de esportes let allSportsCourt = allSchools.clone(); - allSportsCourt.where('reg_fund_ai_t1=1 or reg_fund_af_t1=1 or reg_medio_medio_t1=1 or ensino_eja_fund= 1 or ensino_eja_medio= 1 or ensino_eja_prof= 1 or esp_eja_fund=1 or esp_eja_medio=1 or ensino_esp_exclusiva_eja_prof=1'); + allSportsCourt.where('escola_agregada.localizacao_id = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1; let haveSportsCourt = allSportsCourt.clone(); - haveSportsCourt.where('escola_agregada.quadra_esportes = 1'); + haveSportsCourt.where('escola_agregada.quadra_esportes = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1; let needSportsCourt = allSportsCourt.clone(); - needSportsCourt.where('escola_agregada.quadra_esportes = 0'); + needSportsCourt.where('escola_agregada.quadra_esportes = 0 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.needSportsCourt = req.querySet.push(needSportsCourt) - 1; // Quadras a serem cobertas @@ -468,11 +468,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allCourtyard = req.queryIndex.allSchools; let haveCourtyard = allSchools.clone(); - haveCourtyard.where('escola_agregada.patio = 1 OR escola_agregada.patio = 2'); + haveCourtyard.where('escola_agregada.func_predio_escolar = 1 AND (escola_agregada.patio = 1 OR escola_agregada.patio = 2)'); req.queryIndex.haveCourtyard = req.querySet.push(haveCourtyard) - 1; let needCourtyard = allSchools.clone(); - needCourtyard.where('escola_agregada.patio = 0'); + needCourtyard.where('escola_agregada.func_predio_escolar = 1 AND escola_agregada.patio = 0'); req.queryIndex.needCourtyard = req.querySet.push(needCourtyard) - 1; // Pátios a serem cobertos @@ -554,11 +554,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInternet = req.queryIndex.allCountrySchools; let haveInternet = allCountrySchools.clone(); - haveInternet.where('escola_agregada.internet = 1'); + haveInternet.where('escola_agregada.internet = 1 AND localizacao_id = 2'); req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1; let needInternet = allCountrySchools.clone(); - needInternet.where('escola_agregada.internet = 0'); + needInternet.where('escola_agregada.internet = 0 AND localizacao_id = 2'); req.queryIndex.needInternet = req.querySet.push(needInternet) - 1; // Internet banda larga @@ -567,11 +567,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allBroadbandInternet = req.queryIndex.allUrbanSchools; let haveBroadbandInternet = allUrbanSchools.clone(); - haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1'); + haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1 AND localizacao_id = 1'); req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1; let needBroadbandInternet = allUrbanSchools.clone(); - needBroadbandInternet.where('escola_agregada.internet_banda_larga = 0'); + needBroadbandInternet.where('escola_agregada.internet_banda_larga = 0 AND localizacao_id = 1'); req.queryIndex.needBroadbandInternet = req.querySet.push(needBroadbandInternet) - 1; // Banheiro @@ -593,11 +593,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInsideKidsBathroom = req.querySet.push(allInsideKidsBathroom) - 1; let haveInsideKidsBathroom = allInsideKidsBathroom.clone(); - haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1'); + haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1 AND (escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1) AND localizacao_id IN (1, 2)'); req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1; let needInsideKidsBathroom = allInsideKidsBathroom.clone(); - needInsideKidsBathroom.where('escola_agregada.sanitario_ei = 0'); + needInsideKidsBathroom.where('escola_agregada.sanitario_ei = 0 AND (escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1) AND localizacao_id IN (1, 2)'); req.queryIndex.needInsideKidsBathroom = req.querySet.push(needInsideKidsBathroom) - 1; // Fornecimento de energia -- GitLab From a02836c622002bef16aac66b64892023b99d0382 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 7 Jun 2023 11:11:18 -0300 Subject: [PATCH 041/123] [ADD] GET PUBLICATIONS AND ACTIVITIES --- src/libs/models/activity.js | 80 ++++++++++++++ src/libs/models/userActivity.js | 29 +++++ src/libs/routes_v1/activity.js | 176 ++++++++++++++++++++++++++++++ src/libs/routes_v1/publication.js | 115 +++++++++---------- 4 files changed, 343 insertions(+), 57 deletions(-) create mode 100644 src/libs/models/activity.js create mode 100644 src/libs/models/userActivity.js create mode 100644 src/libs/routes_v1/activity.js diff --git a/src/libs/models/activity.js b/src/libs/models/activity.js new file mode 100644 index 00000000..f5a1cda2 --- /dev/null +++ b/src/libs/models/activity.js @@ -0,0 +1,80 @@ +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); +const libs = `${process.cwd()}/libs`; + +var Activity = db.define("Activity",{ + id:{ + type: Sequelize.STRING, + allowNull:false, + unique: true, + primaryKey: true + }, + type:{ + type: Sequelize.STRING, + allowNull:false + }, + title:{ + type: Sequelize.STRING, + allowNull:false, + }, + subtitle:{ + type: Sequelize.STRING + }, + date:{ + type: Sequelize.DATE, + allowNull:false + }, + authors:{ + type: Sequelize.STRING, + }, + text:{ + type: Sequelize.STRING, + allowNull: false + }, + name_headline:{ + type: Sequelize.STRING, + allowNull:false + }, + resume_headline:{ + type:Sequelize.STRING, + allowNull:false + }, + date_headline:{ + type: Sequelize.DATE, + allowNull:false + }, + local_headline:{ + type:Sequelize.STRING, + allowNull:false + }, + additional_headline:{ + type:Sequelize.STRING + }, + is_draft:{ + type:Sequelize.BOOLEAN, + allowNull:false, + defaultValue: true + }, + is_headline:{ + type:Sequelize.BOOLEAN, + allowNull: false, + defaultValue: false + } + +}, +{timestamps: false}); + +Activity.generateObjectId = function(){ + var timestamp = (new Date().getTime() / 1000 | 0).toString(16); + return timestamp + 'xxxxxxxxxxxxxxxx'.replace(/[x]/g, function() { + return (Math.random() * 16 | 0).toString(16); + }).toLowerCase(); +} + +const setObjectId = act => { + act.id = Activity.generateObjectId() +}; + +Activity.beforeCreate(setObjectId); + +module.exports = Activity; \ No newline at end of file diff --git a/src/libs/models/userActivity.js b/src/libs/models/userActivity.js new file mode 100644 index 00000000..2c1f8b56 --- /dev/null +++ b/src/libs/models/userActivity.js @@ -0,0 +1,29 @@ +const Sequelize = require("sequelize"); +const db = require('../db/postgres.js'); +const libs = `${process.cwd()}/libs`; +const User = require(`${libs}/models/user`); +const Activity = require(`${libs}/models/activity`); + +var userActivity = db.define("userActivity",{ + id:{ + type: Sequelize.INTEGER, + allowNull:false, + unique: true, + primaryKey: true + }, + user_id:{ + type: Sequelize.STRING, + allowNull:false, + }, + activity_id:{ + type: Sequelize.STRING, + allowNull:false + } +}, +{timestamps: false}); + +userActivity.hasMany(User, {foreignKey: 'id'}); +userActivity.hasMany(Activity, {foreignKey: 'id'}); + +module.exports = userActivity; + diff --git a/src/libs/routes_v1/activity.js b/src/libs/routes_v1/activity.js new file mode 100644 index 00000000..87ba5d1e --- /dev/null +++ b/src/libs/routes_v1/activity.js @@ -0,0 +1,176 @@ +const express = require('express'); + +const activityApp = express(); + +const libs = `${process.cwd()}/libs`; + +const config = require(`${libs}/config`); + +const log = require(`${libs}/log`)(module); + +const Activity = require(`${libs}/models/activity`); + +const response = require(`${libs}/middlewares/response`); + +const email = require(`${libs}/middlewares/email`); + +const passport = require('passport'); + +const fileWorker = require('./file.controller.js'); + +let upload = require('../middlewares/multer.config.js'); + +function emailSyntax(email) { + const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + return regex.test(email); +} + +activityApp.get('/', async (req, res, next) => { + const page = parseInt(req.query.page) || 1; + const pageSize = parseInt(req.query.pageSize) || 5; + try { + const totalCount = await Activity.count(); + const offset = (page - 1) * pageSize; + + const acts = await Activity.findAll({ + offset, + limit: pageSize, + where: { + is_draft: false + }, + order:[ + ['date', 'DESC']] + }); + + res.json({ + page, + pageSize, + totalCount, + data: acts, + }); + } catch (error) { + console.error(error); + res.status(500).json({ error: 'An error occurred' }); + } +}); + +activityApp.get('/', async (req, res, next) => { + const page = parseInt(req.query.page) || 1; + const pageSize = parseInt(req.query.pageSize) || 5; + try { + const totalCount = await Activity.count(); + const offset = (page - 1) * pageSize; + + const acts = await Activity.findAll({ + offset, + limit: pageSize, + where: { + is_draft: acts + }, + order:[ + ['date', 'DESC']] + }); + + res.json({ + page, + pageSize, + totalCount, + data: acts, + }); + } catch (error) { + console.error(error); + res.status(500).json({ error: 'An error occurred' }); + } + }); + +activityApp.get('/:id', (req, res, next) => { + Activity.findByPk(req.params.id).then((act) => { + if (!act) { + res.statusCode = 404; + res.json({ msg: "A atividade não está cadastrada" }); + } else { + req.result = act.toJSON(); + next(); + } + }).catch(function (err) { + log.error(err); + return next(err); + }); +}, response('activity')); + +activityApp.post('/', async (req, res, next) => { + let data = JSON.parse(req.body.data); + let pb = await Publication.create({ + id: 0, + filter: data.categoria, + title: data.title, + authors: data.autores, + organization: data.organizacao, + year: data.ano, + text: data.texto, + link: data.link, + upload: _file_id, + is_draft: data.rascunho, + is_homepage: data.homepage + }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); + res.statusCode = 400; + return res.json({ err, errors }); + // handle error; + }); + req.result = pb.toJSON(); + next(); +}, response('publication')); + +activityApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + let pb = await Publication.findByPk(req.params.id).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + }) + if (!pb) { + res.statusCode = 404; + return next({ + err: { + message: 'Publicação não encontrada' + } + }); + } + pb.filter = req.body.categoria || pb.filter; + pb.title = req.body.title || pb.title; + pb.authors = req.body.autores || pb.authors; + pb.organization= req.body.organizacao || pb.organization; + pb.year= req.body.ano || pb.year; + pb.text= req.body.texto || pb.text; + pb.link= req.body.link || pb.link; + pb.upload= req.body.upload || pb.upload; + pb.is_homepage= req.body.homepage || pb.is_homepage; + + pb.save().catch(err => { + if (err) { + log.error(err); + return next({ message: 'Erro ao atualizar publicacao' }); + } + }) + let p = p.toJSON(); + res.json({ publication: p }); + +}); + +activityApp.delete('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + await Publication.destroy({where:{id:req.params.id}}).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } +}); + return next({ msg: 'Publication Deleted', status: 200 }); +}); + +module.exports = activityApp; diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 972928c7..e29abd7e 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -27,26 +27,65 @@ function emailSyntax(email) { return regex.test(email); } -pubApp.get('/', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let up = await UserPublication.findAll({ where: { user_id: req.user.id } }).catch(function (err) { - if (err) { - log.error(err); - return next(err); - } - }); - console.log(up); - let publications = []; - for (let _id in up.publication_id) { - let pb = await Publication.findByPk(_id).catch(function (err) { - if (err) { - log.error(err); - return next(err); +pubApp.get('/', async (req, res, next) => { + const page = parseInt(req.query.page) || 1; // Current page number + const pageSize = parseInt(req.query.pageSize) || 5; // Number of items per page + try { + const totalCount = await Publication.count(); + const offset = (page - 1) * pageSize; + + const publis = await Publication.findAll({ + offset, + limit: pageSize, + where: { + is_draft: false } }); - publications.push(pb); + + res.json({ + page, + pageSize, + totalCount, + data: publis, + }); + } catch (error) { + console.error(error); + res.status(500).json({ error: 'An error occurred' }); } - next(); -}, response('publications')); +}); + +pubApp.get('/drafts', async (req, res, next) => { + const page = parseInt(req.query.page) || 1; // Current page number + const pageSize = parseInt(req.query.pageSize) || 5; // Number of items per page + + try { + // Count total number of items + const totalCount = await Publication.count(); + + // Calculate offset based on page and pageSize + const offset = (page - 1) * pageSize; + + // Query the database with pagination options + const drafts = await Publication.findAll({ + offset, + limit: pageSize, + where: { + is_draft: true + } + }); + + res.json({ + page, + pageSize, + totalCount, + data: drafts, + }); + } catch (error) { + console.error(error); + res.status(500).json({ error: 'An error occurred' }); + } +}); + pubApp.get('/:id', (req, res, next) => { Publication.findByPk(req.params.id).then((pb) => { @@ -80,40 +119,7 @@ pubApp.post('/', upload.single('file'), async (req, res, next) => { text: data.texto, link: data.link, upload: _file_id, - is_draft: false, - is_homepage: data.homepage - }).catch(function (err) { - log.error(err); - let errors = []; - for (let errName in err.errors) { - errors.push(err.errors[errName].message); - } - log.error(errors); - res.statusCode = 400; - return res.json({ err, errors }); - // handle error; - }); - req.result = pb.toJSON; -}, response('publication')); - -pubApp.post('/rascunho', upload.single('file'), passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let _file_id = null - if(req.file){ - _file_id = await fileWorker.uploadFile(req.file); - if(!_file_id) - console.log("NAO ARQUIVO");} - let data = JSON.parse(req.body.data); - let pb = await Publication.create({ - id: 0, - filter: data.categoria, - title: data.title, - authors: data.autores, - organization: data.organizacao, - year: data.ano, - text: data.texto, - link: data.link, - upload: _file_id, - is_draft: true, + is_draft: data.rascunho, is_homepage: data.homepage }).catch(function (err) { log.error(err); @@ -126,14 +132,9 @@ pubApp.post('/rascunho', upload.single('file'), passport.authenticate('bearer', return res.json({ err, errors }); // handle error; }); - let up = await Publication.create({ - user_id: req.user.id, - publication_id: pb.id - }) req.result = pb.toJSON(); - next(); -},response('rascunho')); +}, response('publication')); pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { let pb = await Publication.findByPk(req.params.id).catch(function (err) { -- GitLab From d0af2ab104f776600cbdfad2a65e72f57ca8256d Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 14 Jun 2023 10:22:30 -0300 Subject: [PATCH 042/123] [FIX] Api CheckPassword --- src/libs/middlewares/oauth2.js | 5 ++- src/libs/middlewares/passport.js | 2 +- src/libs/routes_v1/activity.js | 74 ++++++++++++++++++-------------- src/libs/routes_v1/api.js | 5 +++ 4 files changed, 51 insertions(+), 35 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 672c203e..cc9eaab0 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -54,14 +54,15 @@ let generateTokens = (userId, clientId, done) => { }; - +// Exchange username & password for access token. aserver.exchange(oauth2orize.exchange.password(function(client, username, password, scope, done) { User.findOne({ where: {email:username} }).then(function(user) { - if(user == null){ + if(user == null|| !user.checkPassword(password)){ return done(null, false); } + if(user.dataValues.origin != client.client_secret){ console.log("Erro de client_secret"); return done(null, false); diff --git a/src/libs/middlewares/passport.js b/src/libs/middlewares/passport.js index a63cd150..7e8d5120 100644 --- a/src/libs/middlewares/passport.js +++ b/src/libs/middlewares/passport.js @@ -20,7 +20,7 @@ passport.use(new ClientPasswordStrategy( return done(null, false); } if (client.client_secret !== client_secret) { - console.log("Erro de geracao Chave Secreta"); + console.log("Erro de Chave Secreta"); return done(null, false); } return done(null, client); diff --git a/src/libs/routes_v1/activity.js b/src/libs/routes_v1/activity.js index 87ba5d1e..9467021f 100644 --- a/src/libs/routes_v1/activity.js +++ b/src/libs/routes_v1/activity.js @@ -99,19 +99,22 @@ activityApp.get('/:id', (req, res, next) => { }, response('activity')); activityApp.post('/', async (req, res, next) => { - let data = JSON.parse(req.body.data); - let pb = await Publication.create({ + console.log(req.body); + let act = await Activity.create({ id: 0, - filter: data.categoria, - title: data.title, - authors: data.autores, - organization: data.organizacao, - year: data.ano, - text: data.texto, - link: data.link, - upload: _file_id, - is_draft: data.rascunho, - is_homepage: data.homepage + type:req.body.tipo, + title: req.body.titulo, + subtitle: req.body.subtitulo, + date: req.body.dataDePostagem, + authors:req.body.autor, + text: req.body.texto, + name_headline: req.body.nome, + resume_headline: req.body.resumo, + date_headline: req.body.dataAtividade, + local_headline: req.body.local, + additional_headline: req.body.informacoes, + is_draft: req.body.rascunho, + is_headline: req.body.is_headline }).catch(function (err) { log.error(err); let errors = []; @@ -123,54 +126,61 @@ activityApp.post('/', async (req, res, next) => { return res.json({ err, errors }); // handle error; }); - req.result = pb.toJSON(); + if(!act){ + console.log("AA"); + } + req.result = act.toJSON(); next(); -}, response('publication')); +}, response('activity')); activityApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - let pb = await Publication.findByPk(req.params.id).catch(function (err) { + let act = await Activity.findByPk(req.params.id).catch(function (err) { if (err) { log.error(err); return next({ err }); } }) - if (!pb) { + if (!act) { res.statusCode = 404; return next({ err: { - message: 'Publicação não encontrada' + message: 'Atividade não encontrada' } }); } - pb.filter = req.body.categoria || pb.filter; - pb.title = req.body.title || pb.title; - pb.authors = req.body.autores || pb.authors; - pb.organization= req.body.organizacao || pb.organization; - pb.year= req.body.ano || pb.year; - pb.text= req.body.texto || pb.text; - pb.link= req.body.link || pb.link; - pb.upload= req.body.upload || pb.upload; - pb.is_homepage= req.body.homepage || pb.is_homepage; - - pb.save().catch(err => { + act.type = req.body.type || act.type; + act.title = req.body.title || act.title; + act.subtitle = req.body.subtitle || act.subtitle; + act.date = req.body.date || act.date; + act.authors = req.body.autores || act.authors; + act.text= req.body.text || act.text; + act.name_headline= req.body.name_headline || act.name_headline; + act.resume_headline= req.body.resume_headline || act.resume_headline; + act.date_headline= req.body.date_headline || act.date_headline; + act.local_headline= req.body.local_headline || act.local_headline; + act.additional_headline= req.body.additional_headline || act.additional_headline; + act.is_draft= req.body.is_draft || act.is_draft; + act.is_headline= req.body.is_headline || act.is_headline; + + act.save().catch(err => { if (err) { log.error(err); return next({ message: 'Erro ao atualizar publicacao' }); } }) - let p = p.toJSON(); - res.json({ publication: p }); + let activity = act.toJSON(); + res.json({ activity: activity}); }); activityApp.delete('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { - await Publication.destroy({where:{id:req.params.id}}).catch(function (err) { + await Activity.destroy({where:{id:req.params.id}}).catch(function (err) { if (err) { log.error(err); return next({ err }); } }); - return next({ msg: 'Publication Deleted', status: 200 }); + return next({ msg: 'Activity Deleted', status: 200 }); }); module.exports = activityApp; diff --git a/src/libs/routes_v1/api.js b/src/libs/routes_v1/api.js index 50941a94..75a8e663 100644 --- a/src/libs/routes_v1/api.js +++ b/src/libs/routes_v1/api.js @@ -139,6 +139,8 @@ const courseStudents = require(`${libs}/routes_v1/courseStudents`); const publication = require(`${libs}/routes_v1/publication`); +const activity = require(`${libs}/routes_v1/activity`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v1 is running' }); }); @@ -202,4 +204,7 @@ api.use('/course_students', courseStudents); //Publication api.use('/publication', publication); +//Activity +api.use('/activity', activity); + module.exports = api; -- GitLab From a2f44a70b4d1b0768b5f2bef3d83c762220a622d Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 15 Jun 2023 11:10:19 -0300 Subject: [PATCH 043/123] [ADD] RETURN RESPONSE --- src/libs/middlewares/oauth2.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index cc9eaab0..2c85f516 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -23,10 +23,11 @@ let errFn = (cb, err) => { } // Destroys any old tokens and generates a new access and refresh token -let generateTokens = (userId, clientId, done) => { +let generateTokens = (userId, clientId,userRole, done) => { // curries in `done` callback so we don't need to pass it let refreshTokenValue; let tokenValue; + let admin = false; RefreshToken.destroy({where:{"user_id": userId, "client_id": clientId}}); AccessToken.destroy({where:{"user_id": userId, "client_id": clientId}}); @@ -47,19 +48,22 @@ let generateTokens = (userId, clientId, done) => { client_id:clientId, token:refreshed_token }) - - done(null, tokenValue, refreshTokenValue, { + if(userRole == 1){ + admin = true; + } + done(null, tokenValue, refreshTokenValue, {'admin': admin},{ 'expires_in': config.security.tokenLife }); }; + // Exchange username & password for access token. aserver.exchange(oauth2orize.exchange.password(function(client, username, password, scope, done) { User.findOne({ where: {email:username} }).then(function(user) { - if(user == null|| !user.checkPassword(password)){ + if(user == null|| !user.checkPassword(user, password)){ return done(null, false); } @@ -68,7 +72,7 @@ aserver.exchange(oauth2orize.exchange.password(function(client, username, passwo return done(null, false); } log.info(`Gerando token para usuário ${user.name}`); - generateTokens(user.dataValues.id, client.id, done); + generateTokens(user.dataValues.id, client.id, user.dataValues.role_id, done); }).catch(function(error) { return done(error); }); @@ -107,4 +111,4 @@ exports.token = [ passport.authenticate(['oauth2-client-password'], { session: false }), aserver.token(), aserver.errorHandler() -]; +]; \ No newline at end of file -- GitLab From b709d6c1d646cb00a7448640edbe33b0f9fe50fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 22 Jun 2023 09:18:15 -0300 Subject: [PATCH 044/123] Changes to simcaq infrastructure --- src/libs/convert/scholarDependency.js | 76 ++++++++++++++++ src/libs/middlewares/id2str.js | 4 +- src/libs/routes_v2/api.js | 3 + .../routes_v2/simcaqSchoolInfrastructure.js | 87 +++++++++++++++++++ 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/libs/convert/scholarDependency.js create mode 100644 src/libs/routes_v2/simcaqSchoolInfrastructure.js diff --git a/src/libs/convert/scholarDependency.js b/src/libs/convert/scholarDependency.js new file mode 100644 index 00000000..25684b9b --- /dev/null +++ b/src/libs/convert/scholarDependency.js @@ -0,0 +1,76 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +module.exports = function scholarDependency(id) { + switch (id) { + case 1: + return "Biblioteca"; + case 2: + return "Sala de leitura"; + case 3: + return "Laboratório de informática"; + case 4: + return "Laboratório de ciências"; + case 5: + return "Parque infantil"; + case 6: + return "Quadra poliesportiva"; + case 7: + return "Quadras a serem cobertas"; + case 8: + return "Pátio"; + case 9: + return "Pátios a serem cobertos"; + case 10: + return "Sala de direção"; + case 11: + return "Secretaria"; + case 12: + return "Sala de professores"; + case 13: + return "Cozinha"; + case 14: + return "Despensa"; + case 15: + return "Almoxarifado"; + case 16: + return "Internet"; + case 17: + return "Internet banda larga"; + case 18: + return "Banheiro dentro do prédio"; + case 19: + return "Banheiro adequado para educação infantil dentro do prédio"; + case 20: + return "Fornecimento de energia"; + case 21: + return "Abastecimento de água"; + case 22: + return "Ãgua filtrada"; + case 23: + return "Coleta de esgoto"; + case 24: + return "Dependências adaptadas para pessoas com deficiências"; + case 25: + return "Banheiros adaptados para pessoas com deficiências"; + default: + return "Dependência escolar desconhecida"; + } +} \ No newline at end of file diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js index 39d819aa..cb549d3d 100644 --- a/src/libs/middlewares/id2str.js +++ b/src/libs/middlewares/id2str.js @@ -100,6 +100,7 @@ const admDependencyPub = require(`${libs}/convert/admDependencyPub`); const supplyDimension = require(`${libs}/convert/supplyDimension`); const type = require(`${libs}/convert/type`); const level = require(`${libs}/convert/level`); +const scholarDependency = require(`${libs}/convert/scholarDependency`); const ids = { gender_id: gender, @@ -191,7 +192,8 @@ const ids = { shift_id: shift, supply_dimension_id: supplyDimension, type_id: type, - level_id: level + level_id: level, + scholar_dependency_id: scholarDependency }; function transform(removeId=false) { diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 5c00d3fe..a8e1e1b7 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -160,6 +160,8 @@ const simcaqAggregatedEnrollment = require(`${libs}/routes_v2/simcaqAggregatedEn const simcaqTeacherCityPlan = require(`${libs}/routes_v2/simcaqTeacherCityPlan`); +const simcaqSchoolInfrastructure = require(`${libs}/routes_v2/simcaqSchoolInfrastructure`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -231,5 +233,6 @@ api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); api.use('/simcaq_enrollment_projection', simcaqEnrollmentProjection); api.use('/simcaq_aggregated_enrollment', simcaqAggregatedEnrollment); api.use('/simcaq_teacher_city_plan', simcaqTeacherCityPlan); +api.use('/simcaq_school_infrastructure', simcaqSchoolInfrastructure); module.exports = api; diff --git a/src/libs/routes_v2/simcaqSchoolInfrastructure.js b/src/libs/routes_v2/simcaqSchoolInfrastructure.js new file mode 100644 index 00000000..f10022cb --- /dev/null +++ b/src/libs/routes_v2/simcaqSchoolInfrastructure.js @@ -0,0 +1,87 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqSchoolInfrastructureApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqSchoolInfrastructureApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_school_infrastructure', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'scholar_dependency', + table: 'simcaq_school_infrastructure', + tableField: 'scholar_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'scholar_dependency_id' + } +}); + +simcaqSchoolInfrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_school_infrastructure') + .field('simcaq_school_infrastructure.ano_censo', 'year') + .field('simcaq_school_infrastructure.scholar_dependency_id', 'scholar_dependency_id') + .field('SUM(simcaq_school_infrastructure.total_schools)', 'total_schools') + .field('SUM(total_no_dependency)', 'total_schools_without_dependency') + .field('SUM(total_with_dependency)', 'total_schools_with_dependency') + .group('simcaq_school_infrastructure.ano_censo') + .group('simcaq_school_infrastructure.scholar_dependency_id'); + next(); +}, query, id2str.transform(), response('simcaqSchoolInfrastructure')); + +module.exports = simcaqSchoolInfrastructureApp; -- GitLab From 0832a14c9d6bfeac10f740d70980f212c3a39a4d Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Thu, 22 Jun 2023 10:26:50 -0300 Subject: [PATCH 045/123] [ADD] ACL in project --- src/libs/middlewares/authorize.js | 39 +++++++++++++++++++++++++++++++ src/libs/models/activity.js | 4 ++-- src/libs/models/permission.js | 2 +- src/libs/models/role.js | 6 ++++- src/libs/routes_v1/activity.js | 31 +++++++++++++++++++----- src/libs/routes_v1/publication.js | 8 ++++--- 6 files changed, 77 insertions(+), 13 deletions(-) create mode 100644 src/libs/middlewares/authorize.js diff --git a/src/libs/middlewares/authorize.js b/src/libs/middlewares/authorize.js new file mode 100644 index 00000000..592c193b --- /dev/null +++ b/src/libs/middlewares/authorize.js @@ -0,0 +1,39 @@ +const express = require('express'); + +const pubApp = express(); + +const libs = `${process.cwd()}/libs`; + +const PermissionRole = require(`${libs}/models/permissionRole`) + +const mapPermission = { + 'criar publicacao': '1', + 'editar publicacao': '2', + 'apagar publicacao': '3', + 'criar atividade': '4', + 'editar atividade': '5', + 'apagar atividade': '6', +} + +function authorized(permission) { + return async function (req, res, next) { + const permission_id = mapPermission[permission] + const userRole = req.user.role_id; // Assuming user role is stored in req.user.role + const hasPermission = await PermissionRole.findOne({where:{role_id:userRole, permission_id: permission_id}}).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + }); + if (hasPermission) { + // User has permission, proceed to next middleware or route handler + next(); + } else { + // User does not have permission, return unauthorized response + res.status(403).json({ message: 'Unauthorized' }); + } + }; +} + +module.exports = authorized + diff --git a/src/libs/models/activity.js b/src/libs/models/activity.js index f5a1cda2..92fc6f08 100644 --- a/src/libs/models/activity.js +++ b/src/libs/models/activity.js @@ -21,7 +21,7 @@ var Activity = db.define("Activity",{ type: Sequelize.STRING }, date:{ - type: Sequelize.DATE, + type: Sequelize.STRING, allowNull:false }, authors:{ @@ -40,7 +40,7 @@ var Activity = db.define("Activity",{ allowNull:false }, date_headline:{ - type: Sequelize.DATE, + type: Sequelize.STRING, allowNull:false }, local_headline:{ diff --git a/src/libs/models/permission.js b/src/libs/models/permission.js index 9d827d30..ba35c4ce 100644 --- a/src/libs/models/permission.js +++ b/src/libs/models/permission.js @@ -35,5 +35,5 @@ const setObjectId = permission => { Permission.beforeCreate(setObjectId); -module.exports = PermissionRole; +module.exports = Permission; diff --git a/src/libs/models/role.js b/src/libs/models/role.js index dc30e09e..d594b061 100644 --- a/src/libs/models/role.js +++ b/src/libs/models/role.js @@ -11,7 +11,11 @@ var Role = db.define("Role",{ role_name:{ type: Sequelize.STRING, allowNull:false, - } + }, + // token:{ + // type: Sequelize.STRING, + // allowNull:false, + // } }, {timestamps: false}); diff --git a/src/libs/routes_v1/activity.js b/src/libs/routes_v1/activity.js index 9467021f..4468af18 100644 --- a/src/libs/routes_v1/activity.js +++ b/src/libs/routes_v1/activity.js @@ -98,19 +98,37 @@ activityApp.get('/:id', (req, res, next) => { }); }, response('activity')); -activityApp.post('/', async (req, res, next) => { + +function transformDateFormat(dateString) { + // Split the date string into day, month, and year components + var parts = dateString.split('/'); + + // Extract day, month, and year values + var day = parts[0]; + var month = parts[1]; + var year = parts[2]; + + // Concatenate the components in "yyyy/mm/dd" format + var transformedDate = year + '/' + month + '/' + day; + + return transformedDate; +} + + + +activityApp.post('/', passport.authenticate('bearer', { session: false }), authorized('criar atividade'), async (req, res, next) => { console.log(req.body); let act = await Activity.create({ id: 0, type:req.body.tipo, title: req.body.titulo, subtitle: req.body.subtitulo, - date: req.body.dataDePostagem, + date: transformDateFormat(req.body.dataDePostagem), authors:req.body.autor, text: req.body.texto, name_headline: req.body.nome, resume_headline: req.body.resumo, - date_headline: req.body.dataAtividade, + date_headline: transformDateFormat(req.body.dataAtividade), local_headline: req.body.local, additional_headline: req.body.informacoes, is_draft: req.body.rascunho, @@ -127,13 +145,14 @@ activityApp.post('/', async (req, res, next) => { // handle error; }); if(!act){ - console.log("AA"); + res.statusCode = 400; + return res; } req.result = act.toJSON(); next(); }, response('activity')); -activityApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { +activityApp.put('/:id', passport.authenticate('bearer', { session: false }), authorized('editar atividade'), async (req, res, next) => { let act = await Activity.findByPk(req.params.id).catch(function (err) { if (err) { log.error(err); @@ -173,7 +192,7 @@ activityApp.put('/:id', passport.authenticate('bearer', { session: false }), asy }); -activityApp.delete('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { +activityApp.delete('/:id', passport.authenticate('bearer', { session: false }), authorized('editar atividade'), async (req, res, next) => { await Activity.destroy({where:{id:req.params.id}}).catch(function (err) { if (err) { log.error(err); diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index e29abd7e..e1e3b0f6 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -22,6 +22,8 @@ const fileWorker = require('./file.controller.js'); let upload = require('../middlewares/multer.config.js'); +const authorized = require(`${libs}/middlewares/authorize.js`); + function emailSyntax(email) { const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; return regex.test(email); @@ -102,7 +104,7 @@ pubApp.get('/:id', (req, res, next) => { }); }, response('publication')); -pubApp.post('/', upload.single('file'), async (req, res, next) => { +pubApp.post('/', passport.authenticate('bearer', { session: false }), authorized('criar publicacao'), upload.single('file'), async (req, res, next) => { let _file_id = null if(req.file){ _file_id = await fileWorker.uploadFile(req.file); @@ -136,7 +138,7 @@ pubApp.post('/', upload.single('file'), async (req, res, next) => { next(); }, response('publication')); -pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { +pubApp.put('/:id', passport.authenticate('bearer', { session: false }), authorized('editar publicacao'), async (req, res, next) => { let pb = await Publication.findByPk(req.params.id).catch(function (err) { if (err) { log.error(err); @@ -172,7 +174,7 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), async (r }); -pubApp.delete('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { +pubApp.delete('/:id', passport.authenticate('bearer', { session: false }), authorized('apagar publicacao'), async (req, res, next) => { await Publication.destroy({where:{id:req.params.id}}).catch(function (err) { if (err) { log.error(err); -- GitLab From 69b469187a26c3b638dda93af9a1be6e26a85c62 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Tue, 27 Jun 2023 09:14:09 -0300 Subject: [PATCH 046/123] [ADD] Updates --- src/libs/routes_v1/activity.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/routes_v1/activity.js b/src/libs/routes_v1/activity.js index 4468af18..0c6e1d02 100644 --- a/src/libs/routes_v1/activity.js +++ b/src/libs/routes_v1/activity.js @@ -167,6 +167,7 @@ activityApp.put('/:id', passport.authenticate('bearer', { session: false }), aut } }); } + console.log("TEste"); act.type = req.body.type || act.type; act.title = req.body.title || act.title; act.subtitle = req.body.subtitle || act.subtitle; -- GitLab From 16fe166d8a0489566bfeb91dcf89b75a502544f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 29 Jun 2023 10:45:25 -0300 Subject: [PATCH 047/123] Fix issue with classroom count rounding --- src/libs/routes_v1/classroomCount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index 0af32828..a14250f9 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -646,7 +646,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { education_level_short_name: enrollmentEducationLevel.name, enrollment: { integral_percentage: req.dims.school ? level_diagnosis : Math.max(level_diagnosis, enrollmentEducationLevel.integralTimeOfferGoal), - integral_time: req.dims.school ? integral_time : Math.round(integral_time_total * Math.max(level_diagnosis, enrollmentEducationLevel.integralTimeOfferGoal)/100), + integral_time: req.dims.school ? integral_time : Math.round((integral_time_total * Math.max(level_diagnosis, enrollmentEducationLevel.integralTimeOfferGoal)/100) * 10) / 10, integral_time_total: integral_time_total, total_enrollment_day: 0, total_enrollment_night: 0, -- GitLab From 63e43123356037773f2a5ca9a4ed53a064d7f216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 29 Jun 2023 11:48:07 -0300 Subject: [PATCH 048/123] Fix issue with schools without teachers --- src/libs/routes_v1/classroomCount.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index a14250f9..0edb0863 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -1151,6 +1151,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { educationLevel.teacherNumber.careerLevels = []; req.teacherFormation.forEach((formation, i) => { + if (educationLevel.teacherNumber.total_teacher < 1) { + educationLevel.teacherNumber.total_teacher_full_period = 1; + educationLevel.teacherNumber.total_teacher_partial = 1; + } + let totalTeacherFullPeriodCareer = educationLevel.teacherNumber.total_teacher_full_period * teacherByFormation[i]; let totalTeacherPartialCareer = educationLevel.teacherNumber.total_teacher_partial * teacherByFormation[i]; -- GitLab From bf6c735daaad30a011b06d1771a24a99fc442912 Mon Sep 17 00:00:00 2001 From: ppc19 <ppc19@inf.ufpr.br> Date: Wed, 30 Nov 2022 08:55:23 -0300 Subject: [PATCH 049/123] change require fs to require fs extra --- gulpfile.babel.js | 2 +- src/libs/routes/classroomCount.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gulpfile.babel.js b/gulpfile.babel.js index 32500420..c4f477cd 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -1,6 +1,6 @@ require('babel-core/register'); -const fs = require('fs'); +const fs = require('fs-extra'); const gulp = require('gulp'); diff --git a/src/libs/routes/classroomCount.js b/src/libs/routes/classroomCount.js index 038c6e45..cb7af893 100644 --- a/src/libs/routes/classroomCount.js +++ b/src/libs/routes/classroomCount.js @@ -43,7 +43,7 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i let rqf = new ReqQueryFields(); -const fs = require('fs') +const fs = require('fs-extra') rqf.addField({ name: 'filter', -- GitLab From c536672e9e0e98720c1fbef2399c05856bb9f99b Mon Sep 17 00:00:00 2001 From: ppc19 <ppc19@inf.ufpr.br> Date: Wed, 30 Nov 2022 09:01:12 -0300 Subject: [PATCH 050/123] remove require fs --- gulpfile.babel.js | 2 -- src/libs/routes/classroomCount.js | 2 -- 2 files changed, 4 deletions(-) diff --git a/gulpfile.babel.js b/gulpfile.babel.js index c4f477cd..c661d5af 100644 --- a/gulpfile.babel.js +++ b/gulpfile.babel.js @@ -1,7 +1,5 @@ require('babel-core/register'); -const fs = require('fs-extra'); - const gulp = require('gulp'); const babel = require('gulp-babel'); diff --git a/src/libs/routes/classroomCount.js b/src/libs/routes/classroomCount.js index cb7af893..4f76bed3 100644 --- a/src/libs/routes/classroomCount.js +++ b/src/libs/routes/classroomCount.js @@ -43,8 +43,6 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i let rqf = new ReqQueryFields(); -const fs = require('fs-extra') - rqf.addField({ name: 'filter', field: false, -- GitLab From 2d041c223feac8289c4c2e7265b1b81d3fbade8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 28 Feb 2023 11:19:31 -0300 Subject: [PATCH 051/123] Add testroute, path to testroute, Add new middleware's body parsing --- src/libs/middlewares/reqBody.js | 24 ++++ src/libs/routes/api.js | 4 + src/libs/routes/testroute.js | 188 ++++++++++++++++++++++++++++++++ 3 files changed, 216 insertions(+) create mode 100644 src/libs/middlewares/reqBody.js create mode 100644 src/libs/routes/testroute.js diff --git a/src/libs/middlewares/reqBody.js b/src/libs/middlewares/reqBody.js new file mode 100644 index 00000000..e1f80cb1 --- /dev/null +++ b/src/libs/middlewares/reqBody.js @@ -0,0 +1,24 @@ +class ReqBody { + constructor() { + + } + parse() { + return(req, res, next) => { + // Gets body of the HTTP requisition + let body = req.body; + + // Chooses operation based on the mode field of the body + switch(body["mode"]) { + case "add_metrics": + console.log(body); + break; + default: + break; + } + + next(); + } + } +} + +module.exports = ReqBody; \ No newline at end of file diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js index f6715eaa..1a68a1d4 100644 --- a/src/libs/routes/api.js +++ b/src/libs/routes/api.js @@ -134,6 +134,8 @@ const message = require(`${libs}/routes/message`); const courseStudents = require(`${libs}/routes/courseStudents`); +const testRoute = require(`${libs}/routes/testroute`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API is running' }); }); @@ -193,4 +195,6 @@ api.use('/universityLocalOffer', universityLocalOffer); api.use('/message', message); api.use('/course_students', courseStudents); +api.use('/test', testRoute); + module.exports = api; diff --git a/src/libs/routes/testroute.js b/src/libs/routes/testroute.js new file mode 100644 index 00000000..2f108eb7 --- /dev/null +++ b/src/libs/routes/testroute.js @@ -0,0 +1,188 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const testApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const ReqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); +let reqBody = new ReqBody(); + +testApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'min_year', + table: 'escola', + tableField: 'ano_censo', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'escola', + tableField: 'ano_censo', + where: { + relation: '<=', + type: 'integer', + field:'ano_censo' + } +}).addValue({ + name: 'region', + table: 'escola', + tableField: 'regiao_id', + where: { + relation: '=', + type: 'integer', + field: 'regiao_id' + } +}).addValue({ + name: 'region_not', + table: 'escola', + tableField: 'regiao_id', + where: { + relation: '<>', + type: 'integer', + field: 'regiao_id' + } +}).addValue({ + name: 'city', + table: 'escola', + tableField: 'municipio_id', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id' + } +}).addValue({ + name: 'city_not', + table: 'escola', + tableField: 'municipio_id', + where: { + relation: '<>', + type: 'integer', + field: 'municipio_id' + } +}).addValue({ + name: 'state', + table: 'escola', + tableField: 'estado_id', + where: { + relation: '=', + type: 'integer', + field: 'estado_id' + } +}).addValue({ + name: 'state_not', + table: 'escola', + tableField: 'estado_id', + where: { + relation: '<>', + type: 'integer', + field: 'estado_id' + } +}).addValue({ + name: 'dep_admin', + table: 'escola', + tableField: 'dependencia_adm_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'dep_pub_ins', + table: 'escola', + tableField: 'dependencia_convenio_publico', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_convenio_publico' + } +}).addValue({ + name: 'arrangement', + table: 'escola', + tableField: 'arranjo', + where: { + relation: '=', + type: 'integer', + field: 'arranjo' + } +}).addValue({ + name: 'location', + table: 'escola', + tableField: 'localizacao_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'diff_location', + table: 'escola', + tableField: 'localizacao_diferenciada_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_id' + } +}).addValue({ + name: 'full_time', + table: 'escola', + tableField: 'tempo_integral', + where: { + relation: '=', + type: 'integer', + field: 'tempo_integral' + } +}); + +testApp.get('/', rqf.parse(), rqf.build(), reqBody.parse(), (req, res, next) => { + req.sql.from('escola') + .field('ano_censo') + .field('count(*)', 'total') + .group('ano_censo').order('ano_censo') + .where('escola.situacao_funcionamento_pareada = 1 AND (escola.ensino_regular = 1 OR escola.ensino_eja=1 or escola.educacao_profissional=1)') + console.log(req.sql.toString()); + next(); +}, query, response('school')); + +module.exports = testApp; \ No newline at end of file -- GitLab From d07a81ab116bb005562be8614596155e56c7b443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Wed, 1 Mar 2023 11:29:52 -0300 Subject: [PATCH 052/123] Add functional version of middleware, add flag to check whether it runs default query or modified query --- src/libs/middlewares/reqBody.js | 37 ++++++++++++++++++++++++++++++++- src/libs/routes/testroute.js | 21 +++++++++++++------ 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/libs/middlewares/reqBody.js b/src/libs/middlewares/reqBody.js index e1f80cb1..9df7ebca 100644 --- a/src/libs/middlewares/reqBody.js +++ b/src/libs/middlewares/reqBody.js @@ -2,6 +2,32 @@ class ReqBody { constructor() { } + + add_metrics(req, column, metricsArray) { + for (let i in metricsArray) { + switch(metricsArray[i]["function"]) { + case "max": + req.sql.field("max(" + column + ")", metricsArray[i]["return_name"]); + req.hasMetrics = true; + break; + case "min": + req.sql.field("min(" + column + ")", metricsArray[i]["return_name"]); + req.hasMetrics = true; + break; + case "count": + req.sql.field("count(" + column + ")", metricsArray[i]["return_name"]); + req.hasMetrics = true; + break; + case "sum": + req.sql.field("sum(" + column + ")", metricsArray[i]["return_name"]); + req.hasMetrics = true; + break; + default: + break; + } + } + } + parse() { return(req, res, next) => { // Gets body of the HTTP requisition @@ -10,8 +36,17 @@ class ReqBody { // Chooses operation based on the mode field of the body switch(body["mode"]) { case "add_metrics": - console.log(body); + // adds flag to check whether it runs the default query or not + req.hasMetrics = false; + // Gets all column names + let columns = Object.keys(body["add_metrics"]); + // Calls function to add metrics that were specified to req.sql + for (let i in columns) { + this.add_metrics(req, columns[i], body["add_metrics"][columns[i]]); + } + break; + default: break; } diff --git a/src/libs/routes/testroute.js b/src/libs/routes/testroute.js index 2f108eb7..97e28b90 100644 --- a/src/libs/routes/testroute.js +++ b/src/libs/routes/testroute.js @@ -176,12 +176,21 @@ rqf.addField({ }); testApp.get('/', rqf.parse(), rqf.build(), reqBody.parse(), (req, res, next) => { - req.sql.from('escola') - .field('ano_censo') - .field('count(*)', 'total') - .group('ano_censo').order('ano_censo') - .where('escola.situacao_funcionamento_pareada = 1 AND (escola.ensino_regular = 1 OR escola.ensino_eja=1 or escola.educacao_profissional=1)') - console.log(req.sql.toString()); + // Runs default query + if (!req.hasMetrics) { + req.sql.from('escola') + .field('ano_censo') + .field('count(*)', 'total') + .group('ano_censo').order('ano_censo') + .where('escola.situacao_funcionamento_pareada = 1 AND (escola.ensino_regular = 1 OR escola.ensino_eja=1 or escola.educacao_profissional=1)') + } + // Runs modified query + else { + req.sql.from('escola') + .field('ano_censo') + .group('ano_censo').order('ano_censo') + .where('escola.situacao_funcionamento_pareada = 1 AND (escola.ensino_regular = 1 OR escola.ensino_eja=1 or escola.educacao_profissional=1)') + } next(); }, query, response('school')); -- GitLab From 791da624ca698a4bf857649e8157ba5f44d2c7f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 3 Mar 2023 09:29:20 -0300 Subject: [PATCH 053/123] Remove test route --- src/libs/routes/api.js | 4 - src/libs/routes/testroute.js | 197 ----------------------------------- 2 files changed, 201 deletions(-) delete mode 100644 src/libs/routes/testroute.js diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js index 1a68a1d4..f6715eaa 100644 --- a/src/libs/routes/api.js +++ b/src/libs/routes/api.js @@ -134,8 +134,6 @@ const message = require(`${libs}/routes/message`); const courseStudents = require(`${libs}/routes/courseStudents`); -const testRoute = require(`${libs}/routes/testroute`); - api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API is running' }); }); @@ -195,6 +193,4 @@ api.use('/universityLocalOffer', universityLocalOffer); api.use('/message', message); api.use('/course_students', courseStudents); -api.use('/test', testRoute); - module.exports = api; diff --git a/src/libs/routes/testroute.js b/src/libs/routes/testroute.js deleted file mode 100644 index 97e28b90..00000000 --- a/src/libs/routes/testroute.js +++ /dev/null @@ -1,197 +0,0 @@ -/* -Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre -Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR - -This file is part of simcaq-node. - -simcaq-node is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -simcaq-node is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. -*/ - -const express = require('express'); - -const testApp = express.Router(); - -const libs = `${process.cwd()}/libs`; - -const squel = require('squel'); - -const query = require(`${libs}/middlewares/query`).query; - -const response = require(`${libs}/middlewares/response`); - -const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); - -const ReqBody = require(`${libs}/middlewares/reqBody`); - -const config = require(`${libs}/config`); - -const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; - -let rqf = new ReqQueryFields(); -let reqBody = new ReqBody(); - -testApp.use(cache('15 day')); - -rqf.addField({ - name: 'filter', - field: false, - where: true -}).addValue({ - name: 'min_year', - table: 'escola', - tableField: 'ano_censo', - where: { - relation: '>=', - type: 'integer', - field: 'ano_censo' - } -}).addValue({ - name: 'max_year', - table: 'escola', - tableField: 'ano_censo', - where: { - relation: '<=', - type: 'integer', - field:'ano_censo' - } -}).addValue({ - name: 'region', - table: 'escola', - tableField: 'regiao_id', - where: { - relation: '=', - type: 'integer', - field: 'regiao_id' - } -}).addValue({ - name: 'region_not', - table: 'escola', - tableField: 'regiao_id', - where: { - relation: '<>', - type: 'integer', - field: 'regiao_id' - } -}).addValue({ - name: 'city', - table: 'escola', - tableField: 'municipio_id', - where: { - relation: '=', - type: 'integer', - field: 'municipio_id' - } -}).addValue({ - name: 'city_not', - table: 'escola', - tableField: 'municipio_id', - where: { - relation: '<>', - type: 'integer', - field: 'municipio_id' - } -}).addValue({ - name: 'state', - table: 'escola', - tableField: 'estado_id', - where: { - relation: '=', - type: 'integer', - field: 'estado_id' - } -}).addValue({ - name: 'state_not', - table: 'escola', - tableField: 'estado_id', - where: { - relation: '<>', - type: 'integer', - field: 'estado_id' - } -}).addValue({ - name: 'dep_admin', - table: 'escola', - tableField: 'dependencia_adm_id', - where: { - relation: '=', - type: 'integer', - field: 'dependencia_adm_id' - } -}).addValue({ - name: 'dep_pub_ins', - table: 'escola', - tableField: 'dependencia_convenio_publico', - where: { - relation: '=', - type: 'integer', - field: 'dependencia_convenio_publico' - } -}).addValue({ - name: 'arrangement', - table: 'escola', - tableField: 'arranjo', - where: { - relation: '=', - type: 'integer', - field: 'arranjo' - } -}).addValue({ - name: 'location', - table: 'escola', - tableField: 'localizacao_id', - where: { - relation: '=', - type: 'integer', - field: 'localizacao_id' - } -}).addValue({ - name: 'diff_location', - table: 'escola', - tableField: 'localizacao_diferenciada_id', - where: { - relation: '=', - type: 'integer', - field: 'localizacao_diferenciada_id' - } -}).addValue({ - name: 'full_time', - table: 'escola', - tableField: 'tempo_integral', - where: { - relation: '=', - type: 'integer', - field: 'tempo_integral' - } -}); - -testApp.get('/', rqf.parse(), rqf.build(), reqBody.parse(), (req, res, next) => { - // Runs default query - if (!req.hasMetrics) { - req.sql.from('escola') - .field('ano_censo') - .field('count(*)', 'total') - .group('ano_censo').order('ano_censo') - .where('escola.situacao_funcionamento_pareada = 1 AND (escola.ensino_regular = 1 OR escola.ensino_eja=1 or escola.educacao_profissional=1)') - } - // Runs modified query - else { - req.sql.from('escola') - .field('ano_censo') - .group('ano_censo').order('ano_censo') - .where('escola.situacao_funcionamento_pareada = 1 AND (escola.ensino_regular = 1 OR escola.ensino_eja=1 or escola.educacao_profissional=1)') - } - next(); -}, query, response('school')); - -module.exports = testApp; \ No newline at end of file -- GitLab From f28d30f7883129cb164cb8033d6a3c8b0202bcc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 3 Mar 2023 11:09:46 -0300 Subject: [PATCH 054/123] Create v2 version, adapt app.js to use both versions --- src/libs/app.js | 8 +- src/libs/{routes => routes_v1}/api.js | 70 +- src/libs/{routes => routes_v1}/auxiliar.js | 0 src/libs/{routes => routes_v1}/city.js | 0 src/libs/{routes => routes_v1}/class.js | 0 src/libs/{routes => routes_v1}/classCount.js | 0 src/libs/{routes => routes_v1}/classroom.js | 0 .../{routes => routes_v1}/classroomCount.js | 0 src/libs/{routes => routes_v1}/courseCount.js | 0 .../{routes => routes_v1}/courseStudents.js | 0 src/libs/{routes => routes_v1}/cub.js | 0 .../dailyChargeAmount.js | 0 src/libs/{routes => routes_v1}/disciplines.js | 0 .../distributionFactor.js | 0 src/libs/{routes => routes_v1}/downloads.js | 0 .../{routes => routes_v1}/educationYears.js | 0 .../educationalBudget.js | 0 src/libs/{routes => routes_v1}/employees.js | 0 src/libs/{routes => routes_v1}/enrollment.js | 0 .../enrollmentProjection.js | 0 src/libs/{routes => routes_v1}/financial.js | 0 .../glossEnrollmentRatio.js | 0 src/libs/{routes => routes_v1}/idhm.js | 0 src/libs/{routes => routes_v1}/idhme.js | 0 src/libs/{routes => routes_v1}/idhml.js | 0 src/libs/{routes => routes_v1}/idhmr.js | 0 .../{routes => routes_v1}/infrastructure.js | 0 .../liquidEnrollmentRatio.js | 0 src/libs/{routes => routes_v1}/location.js | 0 src/libs/{routes => routes_v1}/mesoregion.js | 0 src/libs/{routes => routes_v1}/message.js | 0 src/libs/{routes => routes_v1}/microregion.js | 0 src/libs/{routes => routes_v1}/outOfSchool.js | 0 .../{routes => routes_v1}/pibpercapita.js | 0 src/libs/{routes => routes_v1}/population.js | 0 src/libs/{routes => routes_v1}/portalMec.js | 0 .../{routes => routes_v1}/portalMecInep.js | 0 src/libs/{routes => routes_v1}/rateSchool.js | 0 src/libs/{routes => routes_v1}/region.js | 0 src/libs/{routes => routes_v1}/resetToken.js | 0 src/libs/routes_v1/school.js | 663 +++++++++ .../schoolInfrastructure.js | 0 .../{routes => routes_v1}/schoolLocation.js | 0 src/libs/{routes => routes_v1}/simulation.js | 0 src/libs/{routes => routes_v1}/siope.js | 0 src/libs/{routes => routes_v1}/spatial.js | 0 src/libs/{routes => routes_v1}/state.js | 0 src/libs/{routes => routes_v1}/studentsAee.js | 0 src/libs/{routes => routes_v1}/teacher.js | 0 src/libs/{routes => routes_v1}/transport.js | 0 src/libs/{routes => routes_v1}/university.js | 0 .../universityEnrollment.js | 0 .../universityLocalOffer.js | 0 .../universityTeacher.js | 0 src/libs/{routes => routes_v1}/user.js | 0 src/libs/{routes => routes_v1}/verifyToken.js | 0 src/libs/routes_v2/api.js | 196 +++ src/libs/routes_v2/auxiliar.js | 397 ++++++ src/libs/routes_v2/city.js | 151 +++ src/libs/routes_v2/class.js | 402 ++++++ src/libs/routes_v2/classCount.js | 455 +++++++ src/libs/routes_v2/classroom.js | 277 ++++ src/libs/routes_v2/classroomCount.js | 1172 ++++++++++++++++ src/libs/routes_v2/courseCount.js | 814 +++++++++++ src/libs/routes_v2/courseStudents.js | 201 +++ src/libs/routes_v2/cub.js | 227 ++++ src/libs/routes_v2/dailyChargeAmount.js | 467 +++++++ src/libs/routes_v2/disciplines.js | 682 ++++++++++ src/libs/routes_v2/distributionFactor.js | 210 +++ src/libs/routes_v2/downloads.js | 54 + src/libs/routes_v2/educationYears.js | 46 + src/libs/routes_v2/educationalBudget.js | 325 +++++ src/libs/routes_v2/employees.js | 656 +++++++++ src/libs/routes_v2/enrollment.js | 1204 +++++++++++++++++ src/libs/routes_v2/enrollmentProjection.js | 239 ++++ src/libs/routes_v2/financial.js | 186 +++ src/libs/routes_v2/glossEnrollmentRatio.js | 390 ++++++ src/libs/routes_v2/idhm.js | 212 +++ src/libs/routes_v2/idhme.js | 185 +++ src/libs/routes_v2/idhml.js | 185 +++ src/libs/routes_v2/idhmr.js | 188 +++ src/libs/routes_v2/infrastructure.js | 585 ++++++++ src/libs/routes_v2/liquidEnrollmentRatio.js | 434 ++++++ src/libs/routes_v2/location.js | 135 ++ src/libs/routes_v2/mesoregion.js | 86 ++ src/libs/routes_v2/message.js | 55 + src/libs/routes_v2/microregion.js | 99 ++ src/libs/routes_v2/outOfSchool.js | 377 ++++++ src/libs/routes_v2/pibpercapita.js | 250 ++++ src/libs/routes_v2/population.js | 163 +++ src/libs/routes_v2/portalMec.js | 136 ++ src/libs/routes_v2/portalMecInep.js | 60 + src/libs/routes_v2/rateSchool.js | 337 +++++ src/libs/routes_v2/region.js | 72 + src/libs/routes_v2/resetToken.js | 81 ++ src/libs/{routes => routes_v2}/school.js | 0 src/libs/routes_v2/schoolInfrastructure.js | 741 ++++++++++ src/libs/routes_v2/schoolLocation.js | 114 ++ src/libs/routes_v2/simulation.js | 167 +++ src/libs/routes_v2/siope.js | 186 +++ src/libs/routes_v2/spatial.js | 373 +++++ src/libs/routes_v2/state.js | 108 ++ src/libs/routes_v2/studentsAee.js | 219 +++ src/libs/routes_v2/teacher.js | 576 ++++++++ src/libs/routes_v2/transport.js | 400 ++++++ src/libs/routes_v2/university.js | 347 +++++ src/libs/routes_v2/universityEnrollment.js | 848 ++++++++++++ src/libs/routes_v2/universityLocalOffer.js | 170 +++ src/libs/routes_v2/universityTeacher.js | 517 +++++++ src/libs/routes_v2/user.js | 305 +++++ src/libs/routes_v2/verifyToken.js | 52 + 111 files changed, 18218 insertions(+), 37 deletions(-) rename src/libs/{routes => routes_v1}/api.js (63%) rename src/libs/{routes => routes_v1}/auxiliar.js (100%) rename src/libs/{routes => routes_v1}/city.js (100%) rename src/libs/{routes => routes_v1}/class.js (100%) rename src/libs/{routes => routes_v1}/classCount.js (100%) rename src/libs/{routes => routes_v1}/classroom.js (100%) rename src/libs/{routes => routes_v1}/classroomCount.js (100%) rename src/libs/{routes => routes_v1}/courseCount.js (100%) rename src/libs/{routes => routes_v1}/courseStudents.js (100%) rename src/libs/{routes => routes_v1}/cub.js (100%) rename src/libs/{routes => routes_v1}/dailyChargeAmount.js (100%) rename src/libs/{routes => routes_v1}/disciplines.js (100%) rename src/libs/{routes => routes_v1}/distributionFactor.js (100%) rename src/libs/{routes => routes_v1}/downloads.js (100%) rename src/libs/{routes => routes_v1}/educationYears.js (100%) rename src/libs/{routes => routes_v1}/educationalBudget.js (100%) rename src/libs/{routes => routes_v1}/employees.js (100%) rename src/libs/{routes => routes_v1}/enrollment.js (100%) rename src/libs/{routes => routes_v1}/enrollmentProjection.js (100%) rename src/libs/{routes => routes_v1}/financial.js (100%) rename src/libs/{routes => routes_v1}/glossEnrollmentRatio.js (100%) rename src/libs/{routes => routes_v1}/idhm.js (100%) rename src/libs/{routes => routes_v1}/idhme.js (100%) rename src/libs/{routes => routes_v1}/idhml.js (100%) rename src/libs/{routes => routes_v1}/idhmr.js (100%) rename src/libs/{routes => routes_v1}/infrastructure.js (100%) rename src/libs/{routes => routes_v1}/liquidEnrollmentRatio.js (100%) rename src/libs/{routes => routes_v1}/location.js (100%) rename src/libs/{routes => routes_v1}/mesoregion.js (100%) rename src/libs/{routes => routes_v1}/message.js (100%) rename src/libs/{routes => routes_v1}/microregion.js (100%) rename src/libs/{routes => routes_v1}/outOfSchool.js (100%) rename src/libs/{routes => routes_v1}/pibpercapita.js (100%) rename src/libs/{routes => routes_v1}/population.js (100%) rename src/libs/{routes => routes_v1}/portalMec.js (100%) rename src/libs/{routes => routes_v1}/portalMecInep.js (100%) rename src/libs/{routes => routes_v1}/rateSchool.js (100%) rename src/libs/{routes => routes_v1}/region.js (100%) rename src/libs/{routes => routes_v1}/resetToken.js (100%) create mode 100644 src/libs/routes_v1/school.js rename src/libs/{routes => routes_v1}/schoolInfrastructure.js (100%) rename src/libs/{routes => routes_v1}/schoolLocation.js (100%) rename src/libs/{routes => routes_v1}/simulation.js (100%) rename src/libs/{routes => routes_v1}/siope.js (100%) rename src/libs/{routes => routes_v1}/spatial.js (100%) rename src/libs/{routes => routes_v1}/state.js (100%) rename src/libs/{routes => routes_v1}/studentsAee.js (100%) rename src/libs/{routes => routes_v1}/teacher.js (100%) rename src/libs/{routes => routes_v1}/transport.js (100%) rename src/libs/{routes => routes_v1}/university.js (100%) rename src/libs/{routes => routes_v1}/universityEnrollment.js (100%) rename src/libs/{routes => routes_v1}/universityLocalOffer.js (100%) rename src/libs/{routes => routes_v1}/universityTeacher.js (100%) rename src/libs/{routes => routes_v1}/user.js (100%) rename src/libs/{routes => routes_v1}/verifyToken.js (100%) create mode 100644 src/libs/routes_v2/api.js create mode 100644 src/libs/routes_v2/auxiliar.js create mode 100644 src/libs/routes_v2/city.js create mode 100644 src/libs/routes_v2/class.js create mode 100644 src/libs/routes_v2/classCount.js create mode 100644 src/libs/routes_v2/classroom.js create mode 100644 src/libs/routes_v2/classroomCount.js create mode 100644 src/libs/routes_v2/courseCount.js create mode 100644 src/libs/routes_v2/courseStudents.js create mode 100644 src/libs/routes_v2/cub.js create mode 100644 src/libs/routes_v2/dailyChargeAmount.js create mode 100644 src/libs/routes_v2/disciplines.js create mode 100644 src/libs/routes_v2/distributionFactor.js create mode 100644 src/libs/routes_v2/downloads.js create mode 100644 src/libs/routes_v2/educationYears.js create mode 100644 src/libs/routes_v2/educationalBudget.js create mode 100644 src/libs/routes_v2/employees.js create mode 100644 src/libs/routes_v2/enrollment.js create mode 100644 src/libs/routes_v2/enrollmentProjection.js create mode 100644 src/libs/routes_v2/financial.js create mode 100644 src/libs/routes_v2/glossEnrollmentRatio.js create mode 100644 src/libs/routes_v2/idhm.js create mode 100644 src/libs/routes_v2/idhme.js create mode 100644 src/libs/routes_v2/idhml.js create mode 100644 src/libs/routes_v2/idhmr.js create mode 100644 src/libs/routes_v2/infrastructure.js create mode 100644 src/libs/routes_v2/liquidEnrollmentRatio.js create mode 100644 src/libs/routes_v2/location.js create mode 100644 src/libs/routes_v2/mesoregion.js create mode 100644 src/libs/routes_v2/message.js create mode 100644 src/libs/routes_v2/microregion.js create mode 100644 src/libs/routes_v2/outOfSchool.js create mode 100644 src/libs/routes_v2/pibpercapita.js create mode 100644 src/libs/routes_v2/population.js create mode 100644 src/libs/routes_v2/portalMec.js create mode 100644 src/libs/routes_v2/portalMecInep.js create mode 100644 src/libs/routes_v2/rateSchool.js create mode 100644 src/libs/routes_v2/region.js create mode 100644 src/libs/routes_v2/resetToken.js rename src/libs/{routes => routes_v2}/school.js (100%) create mode 100644 src/libs/routes_v2/schoolInfrastructure.js create mode 100644 src/libs/routes_v2/schoolLocation.js create mode 100644 src/libs/routes_v2/simulation.js create mode 100644 src/libs/routes_v2/siope.js create mode 100644 src/libs/routes_v2/spatial.js create mode 100644 src/libs/routes_v2/state.js create mode 100644 src/libs/routes_v2/studentsAee.js create mode 100644 src/libs/routes_v2/teacher.js create mode 100644 src/libs/routes_v2/transport.js create mode 100644 src/libs/routes_v2/university.js create mode 100644 src/libs/routes_v2/universityEnrollment.js create mode 100644 src/libs/routes_v2/universityLocalOffer.js create mode 100644 src/libs/routes_v2/universityTeacher.js create mode 100644 src/libs/routes_v2/user.js create mode 100644 src/libs/routes_v2/verifyToken.js diff --git a/src/libs/app.js b/src/libs/app.js index b8b953c1..9f185105 100644 --- a/src/libs/app.js +++ b/src/libs/app.js @@ -14,7 +14,8 @@ const config = require(`${libs}/config`); const app = express(); -const api = require('./routes/api'); +const api_v1 = require('./routes_v1/api'); +const api_v2 = require('./routes_v2/api'); const passport = require('passport'); @@ -65,7 +66,10 @@ app.use((req, res, next) => { next(); }); // Mounts all API routes under /api/v1 -app.use('/api/v1', api); +app.use('/api/v1', api_v1); + +// Mounts all API routes under /api/v2 +app.use('/api/v2', api_v2); // Catch 404 and forward to error handler app.use((req, res, next) => { diff --git a/src/libs/routes/api.js b/src/libs/routes_v1/api.js similarity index 63% rename from src/libs/routes/api.js rename to src/libs/routes_v1/api.js index f6715eaa..4b6a5630 100644 --- a/src/libs/routes/api.js +++ b/src/libs/routes_v1/api.js @@ -66,79 +66,79 @@ const idhml = require('./idhml'); const oauth2 = require(`${libs}/middlewares/oauth2`); -const verifyToken = require(`${libs}/routes/verifyToken`); +const verifyToken = require(`${libs}/routes_v1/verifyToken`); -const resetToken = require(`${libs}/routes/resetToken`); +const resetToken = require(`${libs}/routes_v1/resetToken`); -const educationYears = require(`${libs}/routes/educationYears`); +const educationYears = require(`${libs}/routes_v1/educationYears`); -const downloads = require(`${libs}/routes/downloads`); +const downloads = require(`${libs}/routes_v1/downloads`); -const infrastructure = require(`${libs}/routes/infrastructure`); +const infrastructure = require(`${libs}/routes_v1/infrastructure`); -const schoolInfrastructure = require(`${libs}/routes/schoolInfrastructure`); +const schoolInfrastructure = require(`${libs}/routes_v1/schoolInfrastructure`); -const distributionFactor = require(`${libs}/routes/distributionFactor`); +const distributionFactor = require(`${libs}/routes_v1/distributionFactor`); -const siope = require(`${libs}/routes/siope`); +const siope = require(`${libs}/routes_v1/siope`); -const verifyTeacher = require(`${libs}/routes/portalMec`); +const verifyTeacher = require(`${libs}/routes_v1/portalMec`); -const outOfSchool = require(`${libs}/routes/outOfSchool`); +const outOfSchool = require(`${libs}/routes_v1/outOfSchool`); -const classroomCount = require(`${libs}/routes/classroomCount`); +const classroomCount = require(`${libs}/routes_v1/classroomCount`); const transport = require(`./transport`); -const auxiliar = require(`${libs}/routes/auxiliar`); +const auxiliar = require(`${libs}/routes_v1/auxiliar`); -const dailyChargeAmount = require(`${libs}/routes/dailyChargeAmount`); +const dailyChargeAmount = require(`${libs}/routes_v1/dailyChargeAmount`); -const cub = require(`${libs}/routes/cub`); +const cub = require(`${libs}/routes_v1/cub`); -const classCount = require(`${libs}/routes/classCount`); +const classCount = require(`${libs}/routes_v1/classCount`); -const portalMecInep = require(`${libs}/routes/portalMecInep`); +const portalMecInep = require(`${libs}/routes_v1/portalMecInep`); -const enrollmentProjection = require(`${libs}/routes/enrollmentProjection`); +const enrollmentProjection = require(`${libs}/routes_v1/enrollmentProjection`); -const employees = require(`${libs}/routes/employees`); +const employees = require(`${libs}/routes_v1/employees`); -const financial = require(`${libs}/routes/financial`); +const financial = require(`${libs}/routes_v1/financial`); -const universityEnrollment = require(`${libs}/routes/universityEnrollment`); +const universityEnrollment = require(`${libs}/routes_v1/universityEnrollment`); -const courseCount = require(`${libs}/routes/courseCount`); +const courseCount = require(`${libs}/routes_v1/courseCount`); -const university = require(`${libs}/routes/university`); +const university = require(`${libs}/routes_v1/university`); -const universityTeacher = require(`${libs}/routes/universityTeacher`); +const universityTeacher = require(`${libs}/routes_v1/universityTeacher`); -const educationalBudget = require(`${libs}/routes/educationalBudget`); +const educationalBudget = require(`${libs}/routes_v1/educationalBudget`); -const schoolLocation = require(`${libs}/routes/schoolLocation`); +const schoolLocation = require(`${libs}/routes_v1/schoolLocation`); -const studentsAee = require(`${libs}/routes/studentsAee`); +const studentsAee = require(`${libs}/routes_v1/studentsAee`); -const mesoregion = require(`${libs}/routes/mesoregion`); +const mesoregion = require(`${libs}/routes_v1/mesoregion`); -const microregion = require(`${libs}/routes/microregion`); +const microregion = require(`${libs}/routes_v1/microregion`); -const location = require(`${libs}/routes/location`); +const location = require(`${libs}/routes_v1/location`); -const disciplines = require(`${libs}/routes/disciplines`); +const disciplines = require(`${libs}/routes_v1/disciplines`); -const universityLocalOffer = require(`${libs}/routes/universityLocalOffer`); +const universityLocalOffer = require(`${libs}/routes_v1/universityLocalOffer`); -const message = require(`${libs}/routes/message`); +const message = require(`${libs}/routes_v1/message`); -const courseStudents = require(`${libs}/routes/courseStudents`); +const courseStudents = require(`${libs}/routes_v1/courseStudents`); api.get('/', (req, res) => { - res.json({ msg: 'SimCAQ API is running' }); + res.json({ msg: 'SimCAQ API v1 is running' }); }); -// mount API routes +// mount API routes_v1 api.use('/user', user); api.use('/simulation', simulation); api.use('/class', classes); diff --git a/src/libs/routes/auxiliar.js b/src/libs/routes_v1/auxiliar.js similarity index 100% rename from src/libs/routes/auxiliar.js rename to src/libs/routes_v1/auxiliar.js diff --git a/src/libs/routes/city.js b/src/libs/routes_v1/city.js similarity index 100% rename from src/libs/routes/city.js rename to src/libs/routes_v1/city.js diff --git a/src/libs/routes/class.js b/src/libs/routes_v1/class.js similarity index 100% rename from src/libs/routes/class.js rename to src/libs/routes_v1/class.js diff --git a/src/libs/routes/classCount.js b/src/libs/routes_v1/classCount.js similarity index 100% rename from src/libs/routes/classCount.js rename to src/libs/routes_v1/classCount.js diff --git a/src/libs/routes/classroom.js b/src/libs/routes_v1/classroom.js similarity index 100% rename from src/libs/routes/classroom.js rename to src/libs/routes_v1/classroom.js diff --git a/src/libs/routes/classroomCount.js b/src/libs/routes_v1/classroomCount.js similarity index 100% rename from src/libs/routes/classroomCount.js rename to src/libs/routes_v1/classroomCount.js diff --git a/src/libs/routes/courseCount.js b/src/libs/routes_v1/courseCount.js similarity index 100% rename from src/libs/routes/courseCount.js rename to src/libs/routes_v1/courseCount.js diff --git a/src/libs/routes/courseStudents.js b/src/libs/routes_v1/courseStudents.js similarity index 100% rename from src/libs/routes/courseStudents.js rename to src/libs/routes_v1/courseStudents.js diff --git a/src/libs/routes/cub.js b/src/libs/routes_v1/cub.js similarity index 100% rename from src/libs/routes/cub.js rename to src/libs/routes_v1/cub.js diff --git a/src/libs/routes/dailyChargeAmount.js b/src/libs/routes_v1/dailyChargeAmount.js similarity index 100% rename from src/libs/routes/dailyChargeAmount.js rename to src/libs/routes_v1/dailyChargeAmount.js diff --git a/src/libs/routes/disciplines.js b/src/libs/routes_v1/disciplines.js similarity index 100% rename from src/libs/routes/disciplines.js rename to src/libs/routes_v1/disciplines.js diff --git a/src/libs/routes/distributionFactor.js b/src/libs/routes_v1/distributionFactor.js similarity index 100% rename from src/libs/routes/distributionFactor.js rename to src/libs/routes_v1/distributionFactor.js diff --git a/src/libs/routes/downloads.js b/src/libs/routes_v1/downloads.js similarity index 100% rename from src/libs/routes/downloads.js rename to src/libs/routes_v1/downloads.js diff --git a/src/libs/routes/educationYears.js b/src/libs/routes_v1/educationYears.js similarity index 100% rename from src/libs/routes/educationYears.js rename to src/libs/routes_v1/educationYears.js diff --git a/src/libs/routes/educationalBudget.js b/src/libs/routes_v1/educationalBudget.js similarity index 100% rename from src/libs/routes/educationalBudget.js rename to src/libs/routes_v1/educationalBudget.js diff --git a/src/libs/routes/employees.js b/src/libs/routes_v1/employees.js similarity index 100% rename from src/libs/routes/employees.js rename to src/libs/routes_v1/employees.js diff --git a/src/libs/routes/enrollment.js b/src/libs/routes_v1/enrollment.js similarity index 100% rename from src/libs/routes/enrollment.js rename to src/libs/routes_v1/enrollment.js diff --git a/src/libs/routes/enrollmentProjection.js b/src/libs/routes_v1/enrollmentProjection.js similarity index 100% rename from src/libs/routes/enrollmentProjection.js rename to src/libs/routes_v1/enrollmentProjection.js diff --git a/src/libs/routes/financial.js b/src/libs/routes_v1/financial.js similarity index 100% rename from src/libs/routes/financial.js rename to src/libs/routes_v1/financial.js diff --git a/src/libs/routes/glossEnrollmentRatio.js b/src/libs/routes_v1/glossEnrollmentRatio.js similarity index 100% rename from src/libs/routes/glossEnrollmentRatio.js rename to src/libs/routes_v1/glossEnrollmentRatio.js diff --git a/src/libs/routes/idhm.js b/src/libs/routes_v1/idhm.js similarity index 100% rename from src/libs/routes/idhm.js rename to src/libs/routes_v1/idhm.js diff --git a/src/libs/routes/idhme.js b/src/libs/routes_v1/idhme.js similarity index 100% rename from src/libs/routes/idhme.js rename to src/libs/routes_v1/idhme.js diff --git a/src/libs/routes/idhml.js b/src/libs/routes_v1/idhml.js similarity index 100% rename from src/libs/routes/idhml.js rename to src/libs/routes_v1/idhml.js diff --git a/src/libs/routes/idhmr.js b/src/libs/routes_v1/idhmr.js similarity index 100% rename from src/libs/routes/idhmr.js rename to src/libs/routes_v1/idhmr.js diff --git a/src/libs/routes/infrastructure.js b/src/libs/routes_v1/infrastructure.js similarity index 100% rename from src/libs/routes/infrastructure.js rename to src/libs/routes_v1/infrastructure.js diff --git a/src/libs/routes/liquidEnrollmentRatio.js b/src/libs/routes_v1/liquidEnrollmentRatio.js similarity index 100% rename from src/libs/routes/liquidEnrollmentRatio.js rename to src/libs/routes_v1/liquidEnrollmentRatio.js diff --git a/src/libs/routes/location.js b/src/libs/routes_v1/location.js similarity index 100% rename from src/libs/routes/location.js rename to src/libs/routes_v1/location.js diff --git a/src/libs/routes/mesoregion.js b/src/libs/routes_v1/mesoregion.js similarity index 100% rename from src/libs/routes/mesoregion.js rename to src/libs/routes_v1/mesoregion.js diff --git a/src/libs/routes/message.js b/src/libs/routes_v1/message.js similarity index 100% rename from src/libs/routes/message.js rename to src/libs/routes_v1/message.js diff --git a/src/libs/routes/microregion.js b/src/libs/routes_v1/microregion.js similarity index 100% rename from src/libs/routes/microregion.js rename to src/libs/routes_v1/microregion.js diff --git a/src/libs/routes/outOfSchool.js b/src/libs/routes_v1/outOfSchool.js similarity index 100% rename from src/libs/routes/outOfSchool.js rename to src/libs/routes_v1/outOfSchool.js diff --git a/src/libs/routes/pibpercapita.js b/src/libs/routes_v1/pibpercapita.js similarity index 100% rename from src/libs/routes/pibpercapita.js rename to src/libs/routes_v1/pibpercapita.js diff --git a/src/libs/routes/population.js b/src/libs/routes_v1/population.js similarity index 100% rename from src/libs/routes/population.js rename to src/libs/routes_v1/population.js diff --git a/src/libs/routes/portalMec.js b/src/libs/routes_v1/portalMec.js similarity index 100% rename from src/libs/routes/portalMec.js rename to src/libs/routes_v1/portalMec.js diff --git a/src/libs/routes/portalMecInep.js b/src/libs/routes_v1/portalMecInep.js similarity index 100% rename from src/libs/routes/portalMecInep.js rename to src/libs/routes_v1/portalMecInep.js diff --git a/src/libs/routes/rateSchool.js b/src/libs/routes_v1/rateSchool.js similarity index 100% rename from src/libs/routes/rateSchool.js rename to src/libs/routes_v1/rateSchool.js diff --git a/src/libs/routes/region.js b/src/libs/routes_v1/region.js similarity index 100% rename from src/libs/routes/region.js rename to src/libs/routes_v1/region.js diff --git a/src/libs/routes/resetToken.js b/src/libs/routes_v1/resetToken.js similarity index 100% rename from src/libs/routes/resetToken.js rename to src/libs/routes_v1/resetToken.js diff --git a/src/libs/routes_v1/school.js b/src/libs/routes_v1/school.js new file mode 100644 index 00000000..73b765e2 --- /dev/null +++ b/src/libs/routes_v1/school.js @@ -0,0 +1,663 @@ +const express = require('express'); + +const schoolApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const passport = require('passport'); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); +let rqfCount = new ReqQueryFields(); + +// Return location +schoolApp.get('/year_range', cache('15 day'), (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')); + +schoolApp.get('/years', cache('15 day'), (req, res, next) => { + req.sql.from('escola'). + field('DISTINCT escola.ano_censo', 'year'); + next(); +}, query, response('years')); + +schoolApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'escola\''); + next(); +}, query, response('source')); + +schoolApp.get('/location', cache('15 day'), (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +schoolApp.get('/diff_location', cache('15 day'), (req, res, next) => { + req.result = [ + {id: 0, name: "Não está em localidade diferenciada"}, + {id: 1, name: "Ãrea de assentamento"}, + {id: 2, name: "Terra indÃgena"}, + {id: 3, name: "Terra remanescente de quilombos"}, + ]; + next(); +}, response('diff_location')); + +schoolApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +schoolApp.get('/adm_dependency_detailed', cache('15 day'), (req, res, next) => { + req.result = []; + for(let i = 1; i <= 8; i++) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +schoolApp.get('/government_agreement', cache('15 day'), (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.governmentAgreement("null") + }]; + for(let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.governmentAgreement(i) + }); + }; + next(); +}, response('government_agreement')); + +schoolApp.get('/agreement', cache('15 day'), (req, res, next) => { + req.result = [ + {id: 1, name: 'Municipal'}, + {id: 2, name: 'Estadual'}, + {id: 3, name: 'Estadual e Municipal'} + ]; + next(); +}, response('agreement')); + +schoolApp.get('/education_day_care_child', (req, res, next) => { + req.result = [ + {id: null, name: 'Não Declarado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('education_day_care_child')); + +schoolApp.get('/education_preschool_child', cache('15 day'), (req, res, next) => { + req.result = [ + {id: null, name: 'Não Declarado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('education_preschool_child')); + +schoolApp.get('/education_begin_elementary_school', cache('15 day'), (req, res, next) => { + req.result = [ + {id: null, name: 'Não Declarado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('education_begin_elementary_school')); + +schoolApp.get('/education_end_elementary_school', cache('15 day'), (req, res, next) => { + req.result = [ + {id: null, name: 'Não Declarado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('education_end_elementary_school')); + +schoolApp.get('/education_middle_school', cache('15 day'), (req, res, next) => { + req.result = [ + {id: null, name: 'Não Declarado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('education_middle_school')); + +schoolApp.get('/education_professional', cache('15 day'), (req, res, next) => { + req.result = [ + {id: null, name: 'Não Declarado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('education_professional')); + +schoolApp.get('/education_eja', cache('15 day'), (req, res, next) => { + req.result = [ + {id: null, name: 'Não Declarado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('education_eja')); + + +schoolApp.get('/arrangement', cache('15 day'), (req, res, next) => { + req.result = [ + {id: 0, name: 'Creche'}, + {id: 1, name: 'Pré Escola'}, + {id: 2, name: 'Ensino Fundamental - AI'}, + {id: 3, name: 'Ensino Fundamental - AF'}, + {id: 4, name: 'Ed. Infantil Unificada/Multietapa/Multissérie/Correção fluxo'}, + {id: 5, name: 'Ensino Médio'}, + {id: 6, name: 'Ensino EJA'}, + {id: 7, name: 'Educação Profissional'}, + {id: 8, name: 'Educação Especial Exclusiva'} + ]; + next(); +}, response('arrangement')); + +schoolApp.get('/integral_time', cache('15 day'), (req, res, next) => { + req.result = []; + for(let i = 0; i <= 2; ++i) { + req.result.push({ + id: i, + name: id2str.integralTime(i) + }); + } + next(); +}, response('integral_time')); + + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'id', + table: 'escola', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo', + table: 'escola' + } +}).addField({ + name: 'search', + field: true, + where: true +}).addValueToField({ + name: 'city_name', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + dontGroup: true, + where: { + relation: 'LIKE', + type: 'string', + field: 'nome' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'search') +.addValueToField({ + name: 'state_name', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + dontGroup: true, + where: { + relation: 'LIKE', + type: 'string', + field: 'sigla' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'escola' + } +}, 'search').addValue({ + name: 'diff_location', + table: 'escola', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}); + +rqfCount.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'id', + table: 'escola', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'filter').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo', + table: 'escola' + } +}).addValue({ + name: 'location', + table: 'escola', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'diff_location', + table: 'escola', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).addValue({ + name: 'rural_location', + table: 'escola', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'arrangement', + table: 'escola', + tableField: 'arranjo', + resultField: 'arrangement_id', + where: { + relation: '=', + type: 'integer', + field: 'arranjo' + } +}).addValue({ + name: 'adm_dependency', + table: 'escola', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'escola', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'government_agreement', + table: 'escola', + tableField: 'dependencia_convenio_publico', + resultField: 'government_agreement_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_convenio_publico' + } +}).addValue({ + name: 'integral_time', + table: 'escola', + tableField: 'tempo_integral', + resultField: 'integral_time_id', + where: { + relation: '=', + type: 'boolean', + field: 'tempo_integral' + } +}).addValue({ + name: 'agreement', + table: 'escola', + tableField: 'tipo_convenio_pp', + resultField: 'agreement_id', + where: { + relation: '=', + type: 'integer', + field: 'tipo_convenio_pp' + } +}).addValue({ + name: 'education_day_care_child', + table: 'escola', + tableField: 'reg_infantil_creche_t1', + resultField: 'education_day_care_child_id', + where: { + relation: '=', + type: 'boolean', + field: 'reg_infantil_creche_t1' + } +}).addValue({ + name: 'education_preschool_child', + table: 'escola', + tableField: 'reg_infantil_preescola_t1', + resultField: 'education_preschool_child_id', + where: { + relation: '=', + type: 'boolean', + field: 'reg_infantil_preescola_t1' + } +}).addValue({ + name: 'education_begin_elementary_school', + table: 'escola', + tableField: 'reg_fund_ai_t1', + resultField: 'education_begin_elementary_school_id', + where: { + relation: '=', + type: 'boolean', + field: 'reg_fund_ai_t1' + } +}).addValue({ + name: 'education_end_elementary_school', + table: 'escola', + tableField: 'reg_fund_af_t1', + resultField: 'education_end_elementary_school_id', + where: { + relation: '=', + type: 'boolean', + field: 'reg_fund_af_t1' + } +}).addValue({ + name: 'education_middle_school', + table: 'escola', + tableField: 'reg_medio_medio_t1', + resultField: 'education_middle_school_id', + where: { + relation: '=', + type: 'boolean', + field: 'reg_medio_medio_t1' + } +}).addValue({ + name: 'education_professional', + table: 'escola', + tableField: 'educacao_profissional', + resultField: 'education_professional_id', + where: { + relation: '=', + type: 'boolean', + field: 'educacao_profissional' + } +}).addValue({ + name: 'education_eja', + table: 'escola', + tableField: 'ensino_eja', + resultField: 'education_eja_id', + where: { + relation: '=', + type: 'boolean', + field: 'ensino_eja' + } +}).addValue({ + name: 'min_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'school_building', + table: 'escola', + tableField: 'local_func_predio_escolar', + resultField: 'school_building', + where: { + relation: '=', + type: 'boolean', + field: 'local_func_predio_escolar' + } +}); +schoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + + req.sql.from('escola') + .field('escola.id') + .field('escola.ano_censo', 'year') + .field('escola.nome_escola', 'name') + .field('escola.estado_id', 'state_id') + .field('escola.municipio_id', 'city_id'); + next(); +}, query, response('school')); + +schoolApp.get('/count', cache('15 day'), rqfCount.parse(), (req, res, next) => { + let arrang = ["arranjo_creche", "arranjo_pre", "arranjo_fundamental_ai", "arranjo_fundamental_af", "arranjo_multietapa", "arranjo_ensino_medio", "ensino_eja", "educacao_profissional", "ensino_especial"]; + + req.sql.from('escola') + .field('COUNT(escola.id)', 'total') + .field("'Brasil'", 'name') + .field('escola.ano_censo', 'year') + .group('escola.ano_censo') + .order('escola.ano_censo') + .where('escola.situacao_funcionamento_pareada = 1 AND (escola.ensino_regular = 1 OR escola.ensino_eja=1 or escola.educacao_profissional=1)') + + //Transforma a query em OR se tiver o filtro do arranjo + if (req.filter.arrangement) { + let arrangementQuery = ""; + for (let i = 0; i < req.filter.arrangement.length - 1; i++) { + arrangementQuery += 'escola.' + arrang[req.filter.arrangement[i]] + ' = 1 OR '; + } + // o ultimo elemento precisa ser sem o OR + arrangementQuery += 'escola.' + arrang[req.filter.arrangement[req.filter.arrangement.length - 1]] + ' = 1'; + req.sql.where('' + arrangementQuery); + } + delete req.filter.arrangement + next(); +}, rqfCount.build(), query, id2str.transform(), addMissing(rqfCount), response('school')); + +module.exports = schoolApp; diff --git a/src/libs/routes/schoolInfrastructure.js b/src/libs/routes_v1/schoolInfrastructure.js similarity index 100% rename from src/libs/routes/schoolInfrastructure.js rename to src/libs/routes_v1/schoolInfrastructure.js diff --git a/src/libs/routes/schoolLocation.js b/src/libs/routes_v1/schoolLocation.js similarity index 100% rename from src/libs/routes/schoolLocation.js rename to src/libs/routes_v1/schoolLocation.js diff --git a/src/libs/routes/simulation.js b/src/libs/routes_v1/simulation.js similarity index 100% rename from src/libs/routes/simulation.js rename to src/libs/routes_v1/simulation.js diff --git a/src/libs/routes/siope.js b/src/libs/routes_v1/siope.js similarity index 100% rename from src/libs/routes/siope.js rename to src/libs/routes_v1/siope.js diff --git a/src/libs/routes/spatial.js b/src/libs/routes_v1/spatial.js similarity index 100% rename from src/libs/routes/spatial.js rename to src/libs/routes_v1/spatial.js diff --git a/src/libs/routes/state.js b/src/libs/routes_v1/state.js similarity index 100% rename from src/libs/routes/state.js rename to src/libs/routes_v1/state.js diff --git a/src/libs/routes/studentsAee.js b/src/libs/routes_v1/studentsAee.js similarity index 100% rename from src/libs/routes/studentsAee.js rename to src/libs/routes_v1/studentsAee.js diff --git a/src/libs/routes/teacher.js b/src/libs/routes_v1/teacher.js similarity index 100% rename from src/libs/routes/teacher.js rename to src/libs/routes_v1/teacher.js diff --git a/src/libs/routes/transport.js b/src/libs/routes_v1/transport.js similarity index 100% rename from src/libs/routes/transport.js rename to src/libs/routes_v1/transport.js diff --git a/src/libs/routes/university.js b/src/libs/routes_v1/university.js similarity index 100% rename from src/libs/routes/university.js rename to src/libs/routes_v1/university.js diff --git a/src/libs/routes/universityEnrollment.js b/src/libs/routes_v1/universityEnrollment.js similarity index 100% rename from src/libs/routes/universityEnrollment.js rename to src/libs/routes_v1/universityEnrollment.js diff --git a/src/libs/routes/universityLocalOffer.js b/src/libs/routes_v1/universityLocalOffer.js similarity index 100% rename from src/libs/routes/universityLocalOffer.js rename to src/libs/routes_v1/universityLocalOffer.js diff --git a/src/libs/routes/universityTeacher.js b/src/libs/routes_v1/universityTeacher.js similarity index 100% rename from src/libs/routes/universityTeacher.js rename to src/libs/routes_v1/universityTeacher.js diff --git a/src/libs/routes/user.js b/src/libs/routes_v1/user.js similarity index 100% rename from src/libs/routes/user.js rename to src/libs/routes_v1/user.js diff --git a/src/libs/routes/verifyToken.js b/src/libs/routes_v1/verifyToken.js similarity index 100% rename from src/libs/routes/verifyToken.js rename to src/libs/routes_v1/verifyToken.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js new file mode 100644 index 00000000..906af9cf --- /dev/null +++ b/src/libs/routes_v2/api.js @@ -0,0 +1,196 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const api = express(); + +const libs = `${process.cwd()}/libs`; + +const config = require(`${libs}/config`); + +const classes = require('./class'); + +const enrollment = require('./enrollment'); + +const state = require('./state'); + +const region = require('./region'); + +const city = require('./city'); + +const school = require('./school'); + +const simulation = require('./simulation'); + +const user = require('./user'); + +const classroom = require('./classroom'); + +const teacher = require('./teacher'); + +const idhme = require('./idhme'); + +const pibpercapita = require('./pibpercapita') + +const population = require('./population') + +const rateSchool = require('./rateSchool') + +const glossEnrollmentRatio = require('./glossEnrollmentRatio') + +const liquidEnrollmentRatio = require('./liquidEnrollmentRatio') + +const idhm = require('./idhm'); + +const idhmr = require('./idhmr'); + +const idhml = require('./idhml'); + +const oauth2 = require(`${libs}/middlewares/oauth2`); + +const verifyToken = require(`${libs}/routes_v2/verifyToken`); + +const resetToken = require(`${libs}/routes_v2/resetToken`); + +const educationYears = require(`${libs}/routes_v2/educationYears`); + +const downloads = require(`${libs}/routes_v2/downloads`); + +const infrastructure = require(`${libs}/routes_v2/infrastructure`); + +const schoolInfrastructure = require(`${libs}/routes_v2/schoolInfrastructure`); + +const distributionFactor = require(`${libs}/routes_v2/distributionFactor`); + +const siope = require(`${libs}/routes_v2/siope`); + +const verifyTeacher = require(`${libs}/routes_v2/portalMec`); + +const outOfSchool = require(`${libs}/routes_v2/outOfSchool`); + +const classroomCount = require(`${libs}/routes_v2/classroomCount`); + +const transport = require(`./transport`); + +const auxiliar = require(`${libs}/routes_v2/auxiliar`); + +const dailyChargeAmount = require(`${libs}/routes_v2/dailyChargeAmount`); + +const cub = require(`${libs}/routes_v2/cub`); + +const classCount = require(`${libs}/routes_v2/classCount`); + +const portalMecInep = require(`${libs}/routes_v2/portalMecInep`); + +const enrollmentProjection = require(`${libs}/routes_v2/enrollmentProjection`); + +const employees = require(`${libs}/routes_v2/employees`); + +const financial = require(`${libs}/routes_v2/financial`); + +const universityEnrollment = require(`${libs}/routes_v2/universityEnrollment`); + +const courseCount = require(`${libs}/routes_v2/courseCount`); + +const university = require(`${libs}/routes_v2/university`); + +const universityTeacher = require(`${libs}/routes_v2/universityTeacher`); + +const educationalBudget = require(`${libs}/routes_v2/educationalBudget`); + +const schoolLocation = require(`${libs}/routes_v2/schoolLocation`); + +const studentsAee = require(`${libs}/routes_v2/studentsAee`); + +const mesoregion = require(`${libs}/routes_v2/mesoregion`); + +const microregion = require(`${libs}/routes_v2/microregion`); + +const location = require(`${libs}/routes_v2/location`); + +const disciplines = require(`${libs}/routes_v2/disciplines`); + +const universityLocalOffer = require(`${libs}/routes_v2/universityLocalOffer`); + +const message = require(`${libs}/routes_v2/message`); + +const courseStudents = require(`${libs}/routes_v2/courseStudents`); + +api.get('/', (req, res) => { + res.json({ msg: 'SimCAQ API v2 is running' }); +}); + +// mount API routes_v2 +api.use('/user', user); +api.use('/simulation', simulation); +api.use('/class', classes); +api.use('/enrollment', enrollment); +api.use('/state', state); +api.use('/region', region); +api.use('/city', city); +api.use('/school', school); +api.use('/classroom', classroom); +api.use('/teacher', teacher); +api.use('/idhmr', idhmr); +api.use('/idhm', idhm); +api.use('/idhme', idhme); +api.use('/pibpercapita', pibpercapita); +api.use('/population', population); +api.use('/rate_school', rateSchool); +api.use('/gloss_enrollment_ratio', glossEnrollmentRatio); +api.use('/liquid_enrollment_ratio', liquidEnrollmentRatio); +api.use('/idhml', idhml); +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('/school_infrastructure', schoolInfrastructure); +api.use('/distribution_factor', distributionFactor); +api.use('/siope', siope); +api.use('/out_of_school', outOfSchool); +api.use('/classroom_count', classroomCount); +api.use('/daily_charge_amount', dailyChargeAmount); +api.use('/transport', transport); +api.use('/cub', cub); +api.use('/auxiliar', auxiliar); +api.use('/verify_teacher', verifyTeacher); +api.use('/class_count', classCount); +api.use('/portal_mec_inep', portalMecInep); +api.use('/enrollment_projection', enrollmentProjection); +api.use('/employees', employees); +api.use('/financial', financial); +api.use('/university_enrollment', universityEnrollment); +api.use('/university', university); +api.use('/university_teacher', universityTeacher); +api.use('/course_count', courseCount); +api.use('/school_location', schoolLocation); +api.use('/students_aee', studentsAee); +api.use('/mesoregion', mesoregion); +api.use('/microregion', microregion); +api.use('/location', location); +api.use('/disciplines', disciplines); +api.use('/universityLocalOffer', universityLocalOffer); +api.use('/message', message); +api.use('/course_students', courseStudents); + +module.exports = api; diff --git a/src/libs/routes_v2/auxiliar.js b/src/libs/routes_v2/auxiliar.js new file mode 100644 index 00000000..ef538961 --- /dev/null +++ b/src/libs/routes_v2/auxiliar.js @@ -0,0 +1,397 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const auxiliarApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +auxiliarApp.use(cache('15 day')); + +auxiliarApp.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')); + +auxiliarApp.get('/years', (req, res, next) => { + req.sql.from('docente'). + field('DISTINCT docente.ano_censo', 'year') + next(); +}, query, response('years')); + +auxiliarApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'docente\''); + next(); +}, query, response('source')) + +auxiliarApp.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')); + +auxiliarApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 7; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +auxiliarApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +auxiliarApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +auxiliarApp.get('/diff_location', (req, res, next) => { + req.result = [ + {id: 0, name: "A escola não está em localidade diferenciada"}, + {id: 1, name: "Ãrea de assentamento"}, + {id: 2, name: "Terra indÃgena"}, + {id: 3, name: "Terra remanescente de quilombos"}, + ]; + next(); +}, response('diff_location')); + +auxiliarApp.get('/education_level_mod', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 12; ++i) { + req.result.push({ + id: i, + name: id2str.educationLevelMod(i) + }); + } + + req.result.push({ + id: 99, + name: id2str.educationLevelMod(99) + }); + next(); +}, response('education_level_mod')); + +auxiliarApp.get('/gender', (req, res, next) => { + req.result = [ + {id: 1, name: 'Masculino'}, + {id: 2, name: 'Feminino'} + ]; + next(); +}, response('gender')); + +auxiliarApp.get('/ethnic_group', (req, res, next) => { + req.result = []; + for(let i = 0; i <=5; ++i) { + req.result.push({ + id: i, + name: id2str.ethnicGroup(i) + }); + } + next(); +}, 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_type', + table: 'docente', + tableField: 'nivel_tipo_formacao', + resultField: 'education_type_id', + where: { + relation: '=', + type: 'integer', + field: 'nivel_tipo_formacao' + } +}).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: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_regiao_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_estado_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'rural_location', + table: 'docente', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}, 'filter').addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'docente' + } +}, 'dims').addValueToField({ + 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' + } +}, 'filter').addValue({ + name: 'location', + table: 'docente', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'diff_location', + table: 'docente', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).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', + field: 'cor_raca' + } +}); + +// LDE +auxiliarApp.get('/', rqf.parse(), (req, res, next) => { + req.sql.field('COUNT(DISTINCT docente.id_docente)', 'total') + .field("'Brasil'", 'name') + .field('docente.ano_censo', 'year') + .from('docente') + .join('turma', null, 'docente.turma_id=turma.id AND docente.ano_censo=turma.ano_censo') + .group('docente.ano_censo') + .order('docente.ano_censo') + .where('(docente.tipo_docente = 2) AND \ + ((docente.tipo_turma_id >= 0 AND docente.tipo_turma_id <= 3 AND docente.tipo_turma_atendimento_id is NULL) \ + OR ((docente.tipo_turma_atendimento_id = 1 OR docente.tipo_turma_atendimento_id = 2) AND docente.tipo_turma_id is NULL)) \ + AND (docente.ano_censo <> 2009 or (docente.escola_estado_id <> 42 AND docente.escola_estado_id <> 43))'); // não devemos trazer SC em 2009. + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(), response('auxiliar')); + +// SimCAQ +auxiliarApp.get('/count', rqf.parse(), (req, res, next) => { + req.sql.field('COUNT(DISTINCT docente.id_docente)', 'total') + .field("'Brasil'", 'name') + .field('docente.ano_censo', 'year') + .from('docente') + .group('docente.ano_censo') + .order('docente.ano_censo') + .where('(tipo_turma_id <= 3) AND (tipo_docente=2) AND (dependencia_adm_id = 1 OR dependencia_adm_id = 2 OR dependencia_adm_id = 3) AND \ + (etapas_mod_ensino_segmento_id=1 OR etapas_mod_ensino_segmento_id=2 OR etapas_mod_ensino_segmento_id=4 OR \ + etapas_mod_ensino_segmento_id=5 OR etapas_mod_ensino_segmento_id=6 OR etapas_mod_ensino_segmento_id=8 OR etapas_mod_ensino_segmento_id=9)'); + + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(), response('auxiliar')); + +module.exports = auxiliarApp; diff --git a/src/libs/routes_v2/city.js b/src/libs/routes_v2/city.js new file mode 100644 index 00000000..fc697a9f --- /dev/null +++ b/src/libs/routes_v2/city.js @@ -0,0 +1,151 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const cityApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +cityApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'id', + table: 'municipio', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'municipio' + } +}).addValue({ + name: 'state_not', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '<>', + type: 'integer', + field: 'estado_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'municipio' + } +}).addField({ + name: 'search', + field: false, + where: true +}).addValueToField({ + name: 'name', + table: 'municipio', + tableField: 'nome', + where: { + relation: 'LIKE', + type: 'string', + field: 'nome' + } +}, 'search').addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: 'mesorregiao_id', + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: 'microrregiao_id', + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id' + } +}).addValueToField({ + name: 'region', + table: 'estado', + tableField: 'regiao_id', + resultField: 'region_id', + where: { + relation: '=', + type: 'integer', + field: 'regiao_id', + table: 'estado' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'municipio' + } +}, 'filter'); + +// Return all cities +cityApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('municipio') + .field('municipio.nome', 'name') + .field('municipio.id') + .field('municipio.estado_id', 'state_id') + .field('municipio.longitude', 'longitude') + .field('municipio.latitude', 'latitude') + .field('municipio.mesorregiao_id', 'mesoregion_id') + .field('municipio.microrregiao_id', 'microregion_id'); + next(); +}, query, response('city')); + + +module.exports = cityApp; diff --git a/src/libs/routes_v2/class.js b/src/libs/routes_v2/class.js new file mode 100644 index 00000000..4eca8cc3 --- /dev/null +++ b/src/libs/routes_v2/class.js @@ -0,0 +1,402 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +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`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqfCount = new ReqQueryFields(); + +classApp.use(cache('15 day')); + +// 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('/years', (req, res, next) => { + req.sql.from('turma') + .field('DISTINCT turma.ano_censo', 'year'); + next(); +}, query, response('years')); + +classApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'turma\''); + next(); +}, query, response('source')); + +classApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +classApp.get('/diff_location', (req, res, next) => { + req.result = [ + {id: 0, name: "A escola não está em localidade diferenciada"}, + {id: 1, name: "Ãrea de assentamento"}, + {id: 2, name: "Terra indÃgena"}, + {id: 3, name: "Terra remanescente de quilombos"}, + ]; + next(); +}, response('diff_location')); + +// Returns all adm dependencies +classApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +classApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 8; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +// Returns all periods avaible +classApp.get('/period', (req, res, next) => { + req.result = []; + for(let i=1; i <= 3; ++i) { + req.result.push({ + id: i, + name: id2str.period(i) + }); + } + req.result.push({ + id: 99, + name: id2str.period(99) + }); + next(); +}, response('period')); + +// Returns integral-time avaible +classApp.get('/integral_time', (req, res, next) => { + req.result = []; + for(let i = 0; i <= 2; ++i) { + req.result.push({ + id: i, + name: id2str.integralTime(i) + }); + } + next(); +}, response('integral_time')); + +// Returns all educational levels avaible +classApp.get('/education_level_mod', (req, res, next) => { + req.result = []; + for(let i = 1; i <=12; ++i) { + req.result.push({ + id: i, + name: id2str.educationLevelMod(i) + }); + } + next(); +}, response('education_level_mod')); + +classApp.get('/education_level_short', (req, res, next) => { + req.result = [ + {id: null, name: 'Não classificada'}, + {id: 1, name: 'Creche'}, + {id: 2, name: 'Pré-Escola'}, + {id: 3, name: 'Ensino Fundamental - anos iniciais'}, + {id: 4, name: 'Ensino Fundamental - anos finais'}, + {id: 5, name: 'Ensino Médio'}, + {id: 6, name: 'EJA'}, + {id: 7, name: 'EE exclusiva'} + ]; + next(); +}, response('education_level_short')); + +rqfCount.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'turma' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'turma' + } +}, 'dims').addValueToField({ + 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' + } +}, 'filter').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'turma' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + 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: 'turma', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'location', + table: 'turma', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'diff_location', + table: 'turma', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).addValue({ + name: 'rural_location', + table: 'turma', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name:'education_level_mod', + table: 'turma', + tableField: 'etapas_mod_ensino_segmento_id', + resultField: 'education_level_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'etapas_mod_ensino_segmento_id' + } +}).addValue({ + name: 'education_level_short', + table: 'turma', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'turma', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name:'period', + table: 'turma', + tableField: 'turma_turno_id', + resultField: 'period_id', + where: { + relation: '=', + type: 'integer', + field: 'turma_turno_id' + } +}).addValue({ + name:'integral_time', + table: 'turma', + tableField: 'tempo_integral', + resultField: 'integral_time_id', + where: { + relation: '=', + type: 'integer', + field: 'tempo_integral' + } +}).addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'turma' + } +}, 'dims').addValueToField({ + 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' + } +}, 'filter').addValueToField({ + name: 'period_not', + table: 'turma', + tableField: 'turma_turno_id', + resultField: 'period_id', + where: { + relation: '<>', + type: 'integer', + field: 'turma_turno_id' + } +}, 'filter'); + + +classApp.get('/', rqfCount.parse(), (req, res, next) => { + 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 AND turma.tipo_turma_id <= 3 AND turma.tipo_atendimento_id is NULL) \ + OR ((turma.tipo_atendimento_id = 1 OR turma.tipo_atendimento_id = 2) AND turma.tipo_turma_id is NULL) '); + next(); +}, rqfCount.build(), query, addMissing(rqfCount), id2str.transform(), response('class')); + +module.exports = classApp; diff --git a/src/libs/routes_v2/classCount.js b/src/libs/routes_v2/classCount.js new file mode 100644 index 00000000..ffdbe34f --- /dev/null +++ b/src/libs/routes_v2/classCount.js @@ -0,0 +1,455 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const classCountApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'turma' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'turma' + } +}, 'dims').addValueToField({ + 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' + } +}, 'filter') +.addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'turma' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + 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: 'turma', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'location', + table: 'turma', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'rural_location', + table: 'turma', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name:'education_level_mod', + table: 'turma', + tableField: 'etapas_mod_ensino_segmento_id', + resultField: 'education_level_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'etapas_mod_ensino_segmento_id' + } +}).addValue({ + name:'education_level_short', + table: 'turma', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'turma', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'turma' + } +}, 'dims').addValueToField({ + 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' + } +}, 'filter'); + +classCountApp.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')); + +classCountApp.get('/years', (req, res, next) => { + req.sql.from('escola') + .field('DISTINCT escola.ano_censo', 'year'); + next(); +}, query, response('years')); + +classCountApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +classCountApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +classCountApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +classCountApp.get('/rural_location', (req, res, next) => { + req.result = [ + {id: 1, name: "Urbana"}, + {id: 2, name: "Rural"}, + {id: 3, name: "Rural - Ãrea de assentamento"}, + {id: 4, name: "Rural - Terra indÃgena"}, + {id: 5, name: "Rural - Ãrea remanescente de quilombos"}, + {id: 6, name: "Rural - Unidade de uso sustentável"} + ]; + next(); +}, response('rural_location')); + +classCountApp.get('/education_level_mod', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 10; ++i) { + req.result.push({ + id: i, + name: id2str.educationLevelMod(i) + }); + } + req.result.push({ + id: 99, + name: id2str.educationLevelMod(99) + }); + next(); +}, response('education_level_mod')); + +classCountApp.get('/education_level_short', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 7; ++i) { + req.result.push({ + id: i, + name: id2str.educationLevelShort(i) + }); + } + req.result.push({ + id: 99, + name: id2str.educationLevelShort(99) + }); + next(); +}, response('education_level_short')); + +classCountApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'turma\''); + next(); +}, query, response('source')); + +// Se a dimensão obrigatória do LDE (etapa de ensino) possui alguma etapa sem nenhum valor, então é criado um objeto +// com média 0.0 e é inserido no resultado. Usada para não quebrar a sequência de etapas na tabela do LDE. +function addNullFields(result) { + const firstYear = result[0].year; + var obj = result.filter(res => res.year == firstYear); + var prevFirstDimId = obj[0]; + obj.forEach((d) => { + if((d["education_level_mod_id"] > prevFirstDimId["education_level_mod_id"]) && (prevFirstDimId["education_level_mod_id"] != 10) && + (d["education_level_mod_id"] != prevFirstDimId["education_level_mod_id"] + 1)) { + let newObj = {}; + Object.keys(prevFirstDimId).forEach((key) => { + newObj[key] = prevFirstDimId[key]; + }); + newObj.education_level_mod_id = d["education_level_mod_id"] - 1; + newObj.education_level_mod_name = id2str.educationLevelMod(d["education_level_mod_id"] - 1); + newObj.average = 0.0; + result.splice(result.indexOf(prevFirstDimId) + 1, 0, newObj); + } + prevFirstDimId = d; + }); +} + +function addZeroFields(result) { + let i; + for (i=0; i < result.length; i++) { + let hasTotal = result[i].hasOwnProperty("total"); + if (hasTotal == true) { + result[i].average = 0.0; + result[i].median = 0.0; + result[i].stddev = 0.0; + result[i].first_qt = 0.0; + result[i].third_qt = 0.0; + } + } + return result; +} + +// SimCAQ +classCountApp.get('/count', rqf.parse(), (req, res, next) => { + req.sql.field("'Brasil'", 'name') + .field('turma.ano_censo', 'year') + .field('AVG(turma.num_matricula)', 'average') + .field('MEDIAN(turma.num_matricula)', 'median') + .field('STDDEV_POP(turma.num_matricula)', 'stddev') + .field('QUANTILE(turma.num_matricula, 0.25)', 'first_qt') + .field('QUANTILE(turma.num_matricula, 0.75)', 'third_qt') + .from('turma') + .group('turma.ano_censo') + .order('turma.ano_censo') + .where('turma.local_turma = 0 AND turma.dependencia_adm_id <= 3 AND ((turma.etapa_resumida >= 1 AND turma.etapa_resumida <= 7) OR turma.etapa_resumida = 99) AND turma.turma_turno_id <> 99') + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(), response('class_count')); + +// LDE +// Essa rota não esta sendo usada. +// Ela está com defeito e quando é chamada cai o banco. +/* +classCountApp.get('/', rqf.parse(), (req, res, next) => { + // Faz a consulta do número de alunos pelas dimensões + if(("education_level_mod" in req.dims) || ("education_level_mod" in req.filter) || ("education_level_short" in req.dims)) { + req.sql.field("'Brasil'", 'name') + .field('turma.ano_censo', 'year') + .field('AVG(turma.num_matricula)', 'average') + .field('MEDIAN(turma.num_matricula)', 'median') + .field('STDDEV_POP(turma.num_matricula)', 'stddev') + .field('QUANTILE(turma.num_matricula, 0.25)', 'first_qt') + .field('QUANTILE(turma.num_matricula, 0.75)', 'third_qt') + .from('turma') + .group('turma.ano_censo') + .order('turma.ano_censo') + .where('turma.tipo_turma_id = 0 AND turma.etapas_mod_ensino_segmento_id >= 1 AND turma.etapas_mod_ensino_segmento_id <= 10'); + next(); + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.partial = []; + + // Caso tenha apenas uma dimensão, o indicador possuirá uma linha de total + if((req.dims) && (req.dims.size == 1)) { + req.partial = req.result; + + // A linha de total deverá conter o valor total do ano que está no banco de dados, então usa o mesmo filtro de anos da consulta anterior + let yearFilter = {}; + if("min_year" in req.filter) + yearFilter.min_year = req.filter.min_year; + if("max_year" in req.filter) + yearFilter.max_year = req.filter.max_year; + + // Faz a consulta sem dimensões, do total do(s) ano(s) escolhido(s) + req.resetSql(); + req.dims = {}; + req.filter = yearFilter; + req.sql.field("'Brasil'", 'name') + .field('turma.ano_censo', 'year') + .field('AVG(turma.num_matricula)', 'average') + .field('MEDIAN(turma.num_matricula)', 'median') + .field('STDDEV_POP(turma.num_matricula)', 'stddev') + .field('QUANTILE(turma.num_matricula, 0.25)', 'first_qt') + .field('QUANTILE(turma.num_matricula, 0.75)', 'third_qt') + .from('turma') + .group('turma.ano_censo') + .order('turma.ano_censo') + .where('turma.tipo_turma_id = 0 AND turma.etapas_mod_ensino_segmento_id >= 1 AND turma.etapas_mod_ensino_segmento_id <= 10'); + } + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(), (req, res, next) => { + // Se tem apenas uma dimensão + if(req.partial.length > 0) { + const yearClassCount = req.result; + req.result = req.partial; + + // Como a linha de total deve aparecer em um caso especÃfico, ela é adicionada junto com a dimensão obrigatória + yearClassCount.forEach((result) => { + let obj = {}; + obj = result; + obj.education_level_mod_name = "Total"; + req.result.push(obj); + }) + } + // Caso tenha mais de uma dimensão, retorna a consulta só pelas dimensões, sem linha de total + else { + addNullFields(req.result); + req.result = addZeroFields(req.result); + } + + next(); +}, response('class_count')); +*/ + +module.exports = classCountApp; diff --git a/src/libs/routes_v2/classroom.js b/src/libs/routes_v2/classroom.js new file mode 100644 index 00000000..8e2b6a7e --- /dev/null +++ b/src/libs/routes_v2/classroom.js @@ -0,0 +1,277 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const classroomApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +let rqfCount = new ReqQueryFields(); + +//classroomApp.use(cache('15 day')); + + +// Complete range of the enrollments dataset. +// Returns a tuple of start and ending years of the complete enrollments dataset. +classroomApp.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')); + +classroomApp.get('/years', (req, res, next) => { + req.sql.from('escola') + .field('DISTINCT escola.ano_censo', 'year'); + next(); +}, query, response('years')); + +classroomApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'escola\''); + next(); +}, query, response('source')); + +classroomApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +classroomApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +classroomApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}, 'dims').addValueToField({ + name: 'school', + table: 'escola', + tableField: 'nome_escola', + resultField: 'school_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}, 'filter').addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'filter').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'min_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'adm_dependency', + table: 'escola', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'escola', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'location', + table: 'escola', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}); + +classroomApp.get('/', cache('15 day'), rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('escola') + .field('SUM(escola.qtde_salas_utilizadas_dentro)', 'total') + .field("'Brasil'", 'name') + .field('escola.ano_censo', 'year') + .group('escola.ano_censo') + .order('escola.ano_censo') + .where('escola.situacao_de_funcionamento = 1 AND escola.local_func_predio_escolar = 1') + .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1'); + next(); +}, query, addMissing(rqf), id2str.transform(), (req, res, next) => { + if (req.dims.location && req.result.length < 2) { // Garantimos que conterá as duas localizações no resultado para o simCAQ + let result = []; + for (let i = 1; i <= 2; i++) { + if (i !== req.result[0].location_id) { + let newObj = Object.assign({}, req.result[0]); + newObj.location_id = i; + newObj.total = 0; + newObj.location_name = (i == 1) ? "Urbana" : "Rural"; + result.push(newObj); + } + else { + result.push(req.result[0]); + } + } + + req.result = result; + } + + next(); +}, response('classroom')); + +module.exports = classroomApp; diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js new file mode 100644 index 00000000..4f76bed3 --- /dev/null +++ b/src/libs/routes_v2/classroomCount.js @@ -0,0 +1,1172 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + + +const express = require('express'); + +const classroomCountApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: '@' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}, 'filter').addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}, 'dims').addValueToField({ + name: 'state', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: '@' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}, 'filter').addValueToField({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id', + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}, 'dims').addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id', + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: '@' + } +}, 'dims').addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: '@' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'school_year', + table: '@', + tableField: 'serie_ano_id', + resultField: 'school_year_id', + where: { + relation: '=', + type: 'integer', + field: 'serie_ano_id' + } +}).addValue({ + name: 'location', + table: '@', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'period', + table: '@', + tableField: 'turma_turno_id', + resultField: 'period_id', + where: { + relation: '=', + type: 'integer', + field: 'turma_turno_id' + } +}).addValue({ + name: 'school_building', + table: 'escola', + tableField: 'local_func_predio_escolar', + resultField: 'school_building', + where: { + relation: '=', + type: 'boolean', + field: 'local_func_predio_escolar' + } +}).addValue({ + name: 'night_time', + table: 'matricula', + tableField: 'periodo_noturno', + resultField: 'night_time', + where: { + relation: '=', + type: 'boolean', + field: 'periodo_noturno' + } +}).addValue({ + name: 'formation_level', + table: 'docente_por_formacao', + tableField: 'tipo_formacao', + resultField: 'formation_level', + where: { + relation: '=', + type: 'integer', + field: 'tipo_formacao' + } +}).addValueToField({ + name: 'adm_dependency', + table: '@', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}, 'filter') .addValue({ + name: 'integral_time', + table: 'matricula', + tableField: 'tempo_integral', + resultField: 'integral_time_id', + where: { + relation: '=', + type: 'integer', + field: 'tempo_integral' + } +}).addValue({ + name: 'education_level_short', + table: 'matricula', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}); + +classroomCountApp.post('/', rqf.parse(), (req, res, next) => { + let classSize = JSON.parse(req.body.class_size) || null; + let integralTime = JSON.parse(req.body.integral_time) || null; + let enrollmentProjection = (req.body.projections !== undefined) ? JSON.parse(req.body.projections) : null; + + if(classSize == null || integralTime == null) { + res.statusCode = 400; + return res.json({err: {message: "There was an error processing class_size or integral_time. Check your JSON sintax and be sure you're sending both paramenters."}}); + } + req.classSize = classSize; + req.integralTime = integralTime; + req.projections = (enrollmentProjection !== null) ? enrollmentProjection : false; + + req.dims.state = true; + req.dims.city = true; + req.dims.school_year = true; + req.dims.location = true; + + req.sql.field('sum(dia_total)', 'total_day') + .field('sum(noite_total)', 'total_night') + .field("'Brasil'", 'name') + .field('matricula_por_localizacao.ano_censo', 'year') + .from('matricula_por_localizacao') + .where('matricula_por_localizacao.serie_ano_id < 15') + .group('matricula_por_localizacao.ano_censo') + .order('matricula_por_localizacao.ano_censo') + + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.enrollment = req.result; + + // Gera a relação etapa de ensino X ano escolar + req.educationSchoolYear = {}; + for(let i = 1; i < 15; ++i) { + if(id2str.educationLevelSchoolYear(i) !== id2str.educationLevelSchoolYear(99)) { + let educationLevelId = (i > 10) ? Math.floor(i/10) : i; + + let classSize = req.classSize.find((el) => {return el.id === educationLevelId || el.id === i}); + let integralTime = req.integralTime.find((el) => {return el.id === educationLevelId}); + + let numberStudentClass = (typeof classSize !== 'undefined') ? classSize.numberStudentClass : null; + // Usa o offerGoal que é passado como parâmetro (Brasil inteiro). Atenção para isso. + let integralTimeOfferGoal = (typeof integralTime !== 'undefined') ? integralTime.offerGoal : null; + + let teacherByClass = (typeof classSize !== 'undefined') ? classSize.teacherByClass : null; + + req.educationSchoolYear[i] = { + id: educationLevelId, + name: id2str.educationLevelShort(educationLevelId), + numberStudentClass, + integralTimeOfferGoal, + teacherByClass + }; + } + } + + delete req.dims; + delete req.filter; + req.resetSql(); + next(); +}, rqf.parse(), (req, res, next) => { + + req.dims.state = true; + req.dims.city = true; + req.dims.location = true; + req.dims.school_building = true; + + req.sql.field('SUM(escola.qtde_salas_utilizadas_dentro)', 'total') + .field("'Brasil'", 'name') + .field('escola.ano_censo', 'year') + .from('escola') + .group('escola.ano_censo') + .order('escola.ano_censo') + .where('escola.situacao_de_funcionamento = 1') + .where('escola.dependencia_adm_id < 4') + .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1'); + + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.classroom = req.result; + + delete req.dims; + delete req.filter; + req.resetSql(); + next(); +}, rqf.parse(), (req, res, next) => { + if (req.body.teacher_journey !== undefined) { + // req.teacherJourney = JSON.parse(req.body.teacher_journey) || null; + + let schoolDays = JSON.parse(req.body.school_days) || null; + let teacherFormation = JSON.parse(req.body.teacher_formation) || null; + let teachingHours = JSON.parse(req.body.teaching_hours) || null; + + let schoolDaysParsed = []; + let teachingHoursParsed = []; + for(let i = 1; i <= 6; i++) { // Adciona turnos faltantes, corrige ordem dos id's + schoolDaysParsed.push(schoolDays.find((el) => {return el.id === i})) + + let schoolYear = teachingHours.find((el) => {return el.id === i}) + let shifts = [] + for (let j = 1; j <= 3; j++) { + let turno = schoolYear.shifts.find((el) => {return el.id === j}) + if (turno === undefined) { + turno = {"id": j, value: 0} + } + + shifts.push(turno) + } + schoolYear.shifts = shifts + teachingHoursParsed.push(schoolYear) + } + + req.schoolDays = schoolDaysParsed; + req.teachingHours = teachingHoursParsed; + + let teacherFormationParsed = [] + for (let i of [2, 4, 6, 7, 8]) { + teacherFormationParsed.push(teacherFormation.find((el) => {return el.idFormationLevel === i})) + } + req.teacherFormation = teacherFormationParsed; + + req.teacherCalc = true; + } + + req.dims.state = true; + req.dims.city = true; + req.dims.formation_level = true; + req.sql.field('count(distinct docente_por_formacao.id_docente)', 'total') + .field("'Brasil'", 'name') + .field('docente_por_formacao.ano_censo', 'year') + .from('docente_por_formacao') + .group('docente_por_formacao.ano_censo') + .order('docente_por_formacao.ano_censo'); + + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.teacher = req.result; + + delete req.dims; + delete req.filter; + req.resetSql(); + next(); +}, rqf.parse(), (req, res, next) => { + req.dims.state = true; + req.dims.city = true; + req.dims.education_level_short = true; + req.dims.integral_time = true; + req.sql.field('COUNT(*)', 'total') + .field('matricula.ano_censo', 'year') + .from('matricula') + .group('matricula.ano_censo') + .order('matricula.ano_censo') + .where('((matricula.tipo<=3 OR matricula.tipo IS NULL) AND (matricula.tipo_atendimento_turma IS NULL OR matricula.tipo_atendimento_turma <= 2) AND matricula.turma_turno_id <> 99)'); + next(); +}, rqf.build() ,query, id2str.transform(), (req, res, next) => { + // constrói objeto de tempo integral e calcula diagnósticos + var integral_time_result = req.result + req.integral_time = {} + for (let i = 0; i < integral_time_result.length; ++i){ + // Se cidade não foi criada, cria + let integral_time = integral_time_result[i]; + let code = '' + integral_time.year + integral_time.city_id + if (req.dims.school) code = code + integral_time.school_id + + let currentCodeObj = req.integral_time[code] + + // Cria municÃpio/escola caso não exista + if (currentCodeObj === undefined){ + let obj = { + year: integral_time.year, + city_id: integral_time.city_id, + city_name: integral_time.city_name, + integral_time: {} + } + if (req.dims.school){ + obj.school_id = integral_time.school_id + obj.school_name = integral_time.school_name + } + req.integral_time[code] = obj + currentCodeObj = obj; + } + + // Pega objeto com dados do nÃvel atual + var level = integral_time.education_level_short_id + var levelObj = currentCodeObj.integral_time[level] + if (levelObj === undefined){ + levelObj = { + id: level, + integralTime: 0, + total: 0, + } + } + + // Soma no total em integralTime, caso seja 1 + levelObj.total += integral_time.total + if (integral_time.integral_time_id === 1){ + levelObj.integralTime += integral_time.total + } + + currentCodeObj.integral_time[level] = levelObj + + } + for (let i in req.integral_time){ + let curObj = req.integral_time[i] + // Adiciona diagnóstico aos objetos + for (let key in curObj.integral_time){ + let cur = curObj.integral_time[key] + cur["diagnosis"] = cur.total ? (cur.integralTime/cur.total)*100.0 : 0.0; + curObj.integral_time[key] = cur + } + } + + delete req.dims; + delete req.filter; + req.resetSql(); + next() +}, rqf.parse(), rqf.build(), (req, res, next) => { + + // Talvez dê para remover todos os req.projections. + let enrollmentProjectionNight = []; + let enrollmentProjectionDay = []; + if (req.projections) { + for (let i = 0; i < req.projections.length; i++) { + if (req.projections[i].periods === 3) { + enrollmentProjectionNight.push(req.projections[i]); + } else { + enrollmentProjectionDay.push(req.projections[i]); + } + } + } + let qntYears = 1; + if (req.projections) { + qntYears = enrollmentProjectionDay[0].stagesEnrollments[0].seriesEnrollments[0].enrollments.length; + } + let result = []; + + // Cria estrutura de resposta requisitada (itera por anos de projeção): + for(let yearCount = 0; yearCount < qntYears; yearCount++) { + let i = 0; + let j = 0; + let hashSet = new Set(); + let enrollments = [...req.enrollment]; + + let ti = 0; // index for teacher table + + while (i < req.classroom.length) { + let classroom = req.classroom[i]; + // Cria hash única para cada espacialidade, dado um ano + let hash = '' + yearCount + classroom.state_id + classroom.city_id; + if (req.dims.school) + hash = hash + classroom.school_id + // Estrutura do objeto do resultado final + let obj = { + year: classroom.year + yearCount, + name: classroom.name, + state_id: classroom.state_id, + state_name: classroom.state_name, + city_id: classroom.city_id, + city_name: classroom.city_name, + }; + if (req.dims.school){ + obj.school_id = classroom.school_id, + obj.school_name = classroom.school_name + } + if (req.teacherCalc) + obj.percentage_teacher_career = []; + obj.locations = [] + + // Inserimos a localidade no array de locations da sala + let location = { + location_id: classroom.location_id, + location_name: classroom.location_name, + total_classroom: (classroom.school_building == 1) ? parseInt(classroom.total, 10) : 0, // Conta apenas salas de prédios próprios + total_classroom_be_built: 0, + education_level: [] + }; + + // Ajusta estrutura de localização do último [municÃpio/escola] e inicializa variáveis para o atual + let currentClassroomObj = null; + if( !hashSet.has(hash) ) { // Nunca passou por esse municÃpio/escola + if (result[result.length - 1] !== undefined) { // Após mudar de cidade, passamos pela cidade anterior e juntamos o valor to_be_built de localizações com o mesmo id + let last_city = result[result.length - 1] + let last_locations = result[result.length - 1].locations + for (let i = 0; i < last_locations.length - 1; i++) { + if (last_locations[i].location_id === last_locations[i+1].location_id) { + last_locations[i].total_classroom_be_built += last_locations[i+1].total_classroom_be_built; + last_locations[i].total_classroom += last_locations[i+1].total_classroom; + last_locations.splice(i+1, 1); + } + } + for (let i = 0; i < last_locations.length; i++) { // Passamos agora para não deixar to_be_built < 0 + last_locations[i].total_classroom_be_built = (last_locations[i].total_classroom_be_built < 0) ? 0 : last_locations[i].total_classroom_be_built; + } + + if (req.teacherCalc) executeTeacherCalc(last_city, ti); + } + hashSet.add(hash); + result.push(obj); + currentClassroomObj = obj; + + var id_attribute = req.dims.school ? "school_id" : "city_id" + + var old_ti = ti; + while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) // match da tabela de professores. + ti++; + + if (ti === req.teacher.length) { + console.log(classroom[id_attribute], "not found") + while (classroom[id_attribute] === enrollments[j][id_attribute]) + enrollments.splice(j, 1) + ti = old_ti; + i++; + continue; + } + + } else { // Se a hash já existe, já temos a cidade nos resultados. Como está ordenado, é o último valor nos resultados + currentClassroomObj = result[result.length - 1]; + } + currentClassroomObj.locations.push(location); + + // Partimos para as etapas de ensino/anos escolares + let enrollmentMatch = true; + j = 0; + let educationLevelSet = new Set(); + let schoolYearSet = new Set(); + let enrollment; + while(enrollmentMatch && j < enrollments.length) { + enrollment = enrollments[j]; + + if(typeof enrollment === 'undefined') { + ++j; + continue; + } + + if (req.dims.school){ + if(classroom.school_id !== enrollment.school_id) { // Se as escolas não são iguais, já passamos do range + enrollmentMatch = false; + continue; + } + } + else{ + if(classroom.city_id !== enrollment.city_id) { // Se as cidades não são iguais, já passamos do range + enrollmentMatch = false; + continue; + } + } + + if(enrollment.year != classroom.year || enrollment.location_id != classroom.location_id) { // Se ano ou localização são diferentes, passa para o próximo + ++j; + continue; + } + + + // Temos uma matrÃcula com cidade/escola, ano e localidades certos + // "Consome" a matrÃcula (remove do vetor de matrÃculas) + enrollments.splice(j, 1); + + // Cria a etapa de ensino adequada + let enrollmentEducationLevel = req.educationSchoolYear[enrollment.school_year_id]; + // Se não há um número de alunos por turna para a etapa de ensino, ignoramos a entrada + + if(enrollmentEducationLevel.numberStudentClass == null) continue; + + // Adiciona nÃvel de educação para municÃpio/escola + let educationLevel = null; + if(!educationLevelSet.has(enrollmentEducationLevel.id)) { // cria e insere ordenadamente novo education level + educationLevelSet.add(enrollmentEducationLevel.id); + + let itHash = '' + enrollment.year + enrollment.city_id + if (req.dims.school) itHash += enrollment.school_id + + let cur_education_level_short = enrollmentEducationLevel.id + + let level_diagnosis = 0 + let integral_time = 0; + let integral_time_total = 0; + if (req.integral_time[itHash].integral_time[cur_education_level_short]){ + level_diagnosis = parseFloat( (req.integral_time[itHash].integral_time[cur_education_level_short].diagnosis).toFixed(2) ) + integral_time = req.integral_time[itHash].integral_time[cur_education_level_short].integralTime + integral_time_total = req.integral_time[itHash].integral_time[cur_education_level_short].total + } + + educationLevel = { + education_level_short_id: enrollmentEducationLevel.id, + education_level_short_name: enrollmentEducationLevel.name, + enrollment: { + integral_percentage: req.dims.school ? level_diagnosis : Math.max(level_diagnosis, enrollmentEducationLevel.integralTimeOfferGoal), + integral_time: req.dims.school ? integral_time : Math.round(integral_time_total * Math.max(level_diagnosis, enrollmentEducationLevel.integralTimeOfferGoal)/100), + integral_time_total: integral_time_total, + total_enrollment_day: 0, + total_enrollment_night: 0, + full_period_classes: 0, + day_classes: 0, + night_classes: 0, + total_classrooms_needed: 0 + } + }; + + if(enrollmentEducationLevel.id == 1) { + educationLevel.classes_school_year = []; + } + + // Para manter a ordem da etapa de ensino (insertion sort) + if (location.education_level.length == 0) { + location.education_level.push(educationLevel); + } else { + let k = location.education_level.length - 1; + let el = location.education_level[k]; + while (k >= 0) { + if(educationLevel.education_level_short_id < el.education_level_short_id) { + --k; + if(k>=0) el = location.education_level[k]; + } else break; + } + k++; + location.education_level.splice(k, 0, educationLevel); + } + } else { // pega o objeto de education level já existente + let k = 0; + let el = location.education_level[k]; + while(k < location.education_level.length) { + if(el.education_level_short_id != enrollmentEducationLevel.id) { + ++k; + if(k<location.education_level.length) el = location.education_level[k]; + } else break; + } + if(k >= location.education_level.length) --k; + educationLevel = location.education_level[k]; + } + + // Adiciona as séries da creche + let currentSchoolYear = null; + if(enrollmentEducationLevel.id == 1){ + let schoolYearHash = '' + enrollment.year + enrollment.city_id + enrollment.location_id + enrollment.school_year_id; + if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.shcool_id + + if(schoolYearSet.has(schoolYearHash)) { // Busca a série escolar + let k = 0; + let el = educationLevel.classes_school_year[k]; + while(k < educationLevel.classes_school_year.length) { + if(el.school_year_id != enrollment.school_year_id) { + ++k; + if(k < educationLevel.classes_school_year.length) el = educationLevel.classes_school_year[k]; + } else break; + } + if(k >= educationLevel.classes_school_year.length) --k; + currentSchoolYear = educationLevel.classes_school_year[k]; + } else { // Adiciona uma nova série escolar + let school_year = { + school_year_id: enrollment.school_year_id, + school_year_name: enrollment.school_year_name, + total_enrollment_day: 0, + total_enrollment_night: 0, + full_period_classes: 0, + day_classes: 0, + night_classes: 0, + total_classrooms_needed: 0 + } + schoolYearSet.add(schoolYearHash); + // Busca a posição para inserir + let k = 0; + let el = educationLevel.classes_school_year[k]; + while((typeof el !== 'undefined') && school_year.school_year_id > el.school_year_id) { + el = educationLevel.classes_school_year[++k]; + } + // educationLevel.classes_school_year.push(school_year); + educationLevel.classes_school_year.splice(k, 0, school_year); + currentSchoolYear = school_year; + } + } + + let currentIntegralOfferGoal = educationLevel.enrollment.integral_percentage; + + let currentNumberStudentClass = (enrollment.location_id == 1) ? enrollmentEducationLevel.numberStudentClass.urban : enrollmentEducationLevel.numberStudentClass.country; + + // Soma os totais de matrÃcula da etapa de ensino + educationLevel.enrollment.total_enrollment_day += enrollment.total_day; + educationLevel.enrollment.total_enrollment_night += (educationLevel.education_level_short_id > 2) ? enrollment.total_night : 0; //Não contamos matrÃculas noturnos de pré-escola e creche + + // Calcula o número de turmas parcial + // Turmas de perÃodo integral + educationLevel.enrollment.full_period_classes = parseFloat(((educationLevel.enrollment.total_enrollment_day * (currentIntegralOfferGoal/100)) / currentNumberStudentClass).toFixed(2)); + + // Turmas diurnas (matrÃculas diurnas - matrÃculas integrais) + educationLevel.enrollment.day_classes = parseFloat(((educationLevel.enrollment.total_enrollment_day * (1 - currentIntegralOfferGoal/100)) / currentNumberStudentClass).toFixed(2)); + + // Turmas noturnas + educationLevel.enrollment.night_classes = parseFloat((educationLevel.enrollment.total_enrollment_night / currentNumberStudentClass).toFixed(2)) || 0; + + // Total de salas + educationLevel.enrollment.total_classrooms_needed = (educationLevel.enrollment.full_period_classes + educationLevel.enrollment.day_classes/2); + + if(educationLevel.enrollment.night_classes > (educationLevel.enrollment.day_classes/2)) educationLevel.enrollment.total_classrooms_needed += (educationLevel.enrollment.night_classes - (educationLevel.enrollment.day_classes/2)); + + educationLevel.enrollment.total_classrooms_needed = parseFloat(educationLevel.enrollment.total_classrooms_needed.toFixed(2)); + + + let currentEnrollmentOfferDay; + let currentEnrollmentOfferNight; + if (req.projections) { + currentEnrollmentOfferDay = enrollmentProjectionDay[enrollment.location_id - 1].stagesEnrollments[educationLevel.education_level_short_id - 1]; + currentEnrollmentOfferNight = enrollmentProjectionNight[enrollment.location_id - 1].stagesEnrollments[educationLevel.education_level_short_id - 1]; + } + + // Faz os mesmos cálculos para a série escolar + if(currentSchoolYear) { + // Totais de matrÃcula + currentSchoolYear.total_enrollment_day += enrollment.total_day; + + // Número de turmas parcial + currentSchoolYear.full_period_classes = parseFloat(((currentSchoolYear.total_enrollment_day * (currentIntegralOfferGoal/100)) / currentNumberStudentClass).toFixed(2)); + + currentSchoolYear.day_classes = parseFloat(((currentSchoolYear.total_enrollment_day * (1 - currentIntegralOfferGoal/100)) / currentNumberStudentClass).toFixed(2)); + + + // Total de salas + currentSchoolYear.total_classrooms_needed = (currentSchoolYear.full_period_classes + currentSchoolYear.day_classes/2); + + currentSchoolYear.total_classrooms_needed = parseFloat(currentSchoolYear.total_classrooms_needed.toFixed(2)); + + function reducer(key) { return (sum, elem) => sum + elem[key]} + educationLevel.enrollment.total_enrollment_day = educationLevel.classes_school_year.reduce(reducer('total_enrollment_day'), 0); + educationLevel.enrollment.full_period_classes = educationLevel.classes_school_year.reduce(reducer('full_period_classes'), 0); + educationLevel.enrollment.day_classes = educationLevel.classes_school_year.reduce(reducer('day_classes'), 0); + educationLevel.enrollment.total_classrooms_needed = educationLevel.classes_school_year.reduce(reducer('total_classrooms_needed'), 0); + } + + enrollment = enrollments[j]; + } + + // Calculamos o total classroom be built para o municÃpio usando reduce + location.total_classroom_be_built = location.education_level.reduce((total, atual) => { + return total + atual.enrollment.total_classrooms_needed; + }, 0) - location.total_classroom; + ++i; + } + + // Tratamento do último resultado, para remover double location, tirar negativo do to_be_built. + if (result[result.length - 1] !== undefined) { // Após mudar de cidade, passamos pela cidade anterior e juntamos o valor to_be_built de localizações com o mesmo id + let last_city = result[result.length - 1] + let last_locations = result[result.length - 1].locations + for (let i = 0; i < last_locations.length - 1; i++) { + if (last_locations[i].location_id === last_locations[i+1].location_id) { + last_locations[i].total_classroom_be_built += last_locations[i+1].total_classroom_be_built; + last_locations[i].total_classroom += last_locations[i+1].total_classroom; + last_locations.splice(i+1, 1); + } + } + for (let i = 0; i < last_locations.length; i++) { // Passamos agora para não deixar to_be_built < 0 + last_locations[i].total_classroom_be_built = (last_locations[i].total_classroom_be_built < 0) ? 0 : last_locations[i].total_classroom_be_built; + } + + if (req.teacherCalc) executeTeacherCalc(last_city, ti); + } + } + + // Agregar por estado e brasil + let reduction = null; + + if(req.dims.state || (!req.dims.city && !req.dims.school)) { // Se um dos dois acontecer, sabemos que devemos agregar + let i = 0; + reduction = []; + let reductionSet = new Set(); + while (i < result.length) { + let city = result[i]; + let obj = { + year: city.year, + name: city.name, + count: 1 + } + + if(req.dims.state) { + obj.state_id = city.state_id; + obj.state_name = city.state_name; + } + obj.percentage_teacher_career = [] + obj.locations = []; + + let hash = '' + city.year; + if(req.dims.state) hash += '' + city.state_id; + + let currentObj = null; + if(!reductionSet.has(hash)) { + reductionSet.add(hash); + reduction.push(obj); + currentObj = obj; + } else { // Está ordenado, podemos pegar o último + currentObj = reduction[reduction.length - 1]; + currentObj.count++; + } + + if (currentObj.count == 1) + currentObj.percentage_teacher_career = city.percentage_teacher_career + else { + // Incrementa valores percentuais de cada nivel de carreira no objeto atual + currentObj.percentage_teacher_career.forEach((item, ind, thisArr) => { + thisArr[ind].percentage += city.percentage_teacher_career[ind].percentage + }) + } + + // Fazer "merge" do array locations da cidade com o da agregação + if(currentObj.locations.length == 0) { + // Pode ser que a cidade atual tenha menos localidades que o total (só urbana ou só rural) + currentObj.locations = [...city.locations]; + if (currentObj.locations.length === 1) { // Se a cidade só tinha uma, adcionamos a outra manualmente. + currentObj.locations[1] = { + location_id: (currentObj.locations[0].location_id === 1) ? 2 : 1, // Oposto da adcionada + location_name: (currentObj.locations[0].location_id === 1) ? 'Rural' : 'Urbana', // Oposto da adcionada + total_classroom: 0, + total_classroom_be_built: 0, + education_level: [] + } + } + } else { + let j = 0; + let k = 0; + let cityLocation = null; + let currentLocation = null; + while((typeof cityLocation !== 'undefined') && (typeof currentLocation !== 'undefined')) { + cityLocation = city.locations[j]; + currentLocation = currentObj.locations[k]; + if(cityLocation.location_id < currentLocation.location_id) { + ++j; + cityLocation = city.locations[j]; + continue; + } else if(cityLocation.location_id > currentLocation.location_id) { + ++k; + currentLocation = currentObj.locations[k]; + continue; + } + + // Faz "merge" do array education_level + // Se a localidade atual não tem o vetor + if(currentLocation.education_level.length == 0) { + currentLocation.education_level = [...cityLocation.education_level]; + } else { // Caso já tenha, atualiza os valores + let l = 0; + while(l < cityLocation.education_level.length) { + let cityEducation = cityLocation.education_level[l]; + let m = 0; + let currentEducation = currentLocation.education_level[m]; + while(m < currentLocation.education_level.length && cityEducation.education_level_short_id > currentEducation.education_level_short_id) { + ++m; + currentEducation = currentLocation.education_level[m]; + } + if(m >= currentLocation.education_level.length) --m; + currentEducation = currentLocation.education_level[m]; + + if(currentEducation.education_level_short_id == cityEducation.education_level_short_id) { + currentEducation.enrollment.integral_time += cityEducation.enrollment.integral_time; + currentEducation.enrollment.integral_time_total += cityEducation.enrollment.integral_time_total; + currentEducation.enrollment.total_enrollment_day += cityEducation.enrollment.total_enrollment_day; + currentEducation.enrollment.total_enrollment_night += cityEducation.enrollment.total_enrollment_night; + currentEducation.enrollment.full_period_classes += cityEducation.enrollment.full_period_classes; + currentEducation.enrollment.day_classes += cityEducation.enrollment.day_classes; + currentEducation.enrollment.night_classes += cityEducation.enrollment.night_classes; + currentEducation.enrollment.total_classrooms_needed += cityEducation.enrollment.total_classrooms_needed; + + // Caso tenha feito o cálculo de professores, atualiza os valores + if (req.teacherCalc) { + currentEducation.teacherNumber.total_teacher += cityEducation.teacherNumber.total_teacher; + currentEducation.teacherNumber.total_teacher_full_period += cityEducation.teacherNumber.total_teacher_full_period; + currentEducation.teacherNumber.total_teacher_partial += cityEducation.teacherNumber.total_teacher_partial; + + currentEducation.teacherNumber.careerLevels.forEach((currentLevel, i) => { + currentLevel.total_teacher_career += cityEducation.teacherNumber.careerLevels[i].total_teacher_career; + currentLevel.total_teacher_full_period_career += cityEducation.teacherNumber.careerLevels[i].total_teacher_full_period_career; + currentLevel.total_teacher_partial_career += cityEducation.teacherNumber.careerLevels[i].total_teacher_partial_career; + }) + } + + // Insere as séries escolares, se existirem + if((typeof cityEducation.classes_school_year !== 'undefined') && (typeof currentEducation.classes_school_year !== 'undefined')) { + let n = 0; + let o = 0; + let currentClass = currentEducation.classes_school_year[n]; + let cityClass = cityEducation.classes_school_year[o]; + while((typeof cityClass !== 'undefined') && (typeof currentClass !== 'undefined')) { + currentClass = currentEducation.classes_school_year[n]; + cityClass = cityEducation.classes_school_year[o]; + + // Se a série escolar é menor que a atual, ela não está no vetor, pois o vetor está ordenado e tem range limitado + if(cityClass.school_year_id < currentClass.school_year_id) { + currentEducation.classes_school_year.splice(n, 0, cityClass); + currentClass = currentEducation.classes_school_year[n]; + cityClass = cityEducation.classes_school_year[++o]; + continue; + } else if(cityClass.school_year_id > currentClass.school_year_id) { + currentClass = currentEducation.classes_school_year[++n]; + // Se o ano escolar da cidade é maior que do objeto atual E o vetor de ano escolar do objeto atual + // acaba, então este ano escolar falta no objeto atual, pois os anos escolares estão ordenados + if((typeof currentClass == 'undefined') && (typeof cityClass !== 'undefined')) { + currentEducation.classes_school_year[n] = cityClass; + currentClass = currentEducation.classes_school_year[n]; + } + continue; + } + + currentClass.total_enrollment_day += cityClass.total_enrollment_day; + currentClass.total_enrollment_night += cityClass.total_enrollment_night; + currentClass.full_period_classes += cityClass.full_period_classes; + currentClass.day_classes += cityClass.day_classes; + currentClass.night_classes += cityClass.night_classes; + currentClass.total_classrooms_needed += cityClass.total_classrooms_needed; + + // Caso tenha feito o cálculo de professores, atualiza os valores + if (req.teacherCalc) { + currentClass.teacherNumber.total_teacher += cityClass.teacherNumber.total_teacher; + currentClass.teacherNumber.total_teacher_full_period += cityClass.teacherNumber.total_teacher_full_period; + currentClass.teacherNumber.total_teacher_partial += cityClass.teacherNumber.total_teacher_partial; + + // currentClass.teacherNumber.careerLevels.forEach((currentLevel, i) => { + // currentLevel.total_teacher_career += cityClass.teacherNumber.careerLevels[i].total_teacher_career; + // currentLevel.total_teacher_full_period_career += cityClass.teacherNumber.careerLevels[i].total_teacher_full_period_career; + // currentLevel.total_teacher_partial_career += cityClass.teacherNumber.careerLevels[i].total_teacher_partial_career; + // }) + } + + cityClass = cityEducation.classes_school_year[++o]; + } + + } + } else { + if(currentEducation.education_level_short_id < cityEducation.education_level_short_id) { + currentLocation.education_level.splice(++m, 0, cityEducation); + } else { + currentLocation.education_level.splice(m, 0, cityEducation); + } + } + ++l; + } + } + // Reinicia vetor percentage_teacher_career e calcula porcentagens pelos totais + + currentLocation.total_classroom += cityLocation.total_classroom; + currentLocation.total_classroom_be_built += cityLocation.total_classroom_be_built; + + ++j; + cityLocation = city.locations[j]; + } + } + ++i; + } + for (let state of reduction){ + state.percentage_teacher_career.forEach((item, ind, thisArr) => { + thisArr[ind].percentage = Number((thisArr[ind].percentage / state.count).toFixed(2)) + }) + delete state.count + for (let location of state.locations){ + for (let educationLevel of location.education_level){ + let total = educationLevel.enrollment.integral_time_total; + let integralTime = educationLevel.enrollment.integral_time; + educationLevel.enrollment.integral_percentage = total ? parseFloat( (100*(integralTime / total)).toFixed(2) ) : 0 + } + } + } + } + + req.result = reduction || result; + + + function executeTeacherCalc(lastCity, index) { + let lastLocations = lastCity.locations + let teacherByFormation = []; // Vetor com a porcentagem de professores por formação. + let teacherTotal = req.teacher[index].total; + + let i = index + 1; + for (let j of [2, 4, 6, 7, 8]) { // Calcula a porcentagem de professores por formação. + if (req.teacher[i] === undefined || j !== req.teacher[i].formation_level) { // Nesse caso a cidade não possuà professores com a formação atual, adcionamos 0. + teacherByFormation.push(0); + } + else { + teacherByFormation.push(parseFloat((req.teacher[i].total / teacherTotal).toFixed(3))); + i++; + } + } + + // verifica se a soma de porcentagens vale 100. + let sum = 0; + for (let value of teacherByFormation) { + sum += value; + } + teacherByFormation[1] += teacherByFormation[0] + teacherByFormation[0] = 0 + + let diff = 1 - sum; + + // Se soma de porcentagens for menor/maior que 100, faz correção + if (Math.abs(diff) > 0.0001) { + // Garante que a porcentagem corrigida não ficará negativa + let indDiff = 1; + while (teacherByFormation[indDiff] + diff < 0) indDiff++; + teacherByFormation[indDiff] += diff; + } + + // Cria vetor de porcentagens de carreira dos professores + req.teacherFormation.forEach((formation, i) => { + lastCity.percentage_teacher_career.push({ + formation_level_id: formation.idFormationLevel, + percentage: Number((teacherByFormation[i]*100).toFixed(2)), + }) + }); + + lastLocations.forEach((location) => { + location.education_level.forEach((educationLevel) => { + let educationLevelId = educationLevel.education_level_short_id; + + let currentTeachingHours = req.teachingHours[educationLevelId-1].shifts; + + if(educationLevelId === 1) { // Devido a divisão da creche é necessário tratá-la separadamente. + educationLevel.classes_school_year.forEach((schoolYear) => { // Aplicamos os cálculos para os anos da creche + let teachingTimeFullPeriod = schoolYear.full_period_classes * currentTeachingHours[2].value * req.schoolDays[educationLevelId-1].value; + let teachingTimeNight = schoolYear.night_classes * currentTeachingHours[1].value * req.schoolDays[educationLevelId-1].value; + let teachingTimeDay = schoolYear.day_classes * currentTeachingHours[0].value * req.schoolDays[educationLevelId-1].value; + + let currentTeacherByClass = (location.location_id === 1) ? req.educationSchoolYear[schoolYear.school_year_id].teacherByClass.urban : req.educationSchoolYear[schoolYear.school_year_id].teacherByClass.country; + + let numberOfTeacherFullPeriod = 0; + let numberOfTeacherNight = 0; + let numberOfTeacherDay = 0; + lastCity.percentage_teacher_career.forEach(career => { + let journeyObj = req.teacherFormation.find(formation => formation.idFormationLevel === career.formation_level_id) + let journey = journeyObj.journeyWithInteraction/100 * journeyObj.journeyTotal; + numberOfTeacherFullPeriod += (teachingTimeFullPeriod / journey) * currentTeacherByClass * career.percentage/100; + numberOfTeacherNight += (teachingTimeNight / journey) * currentTeacherByClass * career.percentage/100; + numberOfTeacherDay += (teachingTimeDay / journey) * currentTeacherByClass * career.percentage/100; + }) + numberOfTeacherFullPeriod = parseFloat(numberOfTeacherFullPeriod.toFixed(2)); + numberOfTeacherNight = parseFloat(numberOfTeacherNight.toFixed(2)); + numberOfTeacherDay = parseFloat(numberOfTeacherDay.toFixed(2)); + + schoolYear.teacherNumber = { + total_teacher : numberOfTeacherDay + numberOfTeacherNight + numberOfTeacherFullPeriod, + total_teacher_full_period : numberOfTeacherFullPeriod, + total_teacher_partial : numberOfTeacherNight + numberOfTeacherDay + } + }) + + // Calculamos para o educationLevel usando reduce + function reducer(key) { return (sum, elem) => sum + elem.teacherNumber[key]} + educationLevel.teacherNumber = { + total_teacher : educationLevel.classes_school_year.reduce(reducer('total_teacher'), 0), + total_teacher_full_period : educationLevel.classes_school_year.reduce(reducer('total_teacher_full_period'), 0), + total_teacher_partial : educationLevel.classes_school_year.reduce(reducer('total_teacher_partial'), 0) + } + + // function reducerList(idx, key) { return (sum, elem) => sum + elem.teacherNumber.careerLevels[idx][key]} + educationLevel.teacherNumber.careerLevels = []; + req.teacherFormation.forEach((formation, i) => { + let totalTeacherFullPeriodCareer = educationLevel.teacherNumber.total_teacher_full_period * teacherByFormation[i]; + let totalTeacherPartialCareer = educationLevel.teacherNumber.total_teacher_partial * teacherByFormation[i]; + + educationLevel.teacherNumber.careerLevels.push({ + sequence: formation.sequence, + denomination: formation.denomination, + formation_level_id: formation.idFormationLevel, + total_teacher_career: totalTeacherFullPeriodCareer + totalTeacherPartialCareer, + total_teacher_full_period_career: totalTeacherFullPeriodCareer, + total_teacher_partial_career:totalTeacherPartialCareer, + }) + }) + } + + else { + let teachingTimeFullPeriod = educationLevel.enrollment.full_period_classes * currentTeachingHours[2].value * req.schoolDays[educationLevelId-1].value; + let teachingTimeNight = educationLevel.enrollment.night_classes * currentTeachingHours[1].value * req.schoolDays[educationLevelId-1].value; + let teachingTimeDay = educationLevel.enrollment.day_classes * currentTeachingHours[0].value * req.schoolDays[educationLevelId-1].value; + + let currentTeacherByClass = (location.location_id === 1) ? req.educationSchoolYear[educationLevelId].teacherByClass.urban : req.educationSchoolYear[educationLevelId].teacherByClass.country; + + let numberOfTeacherFullPeriod = 0; + let numberOfTeacherNight = 0; + let numberOfTeacherDay = 0; + lastCity.percentage_teacher_career.forEach(career => { + let journeyObj = req.teacherFormation.find(formation => formation.idFormationLevel === career.formation_level_id) + let journey = journeyObj.journeyWithInteraction/100 * journeyObj.journeyTotal; + numberOfTeacherFullPeriod += (teachingTimeFullPeriod / journey) * currentTeacherByClass * career.percentage/100; + numberOfTeacherNight += (teachingTimeNight / journey) * currentTeacherByClass * career.percentage/100; + numberOfTeacherDay += (teachingTimeDay / journey) * currentTeacherByClass * career.percentage/100; + }) + numberOfTeacherFullPeriod = parseFloat(numberOfTeacherFullPeriod.toFixed(2)); + numberOfTeacherNight = parseFloat(numberOfTeacherNight.toFixed(2)); + numberOfTeacherDay = parseFloat(numberOfTeacherDay.toFixed(2)); + + educationLevel.teacherNumber = { + total_teacher : numberOfTeacherDay + numberOfTeacherNight + numberOfTeacherFullPeriod, + total_teacher_full_period : numberOfTeacherFullPeriod, + total_teacher_partial : numberOfTeacherNight + numberOfTeacherDay + } + + educationLevel.teacherNumber.careerLevels = []; + req.teacherFormation.forEach((formation, i) => { + let totalTeacherFullPeriodCareer = educationLevel.teacherNumber.total_teacher_full_period * teacherByFormation[i]; + let totalTeacherPartialCareer = educationLevel.teacherNumber.total_teacher_partial * teacherByFormation[i]; + + educationLevel.teacherNumber.careerLevels.push({ + sequence: formation.sequence, + denomination: formation.denomination, + formation_level_id: formation.idFormationLevel, + total_teacher_career: totalTeacherFullPeriodCareer + totalTeacherPartialCareer, + total_teacher_full_period_career: totalTeacherFullPeriodCareer, + total_teacher_partial_career:totalTeacherPartialCareer, + }) + }) + + } + }) + }) + } + + next(); +}, response('classroom_count')); + +module.exports = classroomCountApp; + diff --git a/src/libs/routes_v2/courseCount.js b/src/libs/routes_v2/courseCount.js new file mode 100644 index 00000000..404ed2eb --- /dev/null +++ b/src/libs/routes_v2/courseCount.js @@ -0,0 +1,814 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); +const { join } = require('lodash'); + +const courseCountApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +let rqf = new ReqQueryFields(); + +let rqfMapfor = new ReqQueryFields(); + +courseCountApp.get('/upper_adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 7; ++i) { + req.result.push({ + id: i, + name: id2str.upperAdmDependency(i) + }); + }; + next(); +}, response('upper_adm_dependency')); + +courseCountApp.get('/years', (req, res, next) => { + req.sql.from('curso_ens_superior') + .field('DISTINCT curso_ens_superior.ano_censo', 'year') + .where('curso_ens_superior.ano_censo > 2010'); + next(); +}, query, response('years')); + +courseCountApp.get('/year_range', (req, res, next) => { + req.sql.from('curso_ens_superior') + .field('MIN(curso_ens_superior.ano_censo)', 'start_year') + .field('MAX(curso_ens_superior.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +courseCountApp.get('/academic_organization', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 5; ++i) { + req.result.push({ + id: i, + name: id2str.academicOrganization(i) + }); + }; + next(); +}, response('academic_organization')); + +courseCountApp.get('/ocde_geral', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 8; ++i) { + req.result.push({ + id: i, + name: id2str.ocdeGeral(i) + }); + }; + next(); +}, response('ocde_geral')); + +courseCountApp.get('/ocde_specific', (req, res, next) => { + req.result = []; + const defaultCase = null; + for(let i = 1; i <= 86; ++i) { + let obj = { + id: i, + name: id2str.ocdeSpecific(i) + }; + if (obj.name !== id2str.ocdeSpecific(defaultCase)){ + req.result.push(obj); + } + }; + req.result.push({ + id: defaultCase, + name: id2str.ocdeSpecific(defaultCase) + }); + next(); +}, response('ocde_specific')); + +courseCountApp.get('/ocde_detailed', (req, res, next) => { + req.result = []; + const defaultCase = null; + for(let i = 142; i <= 863; ++i) { + let obj = { + id: i, + name: id2str.ocdeDetailed(i) + }; + if (obj.name !== id2str.ocdeDetailed(defaultCase)){ + req.result.push(obj); + } + }; + req.result.push({ + id: defaultCase, + name: id2str.ocdeDetailed(defaultCase) + }); + next(); +}, response('ocde_detailed')); + +courseCountApp.get('/cine_geral', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 10; ++i) { + req.result.push({ + id: i, + name: id2str.cineGeral(i) + }); + }; + next(); +}, response('cine_geral')); + +courseCountApp.get('/cine_specific', (req, res, next) => { + req.result = []; + const defaultCase = null; + for(let i = 1; i <= 104; ++i) { + let obj = { + id: i, + name: id2str.cineSpecific(i) + }; + if (obj.name !== id2str.cineSpecific(defaultCase)){ + req.result.push(obj); + } + }; + req.result.push({ + id: defaultCase, + name: id2str.cineSpecific(defaultCase) + }); + next(); +}, response('cine_specific')); + +courseCountApp.get('/cine_detailed', (req, res, next) => { + req.result = []; + const defaultCase = null; + for(let i = 11; i <= 1041; ++i) { + let obj = { + id: i, + name: id2str.cineDetailed(i) + }; + if (obj.name !== id2str.cineDetailed(defaultCase)){ + req.result.push(obj); + } + }; + req.result.push({ + id: defaultCase, + name: id2str.cineDetailed(defaultCase) + }); + next(); +}, response('cine_detailed')); + +courseCountApp.get('/academic_level', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.academicLevel(i) + }); + }; + next(); +}, response('academic_level')); + +courseCountApp.get('/upper_education_mod', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 2; ++i) { + req.result.push({ + id: i, + name: id2str.upperEducationMod(i) + }); + }; + next(); +}, response('upper_education_mod')); + +courseCountApp.get('/is_free', (req, res, next) => { + req.result = [ + {id: null, name: 'Não Classificado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('is_free')); + +courseCountApp.get('/night_time', (req, res, next) => { + req.result = [{ + id: 9, + name: id2str.nightTime(9) + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.nightTime(i) + }) + } + next(); +}, response('night_time')); + +courseCountApp.get('/university', (req, res, next) => { + req.sql.from('curso_ens_superior') + .field('DISTINCT curso_ens_superior.nome_ies', 'nome') + .field('curso_ens_superior.cod_ies', 'cod') + next(); +}, query, response('university')); + +courseCountApp.get('/localoffer', (req, res, next) => { + req.sql.from('localoferta_ens_superior', 'l') + .field('DISTINCT l.nome', 'localoffer_name') + .field('l.cod_local_oferta', 'localoffer_id'); + next(); +}, query, response('localoffer')); + + +rqfMapfor.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'state', + table: 'municipio', + tableField: 'estado_id', + resultField: 'state_id', + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio', + foreignTable: 'localoferta_ens_superior' + } +}, 'filter').addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio', + foreignTable: 'localoferta_ens_superior' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio', + foreignTable: 'localoferta_ens_superior' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['id', 'nome'], + resultField: ['city_id', 'city_name'], + where: { + relation: '=', + type: 'integer', + field: 'id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio', + foreignTable: 'localoferta_ens_superior' + } +}).addValue({ + name:'academic_level', + table: 'curso_ens_superior', + tableField: 'cod_grau_academico', + resultField: 'academic_level_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_grau_academico' + } +}).addValue({ + name: 'min_year', + table: 'localoferta_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'localoferta_ens_superior', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'localoferta_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'localoferta_ens_superior', + field: 'ano_censo' + } +}).addValue({ + name:'course', + table: 'curso_ens_superior', + tableField: 'nome_curso', + resultField: 'course_name', + where: { + relation: 'LIKE', + type: 'string', + field: 'nome_curso' + } +}).addValueToField({ + name: 'campi', + table: 'localoferta_ens_superior', + tableField: ['cod_local_oferta', 'nome'], + resultField: ['campi_id', 'campi_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_local_oferta', + table: 'localoferta_ens_superior' + } +}, 'filter').addValue({ + name:'upper_adm_dependency', + table: 'curso_ens_superior', + tableField: 'par_categoria_administrativa', + resultField: 'upper_adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'par_categoria_administrativa' + } +}).addValue({ + name:'upper_education_mod', + table: 'curso_ens_superior', + tableField: 'cod_modalidade_ensino', + resultField: 'upper_education_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_modalidade_ensino' + } +}).addValue({ + name:'academic_organization', + table: 'curso_ens_superior', + tableField: 'cod_organizacao_academica', + resultField: 'academic_organization_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_organizacao_academica' + } +}) + + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'region', + table: 'localoferta_ens_superior', + tableField: ['nome_regiao', 'cod_regiao'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_regiao', + table: 'localoferta_ens_superior' + }, + join: { + primary: ['ano_censo', 'cod_curso'], + foreign: ['ano_censo', 'cod_curso'], + foreignTable: 'curso_ens_superior' + } +}).addValue({ + name: 'state', + table: 'localoferta_ens_superior', + tableField: ['sigla_uf_t', 'cod_uf_t'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_uf', + table: 'localoferta_ens_superior' + }, + join: { + primary: ['ano_censo', 'cod_curso'], + foreign: ['ano_censo', 'cod_curso'], + foreignTable: 'curso_ens_superior' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_curso', + foreignTable: 'curso_ens_superior' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_curso', + foreignTable: 'curso_ens_superior' + } +}).addValue({ + name: 'city', + table: 'localoferta_ens_superior', + tableField: ['cod_municipio_t', 'nome_municipio_t'], + resultField: ['city_id', 'city_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_municipio', + table: 'localoferta_ens_superior' + }, + join: { + primary: ['ano_censo', 'cod_curso'], + foreign: ['ano_censo', 'cod_curso'], + foreignTable: 'curso_ens_superior' + } +}).addValue({ + name: 'localoffer', + table: 'localoferta_ens_superior', + tableField: ['cod_local_oferta', 'nome'], + resultField: ['localoffer_id', 'localoffer_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_curso', + table: 'curso_ens_superior' + }, + join: { + primary: ['ano_censo', 'cod_curso'], + foreign: ['ano_censo', 'cod_curso'], + foreignTable: 'curso_ens_superior' + } +}).addValue({ + name: 'campi', + table: 'localoferta_ens_superior', + tableField: ['cod_local_oferta', 'nome'], + resultField: ['campi_id', 'campi_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_curso', + table: 'curso_ens_superior' + }, + join: { + primary: ['ano_censo', 'cod_curso'], + foreign: ['ano_censo', 'cod_curso'], + foreignTable: 'curso_ens_superior' + } +}).addValue({ + name: 'university', + table: 'curso_ens_superior', + tableField: ['cod_ies', 'nome_ies'], + resultField: ['university_id', 'university_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_ies' + } +}).addValue({ + name: 'universityLocalOffer', + table: 'curso_ens_superior', + tableField: ['cod_ies', 'nome_ies'], + resultField: ['university_id', 'university_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_ies' + } +}).addValue({ + name:'upper_adm_dependency', + table: 'curso_ens_superior', + tableField: 'par_categoria_administrativa', + resultField: 'upper_adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'par_categoria_administrativa' + } +}).addValue({ + name:'academic_organization', + table: 'curso_ens_superior', + tableField: 'cod_organizacao_academica', + resultField: 'academic_organization_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_organizacao_academica' + } +}).addValue({ + name:'course', + table: 'curso_ens_superior', + tableField: 'nome_curso', + resultField: 'course_name', + where: { + relation: 'LIKE', + type: 'string', + field: 'nome_curso' + } +}).addValue({ + name:'ocde_specific', + table: 'curso_ens_superior', + tableField: ['cod_ocde_area_especifica', 'nome_ocde_area_especifica'], + resultField: ['ocde_specific_id', 'ocde_specific_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_ocde_area_especifica' + } +}).addValue({ + name:'ocde_geral', + table: 'curso_ens_superior', + tableField: ['cod_ocde_area_geral', 'nome_ocde_area_geral'], + resultField: ['ocde_geral_id', 'ocde_geral_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_ocde_area_geral' + } +}).addValue({ + name:'ocde_detailed', + table: 'curso_ens_superior', + tableField: ['cod_ocde_area_detalhada', 'nome_ocde_area_detalhada'], + resultField: ['ocde_detailed_id', 'ocde_detailed_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_ocde_area_detalhada' + } +}).addValue({ + name:'cine_specific', + table: 'curso_ens_superior', + tableField: ['cod_cine_area_especifica', 'nome_cine_area_especifica'], + resultField: ['cine_specific_id', 'cine_specific_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_cine_area_especifica' + } +}).addValue({ + name:'cine_geral', + table: 'curso_ens_superior', + tableField: ['cod_cine_area_geral', 'nome_cine_area_geral'], + resultField: ['cine_geral_id', 'cine_geral_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_cine_area_geral' + } +}).addValue({ + name:'cine_detailed', + table: 'curso_ens_superior', + tableField: ['cod_cine_area_detalhada', 'nome_cine_area_detalhada'], + resultField: ['cine_detailed_id', 'cine_detailed_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_cine_area_detalhada' + } +}).addValue({ + name:'academic_level', + table: 'curso_ens_superior', + tableField: 'cod_grau_academico', + resultField: 'academic_level_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_grau_academico' + } +}).addValue({ + name:'upper_education_mod', + table: 'curso_ens_superior', + tableField: 'cod_modalidade_ensino', + resultField: 'upper_education_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_modalidade_ensino' + } +}).addValue({ + name:'is_free', + table: 'curso_ens_superior', + tableField: 'gratuito', + resultField: 'is_free_id', + where: { + relation: '=', + type: 'boolean', + field: 'gratuito' + } +}).addValue({ + name:'night_time', + table: 'curso_ens_superior', + tableField: 'noturno_curso_t', + resultField: 'night_time_id', + where: { + relation: '=', + type: 'integer', + field: 'noturno_curso_t' + } +}).addValue({ + name:'situation', + table: 'curso_ens_superior', + tableField: 'cod_situacao_curso', + resultField: 'situacao_curso_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_situacao_curso' + } +}).addValue({ + name:'year', + table: 'curso_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'min_year', + table: 'curso_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'curso_ens_superior', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'curso_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'curso_ens_superior', + field: 'ano_censo' + } +}) + +courseCountApp.get('/count_by_name', rqfMapfor.parse(), (req, res, next) => { + req.sql.from('localoferta_ens_superior') + .field('COUNT(DISTINCT localoferta_ens_superior.cod_curso)', 'total') + .field('localoferta_ens_superior.ano_censo', 'year') + .join ('curso_ens_superior ON (localoferta_ens_superior.cod_curso = curso_ens_superior.cod_curso) AND (localoferta_ens_superior.ano_censo = curso_ens_superior.ano_censo)') + .where('curso_ens_superior.cod_nivel_academico = 1') + .where('curso_ens_superior.tipo_atributo_ingresso <> 1 OR curso_ens_superior.tipo_atributo_ingresso is NULL') + .group('localoferta_ens_superior.ano_censo') + .order('localoferta_ens_superior.ano_censo') + + next(); +}, rqfMapfor.build(), query, (req, res, next) =>{ + if ('course' in req.dims){ + var total_course = req.result.reduce((total, cur) => {return total += cur.total}, 0) + for (var course of req.result){ + course.percentage = Number((( course.total / total_course ) * 100).toFixed(2)) + } + } + next(); +}, id2str.transform(), response('count_by_name')); + +courseCountApp.get('/', rqf.parse(), (req, res, next) => { + if ("localoffer" in req.dims || "campi" in req.dims) { + if ("university" in req.dims || "universityLocalOffer" in req.dims) { + req.sql.from('curso_ens_superior') + .field('curso_ens_superior.ano_censo', 'year') + .field('COUNT(localoferta_ens_superior.cod_local_oferta)', 'total') + .where('curso_ens_superior.tipo_atributo_ingresso <> 1 OR curso_ens_superior.tipo_atributo_ingresso is NULL') + .where('curso_ens_superior.cod_nivel_academico = 1') + .group('curso_ens_superior.ano_censo') + .order('curso_ens_superior.ano_censo') + .order('localoferta_ens_superior.cod_local_oferta'); + } else { + req.sql.from('curso_ens_superior') + .field('curso_ens_superior.ano_censo', 'year') + .field('COUNT(localoferta_ens_superior.cod_local_oferta)', 'total') + .field('localoferta_ens_superior.cod_ies', 'university_id') + .field('curso_ens_superior.nome_ies', 'university_name') + .where('curso_ens_superior.tipo_atributo_ingresso <> 1 OR curso_ens_superior.tipo_atributo_ingresso is NULL') + .where('curso_ens_superior.cod_nivel_academico = 1') + .group('curso_ens_superior.ano_censo') + .group('localoferta_ens_superior.cod_ies') + .group('curso_ens_superior.nome_ies') + .order('curso_ens_superior.ano_censo') + .order('localoferta_ens_superior.cod_local_oferta'); + } + } else if (("state" in req.dims) || ("city" in req.dims) || ("microregion" in req.dims) || ("mesoregion" in req.dims) || ("region" in req.dims) || + ("state" in req.filter) || ("city" in req.filter) || ("microregion" in req.filter) || ("mesoregion" in req.filter) || ("region" in req.filter) ) { + if ("course" in req.dims){ + req.sql.from('curso_ens_superior') + .field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('curso_ens_superior.ano_censo', 'year') + .group('curso_ens_superior.ano_censo') + .order('curso_ens_superior.ano_censo') + .where('curso_ens_superior.cod_nivel_academico = 1') + } + else{ + req.sql.from('curso_ens_superior') + .field('COUNT(DISTINCT curso_ens_superior.cod_curso)', 'total') + .field("'Brasil'", 'name') + .field('curso_ens_superior.ano_censo', 'year') + .group('curso_ens_superior.ano_censo') + .order('curso_ens_superior.ano_censo') + .where('curso_ens_superior.tipo_atributo_ingresso <> 1 OR curso_ens_superior.tipo_atributo_ingresso is NULL') + .where('curso_ens_superior.cod_nivel_academico = 1'); + } + + } else if ("university" in req.dims || "universityLocalOffer" in req.dims) { + req.sql.from('curso_ens_superior') + .field('COUNT(curso_ens_superior.cod_curso)', 'total') + .field("'Brasil'", 'name') + .field('curso_ens_superior.ano_censo', 'year') + .group('curso_ens_superior.cod_ies') + .group('curso_ens_superior.ano_censo') + .order('curso_ens_superior.cod_ies') + .order('curso_ens_superior.ano_censo') + .where('curso_ens_superior.tipo_atributo_ingresso <> 1 OR curso_ens_superior.tipo_atributo_ingresso is NULL') + .where('curso_ens_superior.cod_nivel_academico = 1'); + } else { + req.sql.from('curso_ens_superior') + .field('COUNT(curso_ens_superior.cod_curso)', 'total') + .field("'Brasil'", 'name') + .field('curso_ens_superior.ano_censo', 'year') + .group('curso_ens_superior.ano_censo') + .order('curso_ens_superior.ano_censo') + .where('curso_ens_superior.tipo_atributo_ingresso <> 1 OR curso_ens_superior.tipo_atributo_ingresso is NULL') + .where('curso_ens_superior.cod_nivel_academico = 1'); + } + next(); +}, rqf.build(), query, (req, res, next) =>{ + if ('course' in req.dims){ + var total_course = req.result.reduce((total, cur) => {return total += cur.total}, 0) + for (var course of req.result){ + course.percentage = Number((( course.total / total_course ) * 100).toFixed(2)) + } + } + next(); +}, id2str.transform(), addMissing(rqf), response('course_count')); + +module.exports = courseCountApp; diff --git a/src/libs/routes_v2/courseStudents.js b/src/libs/routes_v2/courseStudents.js new file mode 100644 index 00000000..77180cb2 --- /dev/null +++ b/src/libs/routes_v2/courseStudents.js @@ -0,0 +1,201 @@ +const express = require('express'); + +const courseStudentsApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +let rqf = new ReqQueryFields(); + +courseStudentsApp.get('/enrolled_vacancies_freshmen', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 3; ++i) { + req.result.push({ + id: i, + name: id2str.enrolledVacanciesFreshmen(i) + }); + }; + next(); +}, response('enrolled_vacancies_freshmen')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}) +.addValueToField({ + name: 'state', + table: 'ies_ens_superior', + tableField: 'cod_uf_ies', + resultField: 'state_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_uf_ies', + table: 'ies_ens_superior' + } +}, 'filter') +.addValueToField({ + name: 'min_year', + table: 'curso_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo', + table: 'curso_ens_superior' + } +}, 'filter') +.addValueToField({ + name: 'max_year', + table: 'curso_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo', + table: 'ies_ens_superior' + } +}, 'filter') +.addValue({ + name: 'upper_adm_dependency', + table: 'curso_ens_superior', + tableField: 'par_categoria_administrativa', + resultField: 'upper_adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'par_categoria_administrativa', //cod_categoria_administrativa + table: 'curso_ens_superior' + } +}) +.addValue({ + name: 'course', + table: 'curso_ens_superior', + tableField: 'nome_curso', + resultField: 'course_name', + where: { + relation: '=', + type: 'string', + field: 'nome_curso', + table: 'curso_ens_superior' + } +}) +.addValue({ + name: 'upper_education_mod', + table: 'curso_ens_superior', + tableField: 'cod_modalidade_ensino', + resultField: 'upper_education_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_modalidade_ensino', + table: 'curso_ens_superior' + } +}) +.addValue({ + name: 'academic_organization', + table: 'curso_ens_superior', + tableField: 'cod_organizacao_academica', + resultField: 'academic_organization_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_organizacao_academica', + table: 'curso_ens_superior' + } +}) +.addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_ies', + foreignTable: 'ies_ens_superior' + } +}) +.addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_ies', + foreignTable: 'ies_ens_superior' + } +}) +.addValue({ + name: 'city', + table: 'municipio', + tableField: ['id', 'nome'], + resultField: ['city_id', 'city_name'], + where: { + relation: '=', + type: 'integer', + field: 'id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_ies', + foreignTable: 'ies_ens_superior' + } +}) + + + +courseStudentsApp.get('/', rqf.parse(), (req, res, next) => { + req.sql.field("curso_ens_superior.ano_censo", "year") + .field("SUM(curso_ens_superior.quantidade_inscritos_total)", "inscritos_total") + .field("SUM(curso_ens_superior.quantidade_vagas_totais)", "vagas_totais") + .field("SUM(curso_ens_superior.quantidade_ingresso_curso)", "ingresso_curso") + .from("curso_ens_superior") + .join("ies_ens_superior ON curso_ens_superior.ano_censo = ies_ens_superior.ano_censo AND curso_ens_superior.cod_ies = ies_ens_superior.cod_ies") + .where("curso_ens_superior.cod_nivel_academico = 1") + .where("curso_ens_superior.cod_grau_academico = 2 OR curso_ens_superior.cod_grau_academico = 4") + .group("curso_ens_superior.ano_censo") + .order("curso_ens_superior.ano_censo") + next(); + +}, rqf.build(), query, (req, res, next) => { + for (var res of req.result){ + res.inscritos_total = Number(res.inscritos_total); + res.vagas_totais = Number(res.vagas_totais); + res.ingresso_curso = Number(res.ingresso_curso); + res.total = null; + } + + next(); +}, id2str.transform(), response('course_students')) + +module.exports = courseStudentsApp; diff --git a/src/libs/routes_v2/cub.js b/src/libs/routes_v2/cub.js new file mode 100644 index 00000000..cfc2848a --- /dev/null +++ b/src/libs/routes_v2/cub.js @@ -0,0 +1,227 @@ +const express = require('express'); + +const cubApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const passport = require('passport'); + +const download = require(`${libs}/middlewares/downloadDatabase`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); +let rqfCount = new ReqQueryFields(); + +cubApp.get('/year_range', (req, res, next) => { + req.sql.from('cub') + .field('MIN(cub.ano_censo)', 'start_year') + .field('MAX(cub.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +cubApp.get('/years', (req, res, next) => { + req.sql.from('cub') + .field('DISTINCT cub.ano_censo', 'year'); + next(); +}, query, response('years')); + +cubApp.get('/months', (req, res, next) => { + req.sql.from('cub') + .field('DISTINCT cub.mes_censo', 'month'); + next(); +}, query, response('months')); + +cubApp.get('/years_months', (req, res, next) => { + req.sql.from('cub') + .field('DISTINCT cub.ano_censo AS "year", cub.mes_censo AS "month"'); + next(); +}, query, response('years_months')); + +cubApp.get('/price_type', (req, res, next) => { + req.sql.from('cub') + .field('DISTINCT cub.tipo_preco', 'price_type'); + next(); +}, query, response('price_type')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['sigla', 'id'], + resultField: ['sigla_uf', 'cod_uf'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'cub' + }, + // join: { + // primary: 'id', + // foreign: 'estado_id', + // foreignTable: 'cub' + // } +}).addValue({ + name: 'min_year', + table: 'cub', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'cub', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'cub', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'cub', + field: 'ano_censo' + } +}).addValue({ + name: 'min_month', + table: 'cub', + tableField: 'mes_censo', + resultField: 'month', + where: { + relation: '>=', + type: 'integer', + table: 'cub', + field: 'mes_censo' + } +}).addValue({ + name: 'max_month', + table: 'cub', + tableField: 'mes_censo', + resultField: 'month', + where: { + relation: '<=', + type: 'integer', + table: 'cub', + field: 'mes_censo' + } +}); + +cubApp.get('/last_state_values', rqf.parse(), rqf.build(), (req, res, next) => { + + var price_by_id = squel.select().from('cub') + .field('estado_id') + .field('MAX(ano_censo*100 + mes_censo)', 'ano_censo') + .group('estado_id') + + if (req.filter.size || req.dims.size){ + if ('state' in req.filter || 'state' in req.dims){ + //req.sql = states + req.sql.from('cub') + .field('cub.ano_censo', 'ano') + .field('cub.mes_censo', 'mes') + .field('cub.tipo_preco', 'tipo_preco') + .field('cub.preco', 'preco') + .join( + price_by_id, + 'sub', + 'cub.estado_id = sub.estado_id AND cub.ano_censo = (sub.ano_censo/100)' + ) + .join('estado', null, 'cub.estado_id = estado.id') + .group('cub.ano_censo') + .group('cub.mes_censo') + .group('cub.tipo_preco') + .group('cub.preco') + } + else{ + req.sql.from("cub") + } + } + else{ + //req.sql = average + req.sql.from( + squel.select().from('cub') + .field('cub.tipo_preco', 'tipo_preco') + .field('cub.preco', 'preco') + .join(price_by_id, 'sub', + 'cub.estado_id = sub.estado_id AND cub.ano_censo = (sub.ano_censo/100)' + ) + .join('estado', null, 'cub.estado_id = estado.id') + , "states") + .field('AVG(states.preco)', 'preco') + .field("'BR'", 'sigla_uf') + .field('states.tipo_preco') + .group('states.tipo_preco') + } + next(); +}, query, id2str.transform(), response('last_state_values')) + +cubApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + if (req.filter.size || req.filter.dims) { + if ('state' in req.filter || 'state' in req.dims) { + req.sql.from('cub') + .field('cub.estado_id', 'cod_uf') + .field('estado.sigla', 'sigla_uf') + .field('cub.tipo_preco', 'tipo_preco') + .field('cub.preco', 'preco') + .join('estado', null, 'cub.estado_id=estado.id') + .group('cub.ano_censo') + .group('cub.mes_censo') + .group('cub.estado_id') + .group('estado.sigla') + .group('cub.tipo_preco') + .group('cub.preco') + } else { + req.sql.from('cub') + .field("'BR'", 'sigla_uf') + .field("cub.tipo_preco", 'tipo_preco') + .field('AVG(cub.preco)', 'preco') + .join('estado', null, 'cub.estado_id=estado.id') + .group('cub.ano_censo') + .group('cub.mes_censo') + .group('cub.tipo_preco') + } + } else { + req.sql.from('cub') + .field('cub.estado_id', 'cod_uf') + .field('estado.sigla', 'sigla_uf') + .field('cub.tipo_preco', 'tipo_preco') + .field('cub.preco', 'preco') + .join('estado', null, 'cub.estado_id=estado.id') + .group('cub.ano_censo') + .group('cub.mes_censo') + .group('cub.estado_id') + .group('estado.sigla') + .group('cub.tipo_preco') + .group('cub.preco') + } + + next(); +}, query, id2str.transform(), response('cub')); + +module.exports = cubApp; diff --git a/src/libs/routes_v2/dailyChargeAmount.js b/src/libs/routes_v2/dailyChargeAmount.js new file mode 100644 index 00000000..4af6cb7d --- /dev/null +++ b/src/libs/routes_v2/dailyChargeAmount.js @@ -0,0 +1,467 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const dailyChargeAmountApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: { include: [200] } }).middleware; + +let rqf = new ReqQueryFields(); + +let rqfCount = new ReqQueryFields(); + +//dailyChargeAmountApp.use(cache('15 day')); + +dailyChargeAmountApp.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')); + +dailyChargeAmountApp.get('/years', (req, res, next) => { + req.sql.from('turma') + .field('DISTINCT turma.ano_censo', 'year'); + next(); +}, query, response('years')); + +dailyChargeAmountApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'turma\''); + next(); +}, query, response('source')); + +dailyChargeAmountApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for (let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +dailyChargeAmountApp.get('/adm_dependency_detailed', cache('15 day'), (req, res, next) => { + req.result = []; + for (let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +dailyChargeAmountApp.get('/location', cache('15 day'), (req, res, next) => { + req.result = [ + { id: 1, name: 'Urbana' }, + { id: 2, name: 'Rural' } + ]; + next(); +}, response('location')); + +dailyChargeAmountApp.get('/rural_location', (req, res, next) => { + req.result = [ + { id: 1, name: "Urbana" }, + { id: 2, name: "Rural" }, + { id: 3, name: "Rural - Ãrea de assentamento" }, + { id: 4, name: "Rural - Terra indÃgena" }, + { id: 5, name: "Rural - Ãrea remanescente de quilombos" }, + { id: 6, name: "Rural - Unidade de uso sustentável" } + ]; + next(); +}, response('rural_location')); + +dailyChargeAmountApp.get('/education_level_short', (req, res, next) => { + req.result = [ + { id: null, name: 'Não classificada' }, + { id: 1, name: 'Creche' }, + { id: 2, name: 'Pré-Escola' }, + { id: 3, name: 'Ensino Fundamental - anos iniciais' }, + { id: 4, name: 'Ensino Fundamental - anos finais' }, + { id: 5, name: 'Ensino Médio' }, + { id: 6, name: 'EJA' }, + { id: 7, name: 'EE exclusiva' } + ]; + next(); +}, response('education_level_short')); + +dailyChargeAmountApp.get('/average/education_level_mod', (req, res, next) => { + req.result = [ + { id: null, name: 'Não classificada' }, + { id: 1, name: 'Creche' }, + { id: 2, name: 'Pré-Escola' }, + { id: 3, name: 'Educação Infantil Unificada' }, + { id: 4, name: 'Ensino Fundamental - anos iniciais' }, + { id: 5, name: 'Ensino Fundamental - anos finais' }, + { id: 6, name: 'Ensino Médio' }, + { id: 7, name: 'Turma Multisseriadas e Multietapas' }, + { id: 8, name: 'EJA - Ensino Fundamental' }, + { id: 9, name: 'EJA - Ensino Médio' }, + { id: 10, name: 'Educação Profissional' } + ]; + next(); +}, response('education_level_mod')); + +dailyChargeAmountApp.get('/period', (req, res, next) => { + req.result = []; + for (let i = 1; i <= 3; ++i) { + req.result.push({ + id: i, + name: id2str.period(i) + }); + }; + req.result.push({ + id: 99, + name: id2str.period(99) + }); + next(); +}, response('period')); + +dailyChargeAmountApp.get('/integral_time', (req, res, next) => { + req.result = [ + { id: null, name: 'Não DisponÃvel' }, + { id: 0, name: 'Não' }, + { id: 1, name: 'Sim' } + ]; + next(); +}, response('integral_time')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'turma' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'turma' + } +}).addValue({ + name: 'min_year', + table: 'turma', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'turma', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'turma', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'turma', + field: 'ano_censo' + } +}).addValue({ + name: 'location', + table: 'turma', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'adm_dependency', + table: 'turma', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'turma', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'rural_location', + table: 'turma', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'education_level_mod', + table: 'turma', + tableField: 'etapas_mod_ensino_segmento_id', + resultField: 'education_level_mod_id', + dontGroup: true, + where: { + relation: '=', + type: 'integer', + field: 'etapas_mod_ensino_segmento_id' + } +}).addValue({ + name: 'period', + table: 'turma', + tableField: 'turma_turno_id', + resultField: 'period_id', + where: { + relation: '=', + type: 'integer', + field: 'turma_turno_id' + } +}).addValue({ + name: 'integral_time', + table: 'turma', + tableField: 'tempo_integral', + resultField: 'integral_time_id', + where: { + relation: '=', + type: 'boolean', + field: 'tempo_integral' + } +}).addValue({ + name: 'education_level_short', + table: 'turma', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}); + +dailyChargeAmountApp.get('/', rqf.parse(), (req, res, next) => { + var status = 0; + if ('period' in req.filter) { + if (req.filter['period'].length == 1 && (req.filter['period'][0] == '3' || req.filter['period'][0] === '4')) { + status = 1; + } else if (req.filter['period'].length <= 2 && (req.filter['period'].includes('1') || req.filter['period'].includes('2')) && (!req.filter['period'].includes('3'))) { + status = 1; + } + } else if (req.filter['integral_time'] == '1') { + status = 1; + } + + if (status) { + req.sql.from('turma') + .field('turma.ano_censo', 'year') + .field('turma.etapa_resumida', 'education_level_short_id') + .field('AVG(turma.duracao_turma)/60.0', 'average_class_duration') + .field('MEDIAN(turma.duracao_turma)/60.0', 'median_class_duration') + .field('STDDEV_SAMP(turma.duracao_turma)/60.0', 'std_class_duration') + .field('QUANTILE(turma.duracao_turma, 0.25)/60.0', 'fstqt_class_duration') + .field('QUANTILE(turma.duracao_turma, 0.75)/60.0', 'thdqt_class_duration') + .group('turma.ano_censo') + .group('turma.etapa_resumida') + .order('turma.ano_censo') + .order('turma.etapa_resumida') + .where('((turma.tipo_turma_id <= 3 AND turma.tipo_atendimento_id is NULL) OR (turma.tipo_atendimento_id <= 2 AND turma.tipo_turma_id is NULL)) and turma.dependencia_adm_id <= 3') + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + + next(); + +}, rqf.build(), query, addMissing(rqf), (req, res, next) => { + + function sliced(object) { + return object['education_level_short_id'] > 3; + } + + if ('period' in req.filter || 'period' in req.dims) { + req.filter['period'].forEach((element) => { + if (element == '3') + req.result = req.result.filter(sliced); + }); + } + + next(); +}, id2str.transform(), response('turma')); + +dailyChargeAmountApp.get('/average', rqf.parse(), rqf.build(), (req, res, next) => { + var status = 0; + if (('education_level_mod' in req.filter || 'education_level_mod' in req.dims) + && ('integral_time' in req.filter)) { + if (req.filter['integral_time'] == '0' + && ('period' in req.filter)) { + if (req.filter['period'].length == 1 + && req.filter['period'][0] == '3') { + status = 1; + } else if (req.filter['period'].length <= 2 + && (req.filter['period'].includes('1') + || req.filter['period'].includes('2')) + && (!req.filter['period'].includes('3'))) { + status = 1; + } + } else if (req.filter['integral_time'] == '1') { + status = 1; + } + } + + if (status) { + let baseQ = req.sql.clone(); + + let tableR = baseQ.clone(); + tableR.from('turma') + .field('duracao_turma') + .field('etapas_mod_ensino_segmento_id') + .field('ROW_NUMBER() OVER(PARTITION BY etapas_mod_ensino_segmento_id ORDER BY duracao_turma)', 'rowno') + .where('((turma.tipo_turma_id <= 3 AND turma.tipo_atendimento_id is NULL) OR (turma.tipo_atendimento_id <= 2 AND turma.tipo_turma_id is NULL))') + + let tableG = baseQ.clone(); + tableG.from('turma') + .field('1+COUNT(*)', 'counter') + .field('etapas_mod_ensino_segmento_id') + .where('((turma.tipo_turma_id <= 3 AND turma.tipo_atendimento_id is NULL) OR (turma.tipo_atendimento_id <= 2 AND turma.tipo_turma_id is NULL))') + .group('etapas_mod_ensino_segmento_id') + + let joinRG = squel.select(); + joinRG.from(tableR, 'R') + .field('R.etapas_mod_ensino_segmento_id') + .field('AVG(1.0*R.duracao_turma)/60', 'median_value') + .join(tableG, 'G', 'R.etapas_mod_ensino_segmento_id = G.etapas_mod_ensino_segmento_id AND R.rowNo BETWEEN G.counter/2 AND G.counter/2+G.counter%2') + .group('R.etapas_mod_ensino_segmento_id') + + req.sql + .from('turma') + .from(joinRG, 'm') + .field('turma.ano_censo', 'year') + .field('turma.etapas_mod_ensino_segmento_id', 'education_level_mod_id') + .field('AVG(turma.duracao_turma)/60.0', 'average_class_duration') + .field('AVG(m.median_value)', 'median_class_duration') + .field('STDDEV_SAMP(turma.duracao_turma)/60.0', 'std_class_duration') + .field('QUANTILE(turma.duracao_turma, 0.25)/60.0', 'fstqt_class_duration') + .field('QUANTILE(turma.duracao_turma, 0.75)/60.0', 'thdqt_class_duration') + .group('turma.ano_censo') + .group('turma.etapas_mod_ensino_segmento_id') + .order('turma.ano_censo') + .order('turma.etapas_mod_ensino_segmento_id') + .where('((turma.tipo_turma_id <= 3 AND turma.tipo_atendimento_id is NULL) OR (turma.tipo_atendimento_id <= 2 AND turma.tipo_turma_id is NULL)) \ + and m.etapas_mod_ensino_segmento_id = turma.etapas_mod_ensino_segmento_id') + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + + next(); +}, query, addMissing(rqf), id2str.transform(), response('turma')); + +module.exports = dailyChargeAmountApp; diff --git a/src/libs/routes_v2/disciplines.js b/src/libs/routes_v2/disciplines.js new file mode 100644 index 00000000..63b05f32 --- /dev/null +++ b/src/libs/routes_v2/disciplines.js @@ -0,0 +1,682 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const disciplinesApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: { include: [200] } }).middleware; + +let rqf = new ReqQueryFields(); + +disciplinesApp.use(cache('15 day')); + +// Returns a tuple of start and ending years of the complete enrollments dataset. +disciplinesApp.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')); + +disciplinesApp.get('/years', (req, res, next) => { + req.sql.from('docente'). + field('DISTINCT docente.ano_censo', 'year'); + next(); +}, query, response('years')); + +disciplinesApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'docente\''); + next(); +}, query, response('source')); + +disciplinesApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for (let i = 1; i <= 8; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +disciplinesApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for (let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +disciplinesApp.get('/education_level_mod', (req, res, next) => { + req.result = []; + for (let i = 1; i <= 12; ++i) { + req.result.push({ + id: i, + name: id2str.educationLevelMod(i) + }); + } + req.result.push({ + id: 99, + name: id2str.educationLevelMod(99) + }); + next(); +}, response('education_level_mod')); + +disciplinesApp.get('/education_level_short', (req, res, next) => { + req.result = [ + { id: null, name: 'Não classificada' }, + { id: 1, name: 'Creche' }, + { id: 2, name: 'Pré-Escola' }, + { id: 3, name: 'Ensino Fundamental - anos iniciais' }, + { id: 4, name: 'Ensino Fundamental - anos finais' }, + { id: 5, name: 'Ensino Médio' }, + { id: 6, name: 'EJA' }, + { id: 7, name: 'EE exclusiva' } + ]; + next(); +}, response('education_level_short')); + +disciplinesApp.get('/location', (req, res, next) => { + req.result = []; + for (let i = 1; i <= 2; ++i) { + req.result.push({ + id: i, + name: id2str.location(i) + }); + }; + next(); +}, response('location')); + +disciplinesApp.get('/rural_location', (req, res, next) => { + req.result = []; + for (let i = 1; i <= 8; i++) { + req.result.push({ + id: i, + name: id2str.ruralLocation(i) + }); + }; + next(); +}, response('rural_location')); + +disciplinesApp.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')); + +disciplinesApp.get('/gender', (req, res, next) => { + req.result = [ + { id: 1, name: 'Masculino' }, + { id: 2, name: 'Feminino' } + ]; + next(); +}, response('gender')); + + +disciplinesApp.get('/contract_type', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.contractType("null") + }]; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.contractType(i) + }); + } + next(); +}, response('contract_type')); + +disciplinesApp.get('/ethnic_group', (req, res, next) => { + req.result = []; + for (let i = 0; i <= 5; ++i) { + req.result.push({ + id: i, + name: id2str.ethnicGroup(i) + }); + } + next(); +}, response('ethnic_group')); + +disciplinesApp.get('/discipline', (req, res, next) => { + req.result = []; + for (let i = 1; i <= 19; i++) { + req.result.push({ + id: i, + name: id2str.discipline(i) + }) + } + next(); +}, response('discipline')) + +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: 'contract_type', + table: 'docente', + tableField: 'tipo_contratacao', + resultField: 'contract_type_id', + where: { + relation: '=', + type: 'integer', + field: 'tipo_contratacao' + } +}).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_level_short', + table: 'docente', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}).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', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_regiao_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_estado_id', + foreignTable: 'docente' + } +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}, 'filter').addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'docente' + } +}, 'dims').addValueToField({ + 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' + } +}, 'filter').addValue({ + name: 'location', + table: 'docente', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'rural_location', + table: 'docente', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).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', + field: 'cor_raca' + } +}).addValue({ + name: 'discipline', + table: 'docente', + tableField: '', + resultField: '', + where: { + relation: '=', + type: 'integer', + field: '' + } +}); + +disciplinesApp.get('/', rqf.parse(), (req, res, next) => { + if ('discipline' in req.dims) { + // delete req.filter.discipline; + delete req.dims.discipline; + req.tmp_discipline = true; + + req.sql.field('SUM(n_disc)', 'total') + .field('SUM(n_disc_adequada)', 'total_suitable') + + .field('SUM(quimica_not_null)', 'total_quimica') + .field('SUM(adequacao_quimica)', 'total_suitable_quimica') + + .field('SUM(fisica_not_null)', 'total_fisica') + .field('SUM(adequacao_fisica)', 'total_suitable_fisica') + + .field('SUM(matematica_not_null)', 'total_matematica') + .field('SUM(adequacao_matematica)', 'total_suitable_matematica') + + .field('SUM(biologia_not_null)', 'total_biologia') + .field('SUM(adequacao_biologia)', 'total_suitable_biologia') + + .field('SUM(ciencias_not_null)', 'total_ciencias') + .field('SUM(adequacao_ciencias)', 'total_suitable_ciencias') + + .field('SUM(lingua_portuguesa_not_null)', 'total_lingua_portuguesa') + .field('SUM(adequacao_lingua_portuguesa)', 'total_suitable_lingua_portuguesa') + + .field('SUM(lingua_inglesa_not_null)', 'total_lingua_inglesa') + .field('SUM(adequacao_lingua_inglesa)', 'total_suitable_lingua_inglesa') + + .field('SUM(lingua_espanhola_not_null)', 'total_lingua_espanhola') + .field('SUM(adequacao_lingua_espanhola)', 'total_suitable_lingua_espanhola') + + .field('SUM(lingua_francesa_not_null)', 'total_lingua_francesa') + .field('SUM(adequacao_lingua_francesa)', 'total_suitable_lingua_francesa') + + .field('SUM(lingua_outra_not_null)', 'total_lingua_outra') + .field('SUM(adequacao_lingua_outra)', 'total_suitable_lingua_outra') + + .field('SUM(lingua_indigena_not_null)', 'total_lingua_indigena') + .field('SUM(adequacao_lingua_indigena)', 'total_suitable_lingua_indigena') + + .field('SUM(artes_not_null)', 'total_artes') + .field('SUM(adequacao_artes)', 'total_suitable_artes') + + .field('SUM(educacao_fisica_not_null)', 'total_educacao_fisica') + .field('SUM(adequacao_educacao_fisica)', 'total_suitable_educacao_fisica') + + .field('SUM(historia_not_null)', 'total_historia') + .field('SUM(adequacao_historia)', 'total_suitable_historia') + + .field('SUM(geografia_not_null)', 'total_geografia') + .field('SUM(adequacao_geografia)', 'total_suitable_geografia') + + .field('SUM(filosofia_not_null)', 'total_filosofia') + .field('SUM(adequacao_filosofia)', 'total_suitable_filosofia') + + .field('SUM(ensino_religioso_not_null)', 'total_ensino_religioso') + .field('SUM(adequacao_ensino_religioso)', 'total_suitable_ensino_religioso') + + .field('SUM(estudos_sociais_not_null)', 'total_estudos_sociais') + .field('SUM(adequacao_estudos_sociais)', 'total_suitable_estudos_sociais') + + .field('SUM(sociologia_not_null)', 'total_sociologia') + .field('SUM(adequacao_sociologia)', 'total_suitable_sociologia') + + .field("'Brasil'", 'name') + .field('docente.ano_censo', 'year') + .from('docente') + .group('docente.ano_censo') + .order('docente.ano_censo') + .where('(docente.tipo_docente = 1 OR docente.tipo_docente = 5) AND \ + ((docente.tipo_turma_id >= 0 AND docente.tipo_turma_id <= 3 AND docente.tipo_turma_atendimento_id is NULL) \ + OR ((docente.tipo_turma_atendimento_id = 1 OR docente.tipo_turma_atendimento_id = 2) AND docente.tipo_turma_id is NULL)) AND \ + docente.etapas_mod_ensino_segmento_id <> 6 AND docente.etapas_mod_ensino_segmento_id <> 12'); + } + else if ('discipline' in req.filter) { + const disciplines = ['quimica', 'fisica', 'matematica', 'biologia', 'ciencias', 'lingua_portuguesa', 'lingua_inglesa', 'lingua_espanhola', 'lingua_francesa', 'lingua_outra', 'lingua_indigena', 'artes', 'educacao_fisica', 'historia', 'geografia', 'filosofia', 'ensino_religioso', 'estudos_sociais', 'sociologia'] + + let totalQuery = 'SUM(' + let totalSuitableQuery = 'SUM(' + + if (!(req.filter.discipline instanceof Array)) req.filter.discipline = [req.filter.discipline] + + req.filter.discipline.forEach(d => { + totalQuery += disciplines[d - 1] + '_not_null + ' + totalSuitableQuery += 'adequacao_' + disciplines[d - 1] + ' + ' + }) + totalQuery = totalQuery.slice(0, -2) + ')' + totalSuitableQuery = totalSuitableQuery.slice(0, -2) + ')' + + delete req.filter.discipline; + + req.sql.field(totalQuery, 'total') + .field(totalSuitableQuery, 'total_suitable') + .field("'Brasil'", 'name') + .field('docente.ano_censo', 'year') + .from('docente') + // .join('turma', null, 'docente.turma_id=turma.id AND docente.ano_censo=turma.ano_censo') + .group('docente.ano_censo') + .order('docente.ano_censo') + .where('(docente.tipo_docente = 1 OR docente.tipo_docente = 5) AND \ + ((docente.tipo_turma_id >= 0 AND docente.tipo_turma_id <= 3 AND docente.tipo_turma_atendimento_id is NULL) \ + OR ((docente.tipo_turma_atendimento_id = 1 OR docente.tipo_turma_atendimento_id = 2) AND docente.tipo_turma_id is NULL)) AND \ + docente.etapas_mod_ensino_segmento_id <> 6 AND docente.etapas_mod_ensino_segmento_id <> 12'); + } + else { + req.sql.field('SUM(n_disc)', 'total') + .field('SUM(n_disc_adequada)', 'total_suitable') + .field("'Brasil'", 'name') + .field('docente.ano_censo', 'year') + .from('docente') + // .join('turma', null, 'docente.turma_id=turma.id AND docente.ano_censo=turma.ano_censo') + .group('docente.ano_censo') + .order('docente.ano_censo') + .where('(docente.tipo_docente = 1 OR docente.tipo_docente = 5) AND \ + ((docente.tipo_turma_id >= 0 AND docente.tipo_turma_id <= 3 AND docente.tipo_turma_atendimento_id is NULL) \ + OR ((docente.tipo_turma_atendimento_id = 1 OR docente.tipo_turma_atendimento_id = 2) AND docente.tipo_turma_id is NULL)) AND \ + docente.etapas_mod_ensino_segmento_id <> 6 AND docente.etapas_mod_ensino_segmento_id <> 12'); + } + + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + let filters = Object.keys(req.filter) + + // if(filters.includes("state")) { + // const disciplinesDB = ['quimica', 'fisica', 'matematica', 'biologia', 'ciencias', 'lingua_portuguesa', 'lingua_inglesa', 'lingua_espanhola', + // 'lingua_francesa', 'lingua_outra', 'lingua_indigena', 'artes', 'educacao_fisica', 'historia', 'geografia', 'filosofia', 'ensino_religioso', + // 'estudos_sociais', 'sociologia'] + // const disciplinesAPI = ["QuÃmica", "FÃsica", "Matemática", "Biologia", "Ciências", "LÃngua Portuguesa", "LÃngua Estrangeira – Inglês", + // "LÃngua Estrangeira - Espanhol","LÃngua Estrangeira - Francês", "LÃngua Estrangeira - Outras", "LÃngua IndÃgena", "Arte", "Educação FÃsica", "História", + // "Geografia", "Filosofia", "Ensino religioso", "Estudos Sociais", "Sociologia"] + + // let jsonKeys = [] + // let results = [] + // req.result.forEach((r) => { + // jsonKeys = Object.keys(r) + + // let i + // let size = jsonKeys.length - 2 // Last two infos are "name" and "year" + // for(i = 0; i < size; i++) { + // let total_name = jsonKeys[i] + // let suitable_name = jsonKeys[i + 1] + + // // Calculates percentage + // let percentage = r[suitable_name] / r[total_name] + // percentage = percentage * 100 + // percentage = percentage.toFixed(1) // Rounds to 1 digit after comma, returns string + // percentage = percentage.replace(".", ",") + "%" + + // // Parses name + // total_name = total_name.replace("total_", "") + // let discipline_index = disciplinesDB.indexOf(total_name) + // let discipline_name = disciplinesAPI[discipline_index] + + // let obj = { + // total: percentage, + // name: r["name"], + // year: r["year"], + // discipline_id: discipline_index + 1, // Convert function starts at 1, not at 0 + // discipline_name: discipline_name + // } + // results.push(obj) + + // i++; // Ignore next, it's a suitable already used + // } + // }) + + // req.result = results; + // } + // else { + let disciplinesNotSuitable = []; + let disciplinesSuitable = []; + + req.result.forEach((r) => { + + let obj = { + sum_total: 0, + sum_suitable: 0 + } + + Object.keys(r).forEach(k => { + if (k !== 'total' && k !== 'total_suitable') + obj[k] = r[k]; + }) + + if (req.tmp_discipline){ + Object.keys(r).forEach(k => { + if (/^total_suitable_/.test(k)) // if k starts with total_suitable + obj.sum_suitable += parseInt(r[k]); + else if (/^total_(?!suitable)/.test(k)) + obj.sum_total += parseInt(r[k]); + }) + } else { + delete obj.sum_total; + delete obj.sum_suitable; + } + + let objNotSuitable = Object.assign({}, { + total: parseInt(r.total) - parseInt(r.total_suitable), + suitable: 0, + discipline_name: 'Formação não adequada', + }, obj) + + let objSuitable = Object.assign({}, { + total: parseInt(r.total_suitable), + suitable: 1, + discipline_name: 'Formação adequada', + }, obj) + + disciplinesNotSuitable.push(objNotSuitable) + disciplinesSuitable.push(objSuitable) + }) + + req.result = disciplinesNotSuitable.concat(disciplinesSuitable); + next(); +}, response('disciplines')); + +module.exports = disciplinesApp; + + diff --git a/src/libs/routes_v2/distributionFactor.js b/src/libs/routes_v2/distributionFactor.js new file mode 100644 index 00000000..8a7b0e28 --- /dev/null +++ b/src/libs/routes_v2/distributionFactor.js @@ -0,0 +1,210 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const distributionApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const multiQuery = require(`${libs}/middlewares/multiQuery`); + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +distributionApp.use(cache('15 day')); + +rqf.addField({ + name: 'dims', + field: true, + where: false +}).addField({ + name: 'filter', + field: false, + where: true +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'fatores_matricula' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'fatores_matricula' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'fatores_matricula' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'fatores_matricula' + } +}, 'filter').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'fatores_matricula' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'fatores_matricula' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'fatores_matricula' + } +}) + +// Return all cities +distributionApp.get('/', rqf.parse(), (req, res, next) => { + req.querySet = []; + req.queryIndex = {}; + + let relation = req.sql.clone(); + relation.from('relacao_fatores_matricula').field('*'); + req.queryIndex.relation = req.querySet.push(relation) - 1; + + req.sql.from('fatores_matricula') + .field('fatores_matricula.municipio_id', 'municipio_id') + .field('fatores_matricula."mais_CRE_0"') + .field('fatores_matricula."mais_CRE_1"') + .field('fatores_matricula."mais_CRE_2"') + .field('fatores_matricula."mais_CRE_3"') + .field('fatores_matricula."mais_PRE"') + .field('fatores_matricula."mais_EFAI"') + .field('fatores_matricula."mais_EFAF"') + .field('fatores_matricula."mais_EM"') + .field('fatores_matricula."mais_EJA"') + .field('fatores_matricula."menos_CRE_0"') + .field('fatores_matricula."menos_CRE_1"') + .field('fatores_matricula."menos_CRE_2"') + .field('fatores_matricula."menos_CRE_3"') + .field('fatores_matricula."menos_PRE"') + .field('fatores_matricula."menos_EFAI"') + .field('fatores_matricula."menos_EFAF"') + .field('fatores_matricula."menos_EM"') + .field('fatores_matricula."menos_EJA"') + .group('fatores_matricula.municipio_id') + .group('fatores_matricula."mais_CRE_0"') + .group('fatores_matricula."mais_CRE_1"') + .group('fatores_matricula."mais_CRE_2"') + .group('fatores_matricula."mais_CRE_3"') + .group('fatores_matricula."mais_PRE"') + .group('fatores_matricula."mais_EFAI"') + .group('fatores_matricula."mais_EFAF"') + .group('fatores_matricula."mais_EM"') + .group('fatores_matricula."mais_EJA"') + .group('fatores_matricula."menos_CRE_0"') + .group('fatores_matricula."menos_CRE_1"') + .group('fatores_matricula."menos_CRE_2"') + .group('fatores_matricula."menos_CRE_3"') + .group('fatores_matricula."menos_PRE"') + .group('fatores_matricula."menos_EFAI"') + .group('fatores_matricula."menos_EFAF"') + .group('fatores_matricula."menos_EM"') + .group('fatores_matricula."menos_EJA"'); + + if(typeof req.dims.state !== 'undefined' || typeof req.filter.state !== 'undefined') { + req.sql.where('fatores_matricula.nivel = \'UF\''); + } else { + req.sql.where('fatores_matricula.nivel = \'BR\''); + } + + next(); +}, rqf.build(), query, (req, res, next) => { + req.enrollmentFactor = req.result; + next(); +}, multiQuery, (req, res, next) => { + let relation = req.result[req.queryIndex.relation]; + let result = []; + let first = true; + req.enrollmentFactor.forEach((city) => { + // if(first) console.log(city); + let obj = { + level: city.nivel, + region_id: city.regiao_id, + region_name: city.region_name, + state_id: city.state_id, + state_name: city.state_name, + city_id: city.municipio_id, + city_name: city.city_name, + series: [] + }; + // if(first) console.log(obj); + first = false; + relation.forEach((serie) => { + obj.series.push({ + serie_id: serie.id, + distribution_factor_addition: city[serie.fator_adicao], + distribution_factor_reduction: city[serie.fator_reducao] + }); + }); + result.push(obj); + }); + req.result = result; + next(); +}, response('ditributionFactor')); + +module.exports = distributionApp; diff --git a/src/libs/routes_v2/downloads.js b/src/libs/routes_v2/downloads.js new file mode 100644 index 00000000..2ec83b9e --- /dev/null +++ b/src/libs/routes_v2/downloads.js @@ -0,0 +1,54 @@ +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'); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +downloadApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, next) => { + request.get(config.cdn.url + '/api/v1/file', (err, response, body) => { + let cdn = JSON.parse(body); + 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'}); + } else { + downloads.forEach((dl) => { + for(let i = 0; i < cdn.length; ++i) { + if(cdn[i].query == dl.query) { + dl.status = cdn[i].expired ? 'Expirado' : 'Enviado'; + dl.size = cdn[i].size; + dl.expired = cdn[i].expired; + dl.updatedAt = cdn[i].lastAccess; + dl.link = config.cdn.download + '/' + cdn[i]._id; + + dl.save((err) => { + if(err) log.error(err); + }); + return; + } + } + }); + } + res.json(downloads); + }); + }); +}); + +module.exports = downloadApp; diff --git a/src/libs/routes_v2/educationYears.js b/src/libs/routes_v2/educationYears.js new file mode 100644 index 00000000..0d103883 --- /dev/null +++ b/src/libs/routes_v2/educationYears.js @@ -0,0 +1,46 @@ +const express = require('express'); + +const educationYearsApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const response = require(`${libs}/middlewares/response`); + +const config = require(`${libs}/config`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +educationYearsApp.use(cache('15 day')); + +educationYearsApp.get('/', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 7; ++i) { + let edLvlShort = { + id: i, + name: id2str.educationLevelShort(i), + schoolYears: [] + }; + + for(let j = i*10; j <= (i*10 + 9); ++j) { + + let schoolYear = { + id: j, + name: id2str.schoolYear(j) + }; + + if(schoolYear.name !== id2str.schoolYear(99)) { + edLvlShort.schoolYears.push(schoolYear); + } + } + if(edLvlShort.name !== id2str.schoolYear(99)) { + req.result.push(edLvlShort); + } + } + next(); +}, response('educationYears')); + +module.exports = educationYearsApp; diff --git a/src/libs/routes_v2/educationalBudget.js b/src/libs/routes_v2/educationalBudget.js new file mode 100644 index 00000000..30f6afc1 --- /dev/null +++ b/src/libs/routes_v2/educationalBudget.js @@ -0,0 +1,325 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + + +const libs = `${process.cwd()}/libs`; + +const conn = require(`${libs}/db/monet`); + +const express = require('express'); + +const educationalBudget = express.Router(); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +let rqfId = new ReqQueryFields(); + +const db = require(`${libs}/db/query_exec`); + +const log = require(`${libs}/log`)(module); + +rqfId.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'federative_entity', + table: 'orcamento_educacional', + tableField: 'entidade_federativa', + resultField: 'entidade_federativa_id', + where: { + relation: '=', + type: 'integer', + field: 'entidade_federativa' + } +}); + +//Insert route in orcamento_educacional table +educationalBudget.post('/insert', (req, res, next) => { + let id = req.body.id || null; + let entidade_federativa = req.body.entidade_federativa || null; + let csv = req.body.csv || null; + + //csv example + //"RO|7777777|jiarana|8043|41768845|43141895|66081767|8216|24312922|158,2%" + + req.id = id; + req.entidade_federativa = entidade_federativa; + req.csv = csv.toString(); + req.date = new Date(); + + //split o csv para adicionar separadamente nas colunas + csv = csv.split("|"); + req.uf = csv[0]; + req.municipio_id = csv[1]; + req.nome = csv[2]; + req.matriculas = csv[3]; + req.receitas_vinculadas = csv[4]; + req.despesas_realizadas = csv[5]; + req.despesas_correntes = csv[6]; + req.valor_aluno = csv[7]; + req.completacao = csv[8]; + req.completacao_porcentagem = csv[9]; + + let sqlQueryParams = []; + + //remove id duplicate + let deleteQuery = squel.delete() + .from("orcamento_educacional") + .where('id = ' + req.id) + .toString() + + //Exec delete sql + log.debug(`Executing SQL query '${deleteQuery}' with params '${[sqlQueryParams]}'`); + return new Promise((resolve, reject) => { + // Prepare statement + conn.prepare(deleteQuery, true).then((dbQuery) => { + // Execute query + dbQuery.exec(sqlQueryParams).then((dbResult) => { + // release resources allocated for the prepared statement + dbQuery.release(); + resolve(dbResult.data); + req.result = "Insertion Success" + next(); + }).catch((queryError) => { + log.error(`SQL query execution error: ${queryError.message}`); + req.result = "SQL query execution error:" + queryError.message; + log.error(`SQL query: ${deleteQuery} with params: ${sqlQueryParams}`); + // release resources allocated for the prepared statement + dbQuery.release(); + next(); + }); + }).catch((prepError) => { + log.error(`SQL prepared statement error: ${prepError.message}`); + req.result = "SQL query execution error:" + queryError.message; + log.error(`SQL query: ${deleteQuery} with params: ${sqlQueryParams}`); + next(); + }); + }); + +}, (req, res, next) => { + //build query + let insertQuery = squel.insert() + .into("orcamento_educacional") + .set("id", req.id) + .set("entidade_federativa", req.entidade_federativa) + .set("csv", req.csv) + .set("data", req.date.toString()) + .set("uf", req.uf) + .set("municipio_id", req.municipio_id) + .set("nome", req.nome) + .set("receitas_vinculadas", req.receitas_vinculadas) + .set("despesas_realizadas", req.despesas_realizadas) + .set("despesas_correntes", req.despesas_correntes) + .set("valor_aluno", req.valor_aluno) + .set("completacao", req.completacao) + .set("completacao_porcentagem", req.completacao_porcentagem) + .toString() + + let sqlQueryParams = []; + + //Exec insert sql + log.debug(`Executing SQL query '${insertQuery}' with params '${[sqlQueryParams]}'`); + return new Promise((resolve, reject) => { + // Prepare statement + conn.prepare(insertQuery, true).then((dbQuery) => { + // Execute query + dbQuery.exec(sqlQueryParams).then((dbResult) => { + // release resources allocated for the prepared statement + dbQuery.release(); + resolve(dbResult.data); + req.result = "Insertion Success" + next(); + }).catch((queryError) => { + log.error(`SQL query execution error: ${queryError.message}`); + req.result = "SQL query execution error:" + queryError.message; + log.error(`SQL query: ${insertQuery} with params: ${sqlQueryParams}`); + // release resources allocated for the prepared statement + dbQuery.release(); + next(); + }); + }).catch((prepError) => { + log.error(`SQL prepared statement error: ${prepError.message}`); + req.result = "SQL query execution error:" + queryError.message; + log.error(`SQL query: ${insertQuery} with params: ${sqlQueryParams}`); + next(); + }); + }); + + next(); +}, response('educationalBudget')); + +//Delete orcamento_educacional table +educationalBudget.get('/delete', (req, res, next) => { + + //build query + let insertQuery = squel.delete() + .from("orcamento_educacional") + .toString() + + let sqlQueryParams = []; + + //Exec sql in monet + log.debug(`Executing SQL query '${insertQuery}' with params '${[sqlQueryParams]}'`); + return new Promise((resolve, reject) => { + // Prepare statement + conn.prepare(insertQuery, true).then((dbQuery) => { + // Execute query + dbQuery.exec(sqlQueryParams).then((dbResult) => { + // release resources allocated for the prepared statement + dbQuery.release(); + resolve(dbResult.data); + req.result = "Delete Table Success" + next(); + }).catch((queryError) => { + log.error(`SQL query execution error: ${queryError.message}`); + req.result = "SQL query execution error:" + queryError.message; + log.error(`SQL query: ${insertQuery} with params: ${sqlQueryParams}`); + // release resources allocated for the prepared statement + dbQuery.release(); + next(); + }); + }).catch((prepError) => { + log.error(`SQL prepared statement error: ${prepError.message}`); + req.result = "SQL query execution error:" + queryError.message; + log.error(`SQL query: ${insertQuery} with params: ${sqlQueryParams}`); + next(); + }); + }); + + next(); +}, response('educationalBudget')); + +//Return all id's in table +educationalBudget.get('/id', rqfId.parse(), rqfId.build(), (req, res, next) => { + req.sql.from('orcamento_educacional') + .field('orcamento_educacional.municipio_id') + next(); +}, query, response('educationalBudget')); + +//Return count id grouop by entidade_federativa +educationalBudget.get('/finish', rqf.parse(), (req, res, next) => { + req.sql.field('COUNT(*)', 'total') + .field('orcamento_educacional.entidade_federativa', 'entidade_federativa') + .from('orcamento_educacional') + .group('orcamento_educacional.entidade_federativa') + .order('orcamento_educacional.entidade_federativa') + next(); +}, query, response('educationalBudget')); + +//return all data +educationalBudget.get('/', rqf.parse(), (req, res, next) => { + req.sql.from('orcamento_educacional') + .field('orcamento_educacional.id') + .field('orcamento_educacional.entidade_federativa', 'entidade_federativa') + .field('orcamento_educacional.data', 'data_insercao') + .field('orcamento_educacional.uf', 'uf') + .field('orcamento_educacional.municipio_id', 'municipio_id') + .field('orcamento_educacional.nome', 'nome') + .field('orcamento_educacional.receitas_vinculadas', 'receitas_vinculadas') + .field('orcamento_educacional.despesas_realizadas', 'despesas_realizadas') + .field('orcamento_educacional.despesas_correntes', 'despesas_correntes') + .field('orcamento_educacional.valor_aluno', 'valor_aluno') + .field('orcamento_educacional.completacao', 'completacao') + .field('orcamento_educacional.completacao_porcentagem', 'completacao_porcentagem') + .field('orcamento_educacional.csv', 'csv') + next(); +}, query, response('educationalBudget')); + +//Insert route in orcamento_educacional table +educationalBudget.post('/insert_pqr', (req, res, next) => { + let id = JSON.parse(req.body.id) || null; + let pqr = JSON.parse(req.body.pqr) || null; + + req.id = id; + req.pqr = pqr; + req.date = new Date(); + + //build query + let insertQuery = squel.insert() + .into("orcamento_educacional_pqr") + .set("id", req.id.toString()) + .set("pqr", req.pqr.toString()) + .set("data", req.date.toString()) + .toString() + + let sqlQueryParams = []; + + //Exec sql + log.debug(`Executing SQL query '${insertQuery}' with params '${[sqlQueryParams]}'`); + return new Promise((resolve, reject) => { + // Prepare statement + conn.prepare(insertQuery, true).then((dbQuery) => { + // Execute query + dbQuery.exec(sqlQueryParams).then((dbResult) => { + // release resources allocated for the prepared statement + dbQuery.release(); + resolve(dbResult.data); + req.result = "Insertion Success" + next(); + }).catch((queryError) => { + log.error(`SQL query execution error: ${queryError.message}`); + req.result = "SQL query execution error:" + queryError.message; + log.error(`SQL query: ${insertQuery} with params: ${sqlQueryParams}`); + // release resources allocated for the prepared statement + dbQuery.release(); + next(); + }); + }).catch((prepError) => { + log.error(`SQL prepared statement error: ${prepError.message}`); + req.result = "SQL query execution error:" + queryError.message; + log.error(`SQL query: ${insertQuery} with params: ${sqlQueryParams}`); + next(); + }); + }); + + next(); +}, response('educationalBudget')); + +educationalBudget.get('/get_pqr', (req, res, next) => { + req.sql.from('orcamento_educacional_pqr') + .field('orcamento_educacional_pqr.id', 'id') + .field('orcamento_educacional_pqr.pqr', 'pqr') + .field('orcamento_educacional_pqr.data', 'data') + next(); +}, query, response('educationalBudget')); + +module.exports = educationalBudget; + diff --git a/src/libs/routes_v2/employees.js b/src/libs/routes_v2/employees.js new file mode 100644 index 00000000..1ef4e7fd --- /dev/null +++ b/src/libs/routes_v2/employees.js @@ -0,0 +1,656 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const employeesApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqfTeacher = new ReqQueryFields(); + +let rqfSchool = new ReqQueryFields(); + + +employeesApp.use(cache('15 day')); + +// Returns a tuple of start and ending years of the complete enrollments dataset. +employeesApp.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')); + +employeesApp.get('/years', (req, res, next) => { + req.sql.from('escola'). + field('DISTINCT escola.ano_censo', 'year'); + next(); +}, query, response('years')); + +employeesApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'docente\''); + next(); +}, query, response('source')); + +employeesApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +employeesApp.get('/diff_location', (req, res, next) => { + req.result = [ + {id: 0, name: "A escola não está em localidade diferenciada"}, + {id: 1, name: "Ãrea de assentamento"}, + {id: 2, name: "Terra indÃgena"}, + {id: 3, name: "Terra remanescente de quilombos"}, + ]; + next(); +}, response('diff_location')); + +employeesApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +employeesApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +employeesApp.get('/function', (req, res, next) => { + req.result = [ + {id: 0, name: "Administrativos"}, + {id: 1, name: "Serviços Gerais"}, + {id: 2, name: "Bibliotecário"}, + {id: 3, name: "Saúde"}, + {id: 4, name: "Coordenador"}, + {id: 5, name: "Fonoaudiólogo"}, + {id: 6, name: "Nutricionista"}, + {id: 7, name: "Psicólogo"}, + {id: 8, name: "Alimentação"}, + {id: 9, name: "Pedagogia"}, + {id: 10, name: "Secretário"}, + {id: 11, name: "Segurança"}, + {id: 12, name: "Monitores"}, + {id: 99, name: "Não Classificado"} + ]; + next(); +}, response('function')); + +rqfSchool.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'adm_dependency', + table: '@', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: '@', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: '@' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}, 'filter').addValueToField({ + name: 'school', + table: '@', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, +}, 'dims').addValueToField({ + name: 'school', + table: '@', + tableField: 'escola_nome', + resultField: 'school_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, +}, 'filter').addValue({ + name: 'location', + table: '@', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'diff_location', + table: '@', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).addValue({ + name: 'rural_location', + table: '@', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'function', + table: '@', + tableField: 'a', + resultField: 'function_id', + where: { + relation: '=', + type: 'integer', + field: 'a' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}); + +rqfTeacher.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'adm_dependency', + table: '@', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: '@', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: '@' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}, 'filter').addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id','ano_censo'], + foreign: ['escola_id','ano_censo'], + foreignTable: '@' + } +}, 'dims').addValueToField({ + 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: '@' + } +}, 'filter').addValue({ + name: 'location', + table: '@', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'diff_location', + table: '@', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).addValue({ + name: 'rural_location', + table: '@', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}); + + +function formatFunction(queryOriginal,reqDims) { + delete reqDims.size; + delete reqDims.function; + let dims = Object.keys(reqDims); //se for = 0, apenas lidamos com a dimensao function. Se for = 1, lidamos com function mais a dimensao q esta nesse array. + let name = { + qtde_admin: "Administrativos", + qtde_servicos_gerais: "Serviços Gerais", + qtde_bibliotecario: "Bibliotecário", + qtde_saude: "Saúde", + qtde_coordenador: "Coordenador", + qtde_fono: "Fonoaudiólogo", + qtde_nutricionista: "Nutricionista", + qtde_psicologo: "Psicólogo", + qtde_alimentacao: "Alimentação", + qtde_pedagogia: "Pedagogia", + qtde_secretario: "Secretário", + qtde_seguranca: "Segurança", + qtde_monitores: "Monitores", + qtde_null: "Não Classificado" + } + let resultObj = [] + //Nesse caso apenas precisamos acertar as dimensoes que o banco retorna, ou seja, criando um objeto para cada funcao de funcionario + if (dims.length == 0) { + queryOriginal.forEach((result) => { + Object.keys(result).forEach(function(key,index) { + if (key.includes("qtde")) { + let newObj = { + year: result["year"], + function_id: index, + function_name: name[key], + total: result[key] + } + resultObj.push(newObj); + } + }) + }) + } + //Nesse caso precisamos copiar o id e name da variavel que está na dimensão junto com funcionarios por função + else { + queryOriginal.forEach((result) => { + Object.keys(result).forEach(function(key,index) { + if (key.includes("qtde")) { + let newObj = { + year: result["year"], + function_id: index, + function_name: name[key], + total: result[key] + } + newObj[dims[0] + "_id"] = result[dims[0] + "_id"]; + newObj[dims[0] + "_name"] = result[dims[0] + "_name"]; + resultObj.push(newObj); + } + }) + }) + } + + return resultObj; + +} + +function matchQueries(queryTotal, queryPartial) { + let match = []; + queryTotal.forEach((result) => { + let newObj = {}; + let keys = Object.keys(result); + keys.forEach((key) => { + newObj[key] = result[key]; + }); + let index = keys.indexOf('total'); + if(index > -1) keys.splice(index, 1); + let objMatch = null; + + for(let i = 0; i < queryPartial.length; ++i) { + let partial = queryPartial[i]; + let foundMatch = true; + for(let j = 0; j < keys.length; ++j) { + let key = keys[j]; + if(partial[key] !== result[key]) { + foundMatch = false; + break; + } + } + if(foundMatch) { + objMatch = partial; + break; + } + } + + if(objMatch) { + newObj.total = result.total - objMatch.total; + if (newObj.total > 0) { + newObj.total_employees = result.total; + newObj.total_teachers = objMatch.total + match.push(newObj); + } + } + }); + + return match; +} + +employeesApp.get('/', rqfSchool.parse(), (req, res, next) => { + req.allTeacher = {} + req.schoolTable = {} + + if ("function" in req.dims) { + delete req.dims.function; + req.sql.field('SUM(funcionarios_por_escola.total)', 'qtde_null') + .field('funcionarios_por_escola.ano_censo', 'year') + .from('funcionarios_por_escola') + .group('funcionarios_por_escola.ano_censo') + .order('funcionarios_por_escola.ano_censo') + .where('funcionarios_por_escola.ano_censo <> 2009 or funcionarios_por_escola.estado_id <> 42') + } else { + delete req.dims.function; + req.sql.field('SUM(funcionarios_por_escola.total)', 'total') + .field('funcionarios_por_escola.ano_censo', 'year') + .from('funcionarios_por_escola') + .group('funcionarios_por_escola.ano_censo') + .order('funcionarios_por_escola.ano_censo') + .where('funcionarios_por_escola.ano_censo <> 2009 or funcionarios_por_escola.estado_id <> 42') + } + next(); + +}, rqfSchool.build(), query, rqfSchool.parse(), id2str.transform(), (req, res, next) => { + + req.allTeacher = req.result; + req.resetSql(); + if ("function" in req.dims) { + req.sql.field('SUM(CASE WHEN escola.qt_prof_admin = 88888 THEN 0 ELSE escola.qt_prof_admin END)', 'qtde_admin') + .field('SUM(CASE WHEN escola.qtde_prof_servicos_gerais = 88888 THEN 0 ELSE escola.qtde_prof_servicos_gerais END) AS qtde_servicos_gerais') + .field('SUM(CASE WHEN escola.qtde_prof_bibliotecario = 88888 THEN 0 ELSE escola.qtde_prof_bibliotecario END)', 'qtde_bibliotecario') + .field('SUM(CASE WHEN escola.qtde_prof_saude = 88888 THEN 0 ELSE escola.qtde_prof_saude END)','qtde_saude') + .field('SUM(CASE WHEN escola.qtde_prof_coordenador = 88888 THEN 0 ELSE escola.qtde_prof_coordenador END)','qtde_coordenador') + .field('SUM(CASE WHEN escola.qtde_prof_fono = 88888 THEN 0 ELSE escola.qtde_prof_fono END)','qtde_fono') + .field('SUM(CASE WHEN escola.qtde_prof_nutricionista = 88888 THEN 0 ELSE escola.qtde_prof_nutricionista END)', 'qtde_nutricionista') + .field('SUM(CASE WHEN escola.qtde_prof_psicologo = 88888 THEN 0 ELSE escola.qtde_prof_psicologo END)', 'qtde_psicologo') + .field('SUM(CASE WHEN escola.qtde_prof_alimentacao = 88888 THEN 0 ELSE escola.qtde_prof_alimentacao END)','qtde_alimentacao') + .field('SUM(CASE WHEN escola.qtde_prof_pedagogia = 88888 THEN 0 ELSE escola.qtde_prof_pedagogia END)', 'qtde_pedagogia') + .field('SUM(CASE WHEN escola.qtde_prof_secretario = 88888 THEN 0 ELSE escola.qtde_prof_secretario END)','qtde_secretario') + .field('SUM(CASE WHEN escola.qtde_prof_seguranca = 88888 THEN 0 ELSE escola.qtde_prof_seguranca END)','qtde_seguranca') + .field('SUM(CASE WHEN escola.qtde_prof_monitores = 88888 THEN 0 ELSE escola.qtde_prof_monitores END)', 'qtde_monitores') + .field("'Brasil'", 'name') + .field('escola.ano_censo', 'year') + .from('escola') + .group('escola.ano_censo') + .order('escola.ano_censo') + .where('(escola.situacao_funcionamento_pareada = 1) AND (escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1) AND (escola.dependencia_adm_id = 2 OR escola.dependencia_adm_id = 3 OR escola.dependencia_adm_id = 4) and ano_censo >= 2019'); + delete req.dims.function; + } else { + req.sql.field('SUM(CASE WHEN escola.qt_prof_admin = 88888 THEN 0 ELSE escola.qt_prof_admin END) + SUM(CASE WHEN escola.qtde_prof_servicos_gerais = 88888 THEN 0 ELSE escola.qtde_prof_servicos_gerais END) + SUM(CASE WHEN escola.qtde_prof_bibliotecario = 88888 THEN 0 ELSE escola.qtde_prof_bibliotecario END) + SUM(CASE WHEN escola.qtde_prof_saude = 88888 THEN 0 ELSE escola.qtde_prof_saude END) + SUM(CASE WHEN escola.qtde_prof_coordenador = 88888 THEN 0 ELSE escola.qtde_prof_coordenador END) + SUM(CASE WHEN escola.qtde_prof_fono = 88888 THEN 0 ELSE escola.qtde_prof_fono END) + SUM(CASE WHEN escola.qtde_prof_nutricionista = 88888 THEN 0 ELSE escola.qtde_prof_nutricionista END) + SUM(CASE WHEN escola.qtde_prof_psicologo = 88888 THEN 0 ELSE escola.qtde_prof_psicologo END) + SUM(CASE WHEN escola.qtde_prof_alimentacao = 88888 THEN 0 ELSE escola.qtde_prof_alimentacao END) + SUM(CASE WHEN escola.qtde_prof_pedagogia = 88888 THEN 0 ELSE escola.qtde_prof_pedagogia END) + SUM(CASE WHEN escola.qtde_prof_secretario = 88888 THEN 0 ELSE escola.qtde_prof_secretario END) + SUM(CASE WHEN escola.qtde_prof_seguranca = 88888 THEN 0 ELSE escola.qtde_prof_seguranca END) + SUM(CASE WHEN escola.qtde_prof_monitores = 88888 THEN 0 ELSE escola.qtde_prof_monitores END)', 'total') + .field("'Brasil'", 'name') + .field('escola.ano_censo', 'year') + .from('escola') + .group('escola.ano_censo') + .order('escola.ano_censo') + .where('(escola.situacao_funcionamento_pareada = 1) AND (escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1) AND (escola.dependencia_adm_id = 2 OR escola.dependencia_adm_id = 3 OR escola.dependencia_adm_id = 4) and ano_censo >= 2019'); + } + next(); + +}, rqfSchool.build(), query, rqfSchool.parse(), id2str.transform(), addMissing(rqfSchool), (req, res, next) => { + + if ("function" in req.dims) { + let aux_employes = formatFunction(req.result, req.dims); + req.allTeacher = formatFunction(req.allTeacher, req.dims); + req.schoolTable = aux_employes; + } else { + req.schoolTable = req.result + } + + if (req.filter.min_year <= 2018 && req.filter.max_year <= 2018) { + let aux_employees = req.allTeacher; + req.result = aux_employees; + } else if (req.filter.min_year >= 2019 && req.filter.max_year >= 2019) { + req.result = req.schoolTable; + } else if (req.filter.min_year <= 2018 && req.filter.max_year >= 2019) { + let aux_employees = req.allTeacher; + req.result = aux_employees.concat(req.schoolTable); + } + next(); +}, response('employees')); + +module.exports = employeesApp; diff --git a/src/libs/routes_v2/enrollment.js b/src/libs/routes_v2/enrollment.js new file mode 100644 index 00000000..87259385 --- /dev/null +++ b/src/libs/routes_v2/enrollment.js @@ -0,0 +1,1204 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); +const { result } = require('lodash'); + +const enrollmentApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +enrollmentApp.use(cache('15 day')); + +let rqf = new ReqQueryFields(); + +// Complete range of the enrollments dataset. +// Returns a tuple of start and ending years of the complete enrollments dataset. +enrollmentApp.get('/year_range', (req, res, next) => { + req.sql.from('matricula') + .field('MIN(matricula.ano_censo)', 'start_year') + .field('MAX(matricula.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +enrollmentApp.get('/years', (req, res, next) => { + req.sql.from('matricula') + .field('DISTINCT matricula.ano_censo', 'year'); + next(); +}, query, response('years')); + +enrollmentApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'matricula\''); + next(); +}, query, response('source')); + +enrollmentApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +enrollmentApp.get('/diff_location', (req, res, next) => { + req.result = [ + {id: 0, name: "A escola não está em localidade diferenciada"}, + {id: 1, name: "Ãrea de assentamento"}, + {id: 2, name: "Terra indÃgena"}, + {id: 3, name: "Terra remanescente de quilombos"}, + ]; + next(); +}, response('diff_location')); + +// Returns all school years available +enrollmentApp.get('/school_year', (req, res, next) => { + req.result = []; + for(let i = 11; i <= 71; ++i) { + let obj = { + id: i, + name: id2str.schoolYear(i) + }; + + if(obj.name !== id2str.schoolYear(99)) { + req.result.push(obj); + } + } + req.result.push({ + id: 99, + name: id2str.schoolYear(99) + }); + next(); +}, response('school_year')); + +// Returns all school years available +enrollmentApp.get('/education_level', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 74; ++i) { + let obj = { + id: i, + name: id2str.educationLevel(i) + }; + + if(obj.name !== id2str.educationLevel(99)) { + req.result.push(obj); + } + } + req.result.push({ + id: 99, + name: id2str.educationLevel(99) + }); + next(); +}, response('education_level')); + +// Returns all school years available +enrollmentApp.get('/education_level_mod', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 12; ++i) { + if (i == 3 || i == 6) + continue; + + req.result.push({ + id: i, + name: id2str.educationLevelMod(i) + }); + } + req.result.push({ + id: 99, + name: id2str.educationLevelMod(99) + }); + next(); +}, response('education_level_mod')); + +enrollmentApp.get('/education_level_short', (req, res, next) => { + req.result = [ + {id: null, name: 'Não classificada'}, + {id: 1, name: 'Creche'}, + {id: 2, name: 'Pré-Escola'}, + {id: 3, name: 'Ensino Fundamental - anos iniciais'}, + {id: 4, name: 'Ensino Fundamental - anos finais'}, + {id: 5, name: 'Ensino Médio'}, + {id: 6, name: 'EJA'}, + {id: 7, name: 'EE exclusiva'} + ]; + next(); +}, response('education_level_short')); + +// Returns all adm dependencies +enrollmentApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +enrollmentApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 8; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +// Return genders +enrollmentApp.get('/gender', (req, res, next) => { + req.result = [ + {id: 1, name: 'Masculino'}, + {id: 2, name: 'Feminino'} + ]; + next(); +}, response('gender')); + +// Return ethnic group +enrollmentApp.get('/ethnic_group', (req, res, next) => { + req.result = []; + for(let i = 0; i <=5; ++i) { + req.result.push({ + id: i, + name: id2str.ethnicGroup(i) + }); + } + next(); +}, response('ethnic_group')); + +enrollmentApp.get('/period', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.period(i) + }); + } + req.result.push({ + id: 99, + name: id2str.period(99) + }); + next(); +}, response('period')); + +// Returns integral-time avaible +enrollmentApp.get('/integral_time', (req, res, next) => { + req.result = []; + for(let i = 0; i <= 2; ++i) { + req.result.push({ + id: i, + name: id2str.integralTime(i) + }); + } + next(); +}, response('integral_time')); + +enrollmentApp.get('/special_class', (req, res, next) => { + req.result = [ + {id: null, name: 'Não Declarado'}, + {id: 0, name: 'Não'}, + {id: 1, name: 'Sim'} + ]; + next(); +}, response('special_class')); + +enrollmentApp.get('/pee', (req, res, next) => { + req.result = [ + {id: true, name: id2str.booleanVariable(true)}, + {id: false, name: id2str.booleanVariable(false)} + ]; + next(); +}, response('pee')) + +enrollmentApp.get('/pee_por_categoria', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 14; ++i) { + req.result.push({ + id: i, + name: id2str.peePorCategoria(i) + }); + } + next(); +}, response('pee_por_categoria')); + +enrollmentApp.get('/age_range_all', (req, res, next) => { + req.result = [ + {id: 1, name: '0 a 3 anos'}, + {id: 2, name: '4 a 5 anos'}, + {id: 3, name: '6 a 10 anos'}, + {id: 4, name: '11 a 14 anos'}, + {id: 5, name: '15 a 17 anos'}, + {id: 6, name: '18 a 24 anos'}, + {id: 7, name: '25 a 29 anos'}, + {id: 8, name: '30 a 40 anos'}, + {id: 9, name: '41 a 50 anos'}, + {id: 10, name: '51 a 64 anos'}, + {id: 11, name: 'Mais que 64 anos'} + ]; + next(); +}, response('age_range_all')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'adm_dependency', + table: 'matricula', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'matricula', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'school_year', + table: 'matricula', + tableField: 'serie_ano_id', + resultField: 'school_year_id', + where: { + relation: '=', + type: 'integer', + field: 'serie_ano_id' + } +}).addValue({ + name: 'education_level', + table: 'matricula', + tableField: 'etapa_ensino_id', + resultField: 'education_level_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_ensino_id' + } +}).addValue({ + name: 'education_level_mod', + table: 'matricula', + tableField: 'etapas_mod_ensino_segmento_id', + resultField: 'education_level_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'etapas_mod_ensino_segmento_id' + } +}).addValue({ + name: 'education_level_short', + table: 'matricula', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'matricula' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'matricula' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'matricula' + } +}).addValueToField({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'matricula' + } +}, 'dims').addValueToField({ + name: 'state', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'matricula' + } +}, 'filter').addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'matricula' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'matricula' + } +}, 'filter').addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'matricula' + } +}, 'dims').addValueToField({ + name: 'locale_id', + table: 'matricula', + tableField: 'localizacao_id', + resultField: 'locale_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}, 'dims').addValueToField({ + name: 'school_id', + table: 'escola', + tableField: 'id', + resultField: 'school_id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'matricula' + } +}, 'dims').addValueToField({ + 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: 'matricula' + } +}, 'filter').addValue({ + name: 'location', + table: 'matricula', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'diff_location', + table: 'matricula', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).addValue({ + name: 'rural_location', + table: 'matricula', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'min_year', + table: 'matricula', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'matricula', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'gender', + table: 'matricula', + tableField: 'sexo', + resultField: 'gender_id', + where: { + relation: '=', + type: 'integer', + field: 'sexo' + } +}).addValue({ + name: 'ethnic_group', + table: 'matricula', + tableField: 'cor_raca_id', + resultField: 'ethnic_group_id', + where: { + relation: '=', + type: 'integer', + field: 'cor_raca_id' + } +}).addValue({ + name: 'period', + table: 'matricula', + tableField: 'turma_turno_id', + resultField: 'period_id', + where: { + relation: '=', + type: 'integer', + field: 'turma_turno_id' + } +}).addValue({ + name:'integral_time', + table: 'matricula', + tableField: 'tempo_integral', + resultField: 'integral_time_id', + where: { + relation: '=', + type: 'integer', + field: 'tempo_integral' + } +}).addValue({ + name:'age_range_all', + table: 'matricula', + tableField: 'faixa_etaria_31_03', + resultField: 'age_range_all_id', + where: { + relation: '=', + type: 'integer', + field: 'faixa_etaria_31_03' + } +}).addValue({ + name:'special_class', + table: 'matricula', + tableField: 'exclusiva_especial', + resultField: 'special_class_id', + where: { + relation: '=', + type: 'boolean', + field: 'exclusiva_especial' + } +}).addValueToField({ + name: 'period_not', + table: 'matricula', + tableField: 'turma_turno_id', + resultField: 'period_id', + where: { + relation: '<>', + type: 'integer', + field: 'turma_turno_id' + } +}, 'filter') +.addValue({ + name: 'low_vision', + table: 'matricula', + tableField: 'baixa_visao', + resultField: 'low_vision', + where: { + relation: '=', + type: 'boolean', + field: 'baixa_visao' + } +}).addValue({ + name: 'blindness', + table: 'matricula', + tableField: 'cegueira', + resultField: 'blindness', + where: { + relation: '=', + type: 'boolean', + field: 'cegueira' + } +}).addValue({ + name: 'deafness', + table: 'matricula', + tableField: 'surdez', + resultField: 'deafness', + where: { + relation: '=', + type: 'boolean', + field: 'surdez' + } +}).addValue({ + name: 'hearing_deficiency', + table: 'matricula', + tableField: 'deficiencia_auditiva', + resultField: 'hearing_deficiency', + where: { + relation: '=', + type: 'boolean', + field: 'deficiencia_auditiva' + } +}).addValue({ + name: 'deafblindness', + table: 'matricula', + tableField: 'surdo_cegueira', + resultField: 'deafblindness', + where: { + relation: '=', + type: 'boolean', + field: 'surdo_cegueira' + } +}).addValue({ + name: 'physical_disability', + table: 'matricula', + tableField: 'deficiencia_fisica', + resultField: 'physical_disability', + where: { + relation: '=', + type: 'boolean', + field: 'deficiencia_fisica' + } +}).addValue({ + name: 'intellectual_disability', + table: 'matricula', + tableField: 'deficiencia_intelectual', + resultField: 'intellectual_disability', + where: { + relation: '=', + type: 'boolean', + field: 'deficiencia_intelectual' + } +}).addValue({ + name: 'multiple_disabilities', + table: 'matricula', + tableField: 'deficiencia_multiplas', + resultField: 'multiple_disabilities', + where: { + relation: '=', + type: 'boolean', + field: 'deficiencia_multiplas' + } +}).addValue({ + name: 'autism', + table: 'matricula', + tableField: 'autismo', + resultField: 'autism', + where: { + relation: '=', + type: 'boolean', + field: 'autismo' + } +}).addValue({ + name: 'autism_spectrum_disorder', + table: 'matricula', + tableField: 'transtorno_espectro_autista', + resultField: 'autism_spectrum_disorder', + where: { + relation: '=', + type: 'boolean', + field: 'transtorno_espectro_autista' + } +}).addValue({ + name: 'asperger_syndrom', + table: 'matricula', + tableField: 'sindrome_asperger', + resultField: 'asperger_syndrom', + where: { + relation: '=', + type: 'boolean', + field: 'sindrome_asperger' + } +}).addValue({ + name: 'rett_syndrom', + table: 'matricula', + tableField: 'sindrome_rett', + resultField: 'rett_syndrom', + where: { + relation: '=', + type: 'boolean', + field: 'sindrome_rett' + } +}).addValue({ + name: 'childhood_desintegrative_disorder', + table: 'matricula', + tableField: 'transtorno_desintegrativo_da_infancia', + resultField: 'childhood_desintegrative_disorder', + where: { + relation: '=', + type: 'boolean', + field: 'transtorno_desintegrativo_da_infancia' + } +}).addValue({ + name: 'supergifted', + table: 'matricula', + tableField: 'superdotado', + resultField: 'supergifted', + where: { + relation: '=', + type: 'boolean', + field: 'superdotado' + } +}).addValue({ + name: 'pee', + table: 'matricula', + tableField: 'possui_necessidade_especial', + resultField: 'pee_id', + where: { + relation: '=', + type: 'boolean', + field: 'possui_necessidade_especial' + } +}).addValue({ + name: 'pee_por_categoria', + table: 'matricula', + tableField: 'possui_necessidade_especial', + resultField: 'pee_por_categoria', + where: { + relation: '=', + type: 'boolean', + field: 'possui_necessidade_especial' + } +}); + +enrollmentApp.get('/', rqf.parse(), (req, res, next) => { + if('pee_por_categoria' in req.dims){ + delete req.dims.pee_por_categoria + req.pee_por_categoria = true + req.sql.field('SUM(CASE WHEN cegueira = true THEN 1 ELSE 0 END)', 'Cegueira') + .field('SUM(CASE WHEN baixa_visao = true THEN 1 ELSE 0 END)', 'Baixa visão') + .field('SUM(CASE WHEN surdez = true THEN 1 ELSE 0 END)', 'Surdez') + .field('SUM(CASE WHEN deficiencia_auditiva = true THEN 1 ELSE 0 END)', 'Deficiência auditiva') + .field('SUM(CASE WHEN surdo_cegueira = true THEN 1 ELSE 0 END)', 'Surdocegueira') + .field('SUM(CASE WHEN deficiencia_fisica = true THEN 1 ELSE 0 END)', 'Deficiência fÃsica') + .field('SUM(CASE WHEN deficiencia_intelectual = true THEN 1 ELSE 0 END)', 'Deficiência intelectual') + .field('SUM(CASE WHEN deficiencia_multiplas = true THEN 1 ELSE 0 END)', 'Deficiências múltiplas') + .field('SUM(CASE WHEN autismo = true THEN 1 ELSE 0 END)', 'Autismo') + .field('SUM(CASE WHEN transtorno_espectro_autista = true THEN 1 ELSE 0 END)', 'Transtorno do Espectro Autista (TEA)') + .field('SUM(CASE WHEN sindrome_asperger = true THEN 1 ELSE 0 END)', 'SÃndrome de Asperger') + .field('SUM(CASE WHEN sindrome_rett = true THEN 1 ELSE 0 END)', 'SÃndrome de Rett') + .field('SUM(CASE WHEN transtorno_desintegrativo_da_infancia = true THEN 1 ELSE 0 END)', 'Transtorno desintegrativo da infância') + .field('SUM(CASE WHEN superdotado = true THEN 1 ELSE 0 END)', 'Altas habilidades / Superdotação') + .field('matricula.ano_censo', 'year') + .from('matricula') + .group('matricula.ano_censo') + .order('matricula.ano_censo') + .where('((matricula.tipo<=3 OR matricula.tipo IS NULL) AND (matricula.tipo_atendimento_turma IS NULL OR matricula.tipo_atendimento_turma <= 2))'); + } + else{ + req.sql.field('COUNT(*)', 'total') + .field('matricula.ano_censo', 'year') + .from('matricula') + .group('matricula.ano_censo') + .order('matricula.ano_censo') + .where('((matricula.tipo<=3 OR matricula.tipo IS NULL) AND (matricula.tipo_atendimento_turma IS NULL OR matricula.tipo_atendimento_turma <= 2))'); + } + next(); +}, rqf.build(), query, id2str.transform(false), (req, res, next) => { + if(req.pee_por_categoria === true){ + let result = req.result; + let result_total = []; + for (var j = 0;j < result.length;j++){ + let result_parcial = result[j]; + for (var i in result_parcial){ + if(i !== 'year'){ + let obj = {}; + obj.total = result_parcial[i]; + i = i.replace(/"/g, ''); + obj.pee_por_categoria_name = i; + obj.year = result_parcial.year; + result_total.push(obj); + } + } + } + req.result= result_total; + } + next(); +}, response('enrollment')); + +enrollmentApp.get('/diagnosis', rqf.parse(), (req, res, next) => { + req.dims = {}; + req.dims.state = true; + req.dims.city = true; + req.dims.school_year = true; + req.dims.location = true; + req.dims.adm_dependency_detailed = true; + + req.sql.field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('matricula.ano_censo', 'year') + .from('matricula') + .group('matricula.ano_censo') + .order('matricula.ano_censo') + .where('matricula.tipo<=3'); + + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + let enrollments = req.result; + + // Gera a relação etapa de ensino X ano escolar + let educationSchoolYear = {}; + for(let i = 10; i < 80; ++i) { + if(id2str.schoolYear(i) !== id2str.schoolYear(99)) { + let educationLevelId = Math.floor(i/10); + educationSchoolYear[i] = { + id: educationLevelId, + name: id2str.educationLevelShort(educationLevelId), + }; + } + } + + let result = []; + let educationLevelSet = new Set(); + let schoolYearSet = new Set(); + let i = 0; + while(i < enrollments.length) { + let enrollment = enrollments[i]; + if(!educationSchoolYear[enrollment.school_year_id]) { + ++i; + continue; + } + let educationLevelHash = '' + enrollment.year + educationSchoolYear[enrollment.school_year_id].id + enrollment.city_id; + let schoolYearHash = '' + enrollment.year + enrollment.school_year_id + enrollment.city_id; + + let currentEducation = null; + // Busca ou cria a etapa de ensino adequada + if(educationLevelSet.has(educationLevelHash)) { + let j = 0; + let edu = result[j]; + while(j < result.length && (edu.year != enrollment.year || edu.education_level_school_year_id != educationSchoolYear[enrollment.school_year_id].id)) { + ++j; + edu = result[j]; + } + if(j >= result.length) --j; + edu = result[j]; + + currentEducation = edu; + } else { + educationLevelSet.add(educationLevelHash); + let obj = { + year: enrollment.year, + name: enrollment.name, + state_id: enrollment.state_id, + state_name: enrollment.state_name, + city_id: enrollment.city_id, + city_name: enrollment.city_name, + education_level_school_year_id: educationSchoolYear[enrollment.school_year_id].id, + education_level_school_year_name: educationSchoolYear[enrollment.school_year_id].name, + total: 0, + adm_dependencies: [ + { + adm_dependency_detailed_id: enrollment.adm_dependency_detailed_id, + adm_dependency_detailed_name: enrollment.adm_dependency_detailed_name, + total: 0 + } + ], + locations: [ + { + location_id: enrollment.location_id, + location_name: enrollment.location_name, + total: 0 + } + ] + }; + + result.push(obj); + currentEducation = obj; + } + + let currentSchoolYear = null; + // Busca ou cria a série adequada + if(schoolYearSet.has(schoolYearHash)) { + let j = 0; + let edu = result[j]; + while(j < result.length && (edu.year != enrollment.year || edu.education_level_school_year_id != enrollment.school_year_id)) { + ++j; + edu = result[j]; + } + if(j >= result.length) --j; + edu = result[j]; + + currentSchoolYear = edu; + } else { + schoolYearSet.add(schoolYearHash); + let obj = { + year: enrollment.year, + name: enrollment.name, + state_id: enrollment.state_id, + state_name: enrollment.state_name, + city_id: enrollment.city_id, + city_name: enrollment.city_name, + education_level_school_year_id: enrollment.school_year_id, + education_level_school_year_name: enrollment.school_year_name, + total: 0, + adm_dependencies: [ + { + adm_dependency_detailed_id: enrollment.adm_dependency_detailed_id, + adm_dependency_detailed_name: enrollment.adm_dependency_detailed_name, + total: 0 + } + ], + locations: [ + { + location_id: enrollment.location_id, + location_name: enrollment.location_name, + total: 0 + } + ] + }; + + result.push(obj); + currentSchoolYear = obj; + } + + // Adiciona ao total + currentEducation.total += enrollment.total; + currentSchoolYear.total += enrollment.total; + + // Adiciona ao total da dependência administrativa + let admDependencyIndex = 0; + let admDependency = currentEducation.adm_dependencies[admDependencyIndex]; + while (admDependencyIndex < currentEducation.adm_dependencies.length && enrollment.adm_dependency_detailed_id > admDependency.adm_dependency_detailed_id) { + ++admDependencyIndex; + admDependency = currentEducation.adm_dependencies[admDependencyIndex]; + } + if(admDependencyIndex >= currentEducation.adm_dependencies.length || admDependency.adm_dependency_detailed_id != enrollment.adm_dependency_detailed_id) { // não encontrou + let obj = { + adm_dependency_detailed_id: enrollment.adm_dependency_detailed_id, + adm_dependency_detailed_name: enrollment.adm_dependency_detailed_name, + total: 0 + } + currentEducation.adm_dependencies.splice(admDependencyIndex, 0, obj); + admDependency = obj; + } + admDependency.total += enrollment.total; + + admDependencyIndex = 0; + admDependency = currentSchoolYear.adm_dependencies[admDependencyIndex]; + while (admDependencyIndex < currentSchoolYear.adm_dependencies.length && enrollment.adm_dependency_detailed_id > admDependency.adm_dependency_detailed_id) { + ++admDependencyIndex; + admDependency = currentSchoolYear.adm_dependencies[admDependencyIndex]; + } + if(admDependencyIndex >= currentSchoolYear.adm_dependencies.length || admDependency.adm_dependency_detailed_id != enrollment.adm_dependency_detailed_id) { // não encontrou + let obj = { + adm_dependency_detailed_id: enrollment.adm_dependency_detailed_id, + adm_dependency_detailed_name: enrollment.adm_dependency_detailed_name, + total: 0 + } + currentSchoolYear.adm_dependencies.splice(admDependencyIndex, 0, obj); + admDependency = obj; + } + admDependency.total += enrollment.total; + + // Adiciona ao total da localidade + let locationIndex = 0; + let location = currentEducation.locations[locationIndex]; + while (locationIndex < currentEducation.locations.length && enrollment.location_id > location.location_id) { + ++locationIndex; + location = currentEducation.locations[locationIndex]; + } + if(locationIndex >= currentEducation.locations.length || location.location_id != enrollment.location_id) { + let obj = { + location_id: enrollment.location_id, + location_name: enrollment.location_name, + total: 0 + } + currentEducation.locations.splice(locationIndex, 0, obj); + location = obj; + } + location.total += enrollment.total; + + locationIndex = 0; + location = currentSchoolYear.locations[locationIndex]; + while (locationIndex < currentSchoolYear.locations.length && enrollment.location_id > location.location_id) { + ++locationIndex; + location = currentSchoolYear.locations[locationIndex]; + } + if(locationIndex >= currentSchoolYear.locations.length || location.location_id != enrollment.location_id) { + let obj = { + location_id: enrollment.location_id, + location_name: enrollment.location_name, + total: 0 + } + currentSchoolYear.locations.splice(locationIndex, 0, obj); + location = obj; + } + location.total += enrollment.total; + + ++i; + } + + req.result = result; + + next(); +}, response('enrollment_diagnosis')); + +enrollmentApp.get('/projection', rqf.parse(), (req, res, next) => { + req.dims = {}; + req.dims.state = true; + req.dims.city = true; + req.dims.location = true; + req.dims.school_year = true; + req.dims.adm_dependency = true; + req.dims.period = true; + req.filter.adm_dependency = [1,2,3]; + + req.sql.field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('matricula.ano_censo', 'year') + .from('matricula') + .group('matricula.ano_censo') + .order('matricula.ano_censo') + .where('matricula.tipo<=3'); + + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + let enrollments = req.result; + + // Gera a relação etapa de ensino X ano escolar + let educationSchoolYear = {}; + for(let i = 10; i < 80; ++i) { + if(id2str.schoolYear(i) !== id2str.schoolYear(99)) { + let educationLevelId = Math.floor(i/10); + educationSchoolYear[i] = { + id: educationLevelId, + name: id2str.educationLevelShort(educationLevelId), + }; + } + } + + let result = []; + let educationLevelSet = new Set(); + let schoolYearSet = new Set(); + let i = 0; + while(i < enrollments.length) { + let enrollment = enrollments[i]; + if(!educationSchoolYear[enrollment.school_year_id]) { + ++i; + continue; + } + let educationLevelHash = '' + enrollment.year + educationSchoolYear[enrollment.school_year_id].id + enrollment.city_id; + let schoolYearHash = '' + enrollment.year + enrollment.school_year_id + enrollment.city_id; + + let currentEducation = null; + // Busca ou cria a etapa de ensino adequada + if(educationLevelSet.has(educationLevelHash)) { + let j = 0; + let edu = result[j]; + while(j < result.length && (edu.year != enrollment.year || edu.education_level_school_year_id != educationSchoolYear[enrollment.school_year_id].id)) { + ++j; + edu = result[j]; + } + if((j >= result.length)) --j; + edu = result[j]; + + currentEducation = edu; + } else { + educationLevelSet.add(educationLevelHash); + let obj = { + year: enrollment.year, + name: enrollment.name, + state_id: enrollment.state_id, + state_name: enrollment.state_name, + city_id: enrollment.city_id, + city_name: enrollment.city_name, + education_level_school_year_id: educationSchoolYear[enrollment.school_year_id].id, + education_level_school_year_name: educationSchoolYear[enrollment.school_year_id].name, + urban_day_total: 0, + urban_night_total: 0, + rural_day_total: 0, + rural_night_total: 0 + }; + result.push(obj); + currentEducation = obj; + } + + let currentSchoolYear = null; + // Busca ou cria a série adequada + if(schoolYearSet.has(schoolYearHash)) { + let j = 0; + let edu = result[j]; + while(j < result.length && (edu.year != enrollment.year || edu.education_level_school_year_id != enrollment.school_year_id)){ + ++j; + edu = result[j]; + } + if(j >= result.length) --j; + edu = result[j]; + + currentSchoolYear = edu; + } else { + schoolYearSet.add(schoolYearHash); + let obj = { + year: enrollment.year, + name: enrollment.name, + state_id: enrollment.state_id, + state_name: enrollment.state_name, + city_id: enrollment.city_id, + city_name: enrollment.city_name, + education_level_school_year_id: enrollment.school_year_id, + education_level_school_year_name: enrollment.school_year_name, + urban_day_total: 0, + urban_night_total: 0, + rural_day_total: 0, + rural_night_total: 0 + }; + + result.push(obj); + currentSchoolYear = obj; + } + + if(enrollment.location_id == 1) { + if(enrollment.period_id < 3) { + currentEducation.urban_day_total += enrollment.total; + currentSchoolYear.urban_day_total += enrollment.total; + } else { + currentEducation.urban_night_total += enrollment.total; + currentSchoolYear.urban_night_total += enrollment.total; + } + } else { + if(enrollment.period_id < 3) { + currentEducation.rural_day_total += enrollment.total; + currentSchoolYear.rural_day_total += enrollment.total; + } else { + currentEducation.rural_night_total += enrollment.total; + currentSchoolYear.rural_night_total += enrollment.total; + } + } + + ++i; + } + + req.result = result; + + next(); +}, response('enrollment_projection')); + +module.exports = enrollmentApp; diff --git a/src/libs/routes_v2/enrollmentProjection.js b/src/libs/routes_v2/enrollmentProjection.js new file mode 100644 index 00000000..4dd92e5d --- /dev/null +++ b/src/libs/routes_v2/enrollmentProjection.js @@ -0,0 +1,239 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const enrollmentProjectionApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +let rqf = new ReqQueryFields(); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'projecao_matricula_por_dependencia' + } +}, 'dims').addValueToField({ + name: 'state', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'projecao_matricula_por_dependencia' + } +}, 'filter').addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'projecao_matricula_por_dependencia' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'projecao_matricula_por_dependencia' + } +}, 'filter').addValue({ + name: 'min_year', + table: 'projecao_matricula_por_dependencia', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'projecao_matricula_por_dependencia', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'adm_dependency', + table: 'projecao_matricula_por_dependencia', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}); + +enrollmentProjectionApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.field("'Brasil'", 'name') + .field('SUM(projecao_matricula_por_dependencia.urbano_dia_total)', 'urban_day_total') + .field('SUM(projecao_matricula_por_dependencia.urbano_noite_total)', 'urban_night_total') + .field('SUM(projecao_matricula_por_dependencia.rural_dia_total)', 'rural_day_total') + .field('SUM(projecao_matricula_por_dependencia.rural_noite_total)', 'rural_night_total') + .field('projecao_matricula_por_dependencia.etapa_ensino_escola_ano_id', 'education_level_school_year_id') + .field('projecao_matricula_por_dependencia.ano_censo', 'year') + .from('projecao_matricula_por_dependencia') + .where('projecao_matricula_por_dependencia.etapa_ensino_escola_ano_id <> 7 AND projecao_matricula_por_dependencia.etapa_ensino_escola_ano_id < 71') + .group('projecao_matricula_por_dependencia.etapa_ensino_escola_ano_id') + .group('projecao_matricula_por_dependencia.ano_censo') + .order('projecao_matricula_por_dependencia.ano_censo') + .order('projecao_matricula_por_dependencia.etapa_ensino_escola_ano_id'); + + next(); +}, query, id2str.transform(), (req, res, next) => { + + let result = []; + let i = 0; + let j = 1; + let base_year = req.result[0].year; + + let hashSet = new Set(); + let atual_city_name; + let atual_city_id; + let atual_state_name; + let atual_state_id; + while (i < req.result.length || j <= 63) { // Adciona séries não existentes no banco com 0 nos totais. + let atual = req.result[i]; + if (j > 63) { // Caso j passou da última série existente, mudamos de dimensão. + j = 1; + + if (base_year !== atual.year) { + base_year = atual.year; + hashSet = new Set(); + } + } + if (id2str.educationLevelSchoolYear(j) === id2str.educationLevelSchoolYear(99) || j === 7) { + j++; + continue; + } + + if (j == 1) { + let hash = "" + if ('state' in req.dims) + hash += atual.state_id; + if ('city' in req.dims) + hash += atual.city_id; + + if (!hashSet.has(hash)) { + hashSet.add(hash); + atual_city_id = atual.city_id; + atual_city_name = atual.city_name; + atual_state_id = atual.state_id; + atual_state_name = atual.state_name; + } + } + + if (atual !== undefined && atual.education_level_school_year_id === j) { // Série existe. + atual.urban_day_total = parseInt(atual.urban_day_total, 10); + atual.urban_night_total = ((atual.education_level_school_year_id >= 3 && atual.education_level_school_year_id < 10) || (atual.education_level_school_year_id >= 30)) ? parseInt(atual.urban_night_total, 10) : 0; //Não conta matrÃculas noturnas da pré-escola e da creche + atual.rural_day_total = parseInt(atual.rural_day_total, 10); + atual.rural_night_total = ((atual.education_level_school_year_id >= 3 && atual.education_level_school_year_id < 10) || (atual.education_level_school_year_id >= 30)) ? parseInt(atual.rural_night_total, 10) : 0; + result.push(atual); + + i++; + } + else { // Série não existe, adcionamos 0 ao resultado. + let base_result = { + name: req.result[0].name, + urban_day_total: 0, + urban_night_total: 0, + rural_day_total: 0, + rural_night_total: 0, + education_level_school_year_id: j, + year: base_year, + education_level_school_year_name: id2str.educationLevelSchoolYear(j) + }; + + if ('city' in req.dims) { // adciona os campos de cidade e/ou estado + base_result.city_id = atual_city_id; + base_result.city_name = atual_city_name; + } + if ('state' in req.dims) { + base_result.state_id = atual_state_id; + base_result.state_name = atual_state_name; + } + + result.push(base_result) + } + j++; + } + + req.result = result; + next(); +}, response('enrollment_projection')); + +module.exports = enrollmentProjectionApp; diff --git a/src/libs/routes_v2/financial.js b/src/libs/routes_v2/financial.js new file mode 100644 index 00000000..dab9dfe8 --- /dev/null +++ b/src/libs/routes_v2/financial.js @@ -0,0 +1,186 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const financialApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +financialApp.get('/year_range', (req, res, next) => { + req.sql.from('indicadores_financeiros') + .field('MIN(indicadores_financeiros.ano_censo)', 'start_year') + .field('MAX(indicadores_financeiros.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +financialApp.get('/years', (req, res, next) => { + req.sql.from('indicadores_financeiros') + .field('DISTINCT indicadores_financeiros.ano_censo', 'year'); + next(); +}, query, response('years')); + +financialApp.get('/sphere_adm', (req, res, next) => { + req.result = [ + {id: 1, name: "1"}, + {id: 2, name: "2"} + ] + next(); +}, response('sphere_adm')); + +financialApp.get('/financial_data', (req, res, next) => { + req.sql.from('indicadores_financeiros') + .field('DISTINCT indicadores_financeiros.dados_financeiros', 'financial_data'); + next(); +}, query, response('financial_data')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['sigla', 'id'], + resultField: ['sigla_uf', 'cod_uf'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'indicadores_financeiros' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'indicadores_financeiros' + } +}).addValue({ + name: 'min_year', + table: 'indicadores_financeiros', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'indicadores_financeiros', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'indicadores_financeiros', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'indicadores_financeiros', + field: 'ano_censo' + } +}).addValue({ + name: 'sphere_adm', + table: 'indicadores_financeiros', + tableField: 'esfera_adm', + resultField: 'sphere_adm_id', + where: { + relation: '=', + type: 'integer', + field: 'esfera_adm' + } +}).addValue({ + name: 'city', + table: 'indicadores_financeiros', + tableField: 'municipio_id', + resultField: 'city_id', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id' + } +}).addValue({ + name: 'financial_data', + table: 'indicadores_financeiros', + tableField: 'dados_financeiros', + resultField: 'financial_data_id', + where: { + relation: '=', + type: 'integer', + field: 'dados_financeiros' + } +}); + +financialApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + if ("state" in req.filter) { + req.sql.from('indicadores_financeiros') + .field('indicadores_financeiros.estado_id', 'state_id') + .field('indicadores_financeiros.ano_censo', 'year') + .field('estado.sigla', 'state_abbreviation') + .field('indicadores_financeiros.valor', 'valor') + .field('indicadores_financeiros.esfera_adm', 'sphere_adm_id') + .field('indicadores_financeiros.dados_financeiros', 'financial_data_id') + .group('indicadores_financeiros.ano_censo') + .group('indicadores_financeiros.estado_id') + .group('estado.sigla') + .group('indicadores_financeiros.valor') + .group('indicadores_financeiros.dados_financeiros') + .group('indicadores_financeiros.esfera_adm') + } else { + req.sql.from('indicadores_financeiros') + .field('indicadores_financeiros.estado_id', 'state_id') + .field('indicadores_financeiros.ano_censo', 'year') + .field('estado.sigla', 'state_abbreviation') + .field('indicadores_financeiros.valor', 'valor') + .field('indicadores_financeiros.esfera_adm', 'sphere_adm_id') + .field('indicadores_financeiros.dados_financeiros', 'financial_data_id') + .join('estado', null, 'indicadores_financeiros.estado_id=estado.id') + .group('indicadores_financeiros.ano_censo') + .group('indicadores_financeiros.estado_id') + .group('estado.sigla') + .group('indicadores_financeiros.valor') + .group('indicadores_financeiros.dados_financeiros') + .group('indicadores_financeiros.esfera_adm') + } + next(); +}, query, id2str.transform(), response('financial')); + +module.exports = financialApp; diff --git a/src/libs/routes_v2/glossEnrollmentRatio.js b/src/libs/routes_v2/glossEnrollmentRatio.js new file mode 100644 index 00000000..ab57e325 --- /dev/null +++ b/src/libs/routes_v2/glossEnrollmentRatio.js @@ -0,0 +1,390 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const glossEnrollmentRatioApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const multiQuery = require(`${libs}/middlewares/multiQuery`); + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +glossEnrollmentRatioApp.use(cache('15 day')); + +// Complete range of the enrollments dataset. +// Returns a tuple of start and ending years of the complete enrollments dataset. +glossEnrollmentRatioApp.get('/year_range', (req, res, next) => { + req.sql.from('pnad') + .field('DISTINCT pnad.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('matricula') + .field('DISTINCT matricula.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let distinct_years = []; + let new_result = []; + for (let i = 0; i < req.oldResult.length; i++) { + for (let j = 0; j < req.result.length; j++) { + if(req.oldResult[i].year == req.result[j].year) { + distinct_years.push(req.oldResult[i]); + } + } + } + new_result.push({start_year: distinct_years[distinct_years.length -1].year, end_year: distinct_years[0].year}); + req.result = new_result; + next(); +}, response('range')); + +glossEnrollmentRatioApp.get('/years', (req, res, next) => { + req.sql.from('pnad') + .field('DISTINCT pnad.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('matricula') + .field('DISTINCT matricula.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let new_result = [] + for (let i = 0; i < req.oldResult.length; i++) { + for (let j = 0; j < req.result.length; j++) { + if(req.oldResult[i].year == req.result[j].year) { + new_result.push(req.oldResult[i]); + } + } + } + req.result = new_result; + next(); +}, response('years')); + +glossEnrollmentRatioApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'pnad\''); + next(); +}, query, response('source')); + +glossEnrollmentRatioApp.get('/education_level_short', (req, res, next) => { + req.result = [ + {id: null, name: 'Não classificada'}, + {id: 1, name: 'Creche'}, + {id: 2, name: 'Pré-Escola'}, + {id: 3, name: 'Ensino Fundamental - anos iniciais'}, + {id: 4, name: 'Ensino Fundamental - anos finais'}, + {id: 5, name: 'Ensino Médio'} + ]; + next(); +}, response('education_level_short')); + +glossEnrollmentRatioApp.get('/gender', (req, res, next) => { + req.result = [ + {id: 1, name: 'Masculino'}, + {id: 2, name: 'Feminino'} + ]; + next(); +}, response('gender')); + +glossEnrollmentRatioApp.get('/ethnic_group', (req, res, next) => { + req.result = [ + {id: 0, name: 'Sem declaração'}, + {id: 1, name: 'Branca'}, + {id: 2, name: 'Preta'}, + {id: 3, name: 'Parda'}, + {id: 4, name: 'Amarela'}, + {id: 5, name: 'IndÃgena'} + ]; + next(); +}, response('ethnic_group')); + +glossEnrollmentRatioApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: '@' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}).addValue({ + name: 'ethnic_group', + table: '@', + tableField: 'cor_raca_id', + resultField: 'ethnic_group_id', + where: { + relation: '=', + type: 'integer', + field: 'cor_raca_id' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'gender', + table: '@', + tableField: 'sexo', + resultField: 'gender_id', + where: { + relation: '=', + type: 'integer', + field: 'sexo' + } +}).addValue({ + name: 'location', + table: '@', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'education_level_short', + table: 'matricula', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}); + +function matchQueries(queryTotal, queryPartial) { + let match = []; + queryPartial.forEach((result) => { + let newObj = {}; + let keys = Object.keys(result); + keys.forEach((key) => { + newObj[key] = result[key]; + }); + // console.log('NEW OBJ'); + // console.log(newObj); + // remove total + let index = keys.indexOf('total'); + if(index > -1) keys.splice(index, 1); + // remove education_level_short_id + index = keys.indexOf('education_level_short_id'); + if(index > -1) keys.splice(index, 1); + // remove education_level_short_name + index = keys.indexOf('education_level_short_name'); + if(index > -1) keys.splice(index, 1); + let objMatch = null; + + for(let i = 0; i < queryTotal.length; ++i) { + let total = queryTotal[i]; + let foundMatch = true; + for(let j = 0; j < keys.length; ++j) { + let key = keys[j]; + if(total[key] !== result[key]) { + foundMatch = false; + break; + } + } + if(foundMatch) { + objMatch = total; + break; + } + } + + if(objMatch) { + // console.log('MATCH!!!!'); + // console.log(objMatch); + newObj.total = (result.total / objMatch.total) * 100; + newObj.partial = result.total; + newObj.denominator = objMatch.total + match.push(newObj); + } + }); + // console.log('TAMANHOS'); + // console.log(queryTotal.length); + // console.log(queryPartial.length); + // console.log(match.length); + return match; +} + +glossEnrollmentRatioApp.get('/', rqf.parse(),(req, res, next) => { + req.numerator = {}; + req.denominator = {}; + let glossEnrollmentRatioApp = {}; + + req.sql.from('matricula') + .field('count(*)', 'total') + .field('matricula.ano_censo', 'year') + .group('matricula.ano_censo') + .order('matricula.ano_censo') + .where('matricula.tipo <= 3') + + if ( "education_level_short" in req.dims ) { + req.sql.field('matricula.etapa_resumida', 'age_range') + req.sql.where('matricula.etapa_resumida = 1 OR matricula.etapa_resumida = 2 OR matricula.etapa_resumida = 3 OR matricula.etapa_resumida = 4 OR matricula.etapa_resumida = 5') + req.sql.group('matricula.etapa_resumida', 'age_range'); + } + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.numerator = req.result; + req.resetSql(); + req.sql.field('sum(peso)', 'total') + .field('pnad.ano_censo','year') + .from('pnad') + .group('pnad.ano_censo') + .order('pnad.ano_censo') + + function convert(result) { + if (result == 1) { + return 'pnad.faixa_etaria_31_03 = 1' + } else if (result == 2) { + return 'pnad.faixa_etaria_31_03 = 2' + } else if (result == 4) { + return 'pnad.faixa_etaria_31_03 = 3' + } else if (result == 5) { + return 'pnad.faixa_etaria_31_03 = 4' + } else if (result == 6) { + return 'pnad.faixa_etaria_31_03 = 5' + } + } + + //remove education_level_short how filter and add faixa_etaria_31_03 in filter + if ("education_level_short" in req.filter) { + if (Array.isArray(req.filter.education_level_short)) { + var string_query = ''; + for(let i = 0; i < req.filter.education_level_short.length - 1; i++) { + string_query = string_query + convert(req.filter.education_level_short[i]) + ' OR '; + } + string_query = string_query + convert(req.filter.education_level_short[req.filter.education_level_short.length - 1]); + req.sql.where(string_query); + req.sql.field('pnad.faixa_etaria_31_03','age_range') + req.sql.group('pnad.faixa_etaria_31_03', 'age_range') + } + } else if ( "education_level_short" in req.dims ) { + req.sql.field('pnad.faixa_etaria_31_03','age_range') + req.sql.where('pnad.faixa_etaria_31_03 = 1 OR pnad.faixa_etaria_31_03 = 2 OR pnad.faixa_etaria_31_03 = 3 OR pnad.faixa_etaria_31_03 = 4 OR pnad.faixa_etaria_31_03 = 5') + req.sql.group('pnad.faixa_etaria_31_03', 'age_range'); + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + + next(); +}, rqf.parse(), (req, res, next) => { + if ("education_level_short" in req.filter) { + delete req.filter.education_level_short; + } + if ("education_level_short" in req.dims) { + delete req.dims.education_level_short; + } + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.denominator = req.result; + req.result = [] + let glossEnrollment = matchQueries(req.denominator, req.numerator); + req.result = glossEnrollment; + + next(); +}, response('glossEnrollmentRatio')); + +module.exports = glossEnrollmentRatioApp; diff --git a/src/libs/routes_v2/idhm.js b/src/libs/routes_v2/idhm.js new file mode 100644 index 00000000..5b941793 --- /dev/null +++ b/src/libs/routes_v2/idhm.js @@ -0,0 +1,212 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const idhmApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +idhmApp.use(cache('15 day')); + +idhmApp.get('/year_range', (req, res, next) => { + req.sql.from('adh_idh') + .field('MIN(adh_idh.ano_censo)', 'start_year') + .field('MAX(adh_idh.ano_censo)', 'end_year'); + next(); +}, query, (req, res, next) => { + req.sql.from('adh_idh_uf') + .field('MIN(adh_idh_uf.ano_censo)', 'start_year') + .field('MAX(adh_idh_uf.ano_censo)', 'end_year'); + req.old_result = req.result; + next(); +}, query, (req, res, next) => { + if (req.old_result[0].start_year < req.result[0].start_year) { + req.result[0].start_year = req.old_result[0].start_year; + } + if (req.old_result[0].end_year > req.result[0].end_year) { + req.result[0].end_year = req.old_result[0].old_result; + } + next(); +}, query, response('range')); + +idhmApp.get('/years', (req, res, next) => { + req.sql.from('adh_idh') + .field('DISTINCT adh_idh.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('adh_idh_uf') + .field('DISTINCT adh_idh_uf.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let result = Object.assign(req.oldResult, req.result); + req.result = result; + next(); +}, response('years')); + +idhmApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'adh_idh\''); + next(); +}, query, response('source')); + +idhmApp.get('/IDHM_level', (req, res, next) => { + req.result = [ + {id: null, name: 'Não classificada'}, + {id: 1, name: 'Muito Baixa'}, + {id: 2, name: 'Baixo'}, + {id: 3, name: 'Médio'}, + {id: 4, name: 'Alto'}, + {id: 5, name: 'Muito Alto'} + ]; + next(); +}, response('IDHM_level')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'adh_idh' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'adh_idh' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: '@' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'idhm_level', + table: '@', + tableField: 'idhm_nivel', + resultField: 'idhm_level_id', + where: { + relation: '=', + type: 'integer', + table: '@', + field: 'idhm_nivel' + } +}); + + +idhmApp.get('/', rqf.parse(), (req, res, next) => { + if (("city" in req.dims) || ("city" in req.filter)) { + req.sql.from('adh_idh') + .field('adh_idh.idhm', 'total') + .field('adh_idh.ano_censo', 'year') + .field('adh_idh.municipio_id', 'city_id') + .field('adh_idh.estado_id', 'state_id') + .group('adh_idh.idhm') + .group('adh_idh.ano_censo') + .group('adh_idh.municipio_id') + .group('adh_idh.estado_id') + } else if (("state" in req.filter) || ("state" in req.dims)) { + req.sql.from('adh_idh_uf') + .field('adh_idh_uf.idhm', 'total') + .field('adh_idh_uf.ano_censo', 'year') + .field('adh_idh_uf.estado_id', 'state_id') + .group('adh_idh_uf.idhm') + .group('adh_idh_uf.ano_censo') + .group('adh_idh_uf.estado_id') + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(), response('idhm')); + +module.exports = idhmApp; diff --git a/src/libs/routes_v2/idhme.js b/src/libs/routes_v2/idhme.js new file mode 100644 index 00000000..1b492c61 --- /dev/null +++ b/src/libs/routes_v2/idhme.js @@ -0,0 +1,185 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const idhmeApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +idhmeApp.use(cache('15 day')); + +idhmeApp.get('/year_range', (req, res, next) => { + req.sql.from('adh_idh') + .field('MIN(adh_idh.ano_censo)', 'start_year') + .field('MAX(adh_idh.ano_censo)', 'end_year'); + next(); +}, query, (req, res, next) => { + req.sql.from('adh_idh_uf') + .field('MIN(adh_idh_uf.ano_censo)', 'start_year') + .field('MAX(adh_idh_uf.ano_censo)', 'end_year'); + req.old_result = req.result; + next(); +}, query, (req, res, next) => { + if (req.old_result[0].start_year < req.result[0].start_year) { + req.result[0].start_year = req.old_result[0].start_year; + } + if (req.old_result[0].end_year > req.result[0].end_year) { + req.result[0].end_year = req.old_result[0].old_result; + } + next(); +}, query, response('range')); + +idhmeApp.get('/years', (req, res, next) => { + req.sql.from('adh_idh') + .field('DISTINCT adh_idh.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('adh_idh_uf') + .field('DISTINCT adh_idh_uf.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let result = Object.assign(req.oldResult, req.result); + req.result = result; + next(); +}, response('years')); + +idhmeApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'adh_idh\''); + next(); +}, query, response('source')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'adh_idh' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'adh_idh' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: '@' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}); + +idhmeApp.get('/', rqf.parse(), (req, res, next) => { + + if (("city" in req.dims) || ("city" in req.filter)) { + req.sql.from('adh_idh') + .field('adh_idh.idhm_e', 'total') + .field('adh_idh.ano_censo', 'year') + .field('adh_idh.municipio_id', 'city_id') + .group('adh_idh.idhm_e') + .group('adh_idh.ano_censo') + .group('adh_idh.municipio_id'); + } else if (("state" in req.filter) || ("state" in req.dims)) { + req.sql.from('adh_idh_uf') + .field('adh_idh_uf.idhm_e', 'total') + .field('adh_idh_uf.ano_censo', 'year') + .field('adh_idh_uf.estado_id', 'state_id') + .group('adh_idh_uf.idhm_e') + .group('adh_idh_uf.ano_censo') + .group('adh_idh_uf.estado_id'); + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(), response('idhme')); + +module.exports = idhmeApp; diff --git a/src/libs/routes_v2/idhml.js b/src/libs/routes_v2/idhml.js new file mode 100644 index 00000000..eee89ddf --- /dev/null +++ b/src/libs/routes_v2/idhml.js @@ -0,0 +1,185 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const idhmlApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +idhmlApp.use(cache('15 day')); + +idhmlApp.get('/year_range', (req, res, next) => { + req.sql.from('adh_idh') + .field('MIN(adh_idh.ano_censo)', 'start_year') + .field('MAX(adh_idh.ano_censo)', 'end_year'); + next(); +}, query, (req, res, next) => { + req.sql.from('adh_idh_uf') + .field('MIN(adh_idh_uf.ano_censo)', 'start_year') + .field('MAX(adh_idh_uf.ano_censo)', 'end_year'); + req.old_result = req.result; + next(); +}, query, (req, res, next) => { + if (req.old_result[0].start_year < req.result[0].start_year) { + req.result[0].start_year = req.old_result[0].start_year; + } + if (req.old_result[0].end_year > req.result[0].end_year) { + req.result[0].end_year = req.old_result[0].old_result; + } + next(); +}, query, response('range')); + +idhmlApp.get('/years', (req, res, next) => { + req.sql.from('adh_idh') + .field('DISTINCT adh_idh.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('adh_idh_uf') + .field('DISTINCT adh_idh_uf.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let result = Object.assign(req.oldResult, req.result); + req.result = result; + next(); +}, response('years')); + +idhmlApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'adh_idh\''); + next(); +}, query, response('source')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'adh_idh' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'adh_idh' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: '@' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}); + +idhmlApp.get('/', rqf.parse(), (req, res, next) => { + + if (("city" in req.dims) || ("city" in req.filter)) { + req.sql.from('adh_idh') + .field('adh_idh.idhm_l', 'total') + .field('adh_idh.ano_censo', 'year') + .field('adh_idh.municipio_id', 'city_id') + .group('adh_idh.idhm_l') + .group('adh_idh.ano_censo') + .group('adh_idh.municipio_id'); + } else if (("state" in req.filter) || ("state" in req.dims)) { + req.sql.from('adh_idh_uf') + .field('adh_idh_uf.idhm_l', 'total') + .field('adh_idh_uf.ano_censo', 'year') + .field('adh_idh_uf.estado_id', 'state_id') + .group('adh_idh_uf.idhm_l') + .group('adh_idh_uf.ano_censo') + .group('adh_idh_uf.estado_id'); + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(), response('idhme')); + +module.exports = idhmlApp; diff --git a/src/libs/routes_v2/idhmr.js b/src/libs/routes_v2/idhmr.js new file mode 100644 index 00000000..a9117cb4 --- /dev/null +++ b/src/libs/routes_v2/idhmr.js @@ -0,0 +1,188 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const idhmrApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +idhmrApp.use(cache('15 day')); + +idhmrApp.get('/year_range', (req, res, next) => { + req.sql.from('adh_idh') + .field('MIN(adh_idh.ano_censo)', 'start_year') + .field('MAX(adh_idh.ano_censo)', 'end_year'); + next(); +}, query, (req, res, next) => { + req.sql.from('adh_idh_uf') + .field('MIN(adh_idh_uf.ano_censo)', 'start_year') + .field('MAX(adh_idh_uf.ano_censo)', 'end_year'); + req.old_result = req.result; + next(); +}, query, (req, res, next) => { + if (req.old_result[0].start_year < req.result[0].start_year) { + req.result[0].start_year = req.old_result[0].start_year; + } + if (req.old_result[0].end_year > req.result[0].end_year) { + req.result[0].end_year = req.old_result[0].old_result; + } + next(); +}, query, response('range')); + +idhmrApp.get('/years', (req, res, next) => { + req.sql.from('adh_idh') + .field('DISTINCT adh_idh.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('adh_idh_uf') + .field('DISTINCT adh_idh_uf.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let result = Object.assign(req.oldResult, req.result); + req.result = result; + next(); +}, response('years')); + +idhmrApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'adh_idh\''); + next(); +}, query, response('source')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'adh_idh' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'adh_idh' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: '@' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}); + +idhmrApp.get('/', rqf.parse(), (req, res, next) => { + if (("city" in req.dims) || ("city" in req.filter)) { + req.sql.from('adh_idh') + .field('adh_idh.idhm_r', 'total') + .field('adh_idh.ano_censo', 'year') + .field('adh_idh.municipio_id', 'city_id') + .field('adh_idh.estado_id', 'state_id') + .group('adh_idh.idhm_r') + .group('adh_idh.ano_censo') + .group('adh_idh.municipio_id') + .group('adh_idh.estado_id') + } else if (("state" in req.filter) || ("state" in req.dims)) { + req.sql.from('adh_idh_uf') + .field('adh_idh_uf.idhm_r', 'total') + .field('adh_idh_uf.ano_censo', 'year') + .field('adh_idh_uf.estado_id', 'state_id') + .group('adh_idh_uf.idhm_r') + .group('adh_idh_uf.ano_censo') + .group('adh_idh_uf.estado_id') + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(), response('idhmr')); + +module.exports = idhmrApp; diff --git a/src/libs/routes_v2/infrastructure.js b/src/libs/routes_v2/infrastructure.js new file mode 100644 index 00000000..1ececa91 --- /dev/null +++ b/src/libs/routes_v2/infrastructure.js @@ -0,0 +1,585 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const infrastructureApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const multiQuery = require(`${libs}/middlewares/multiQuery`); + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +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', (req, res, next) => { + req.sql.from('escola') + .field('DISTINCT escola.ano_censo', 'year'); + next(); +}, query, response('years')); + +infrastructureApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'escola\''); + next(); +}, query, response('source')); + +infrastructureApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +infrastructureApp.get('/rural_location', (req, res, next) => { + req.result = [ + {id: 1, name: "Urbana"}, + {id: 2, name: "Rural"}, + {id: 3, name: "Rural - Ãrea de assentamento"}, + {id: 4, name: "Rural - Terra indÃgena"}, + {id: 5, name: "Rural - Ãrea remanescente de quilombos"}, + {id: 6, name: "Rural - Unidade de uso sustentável"} + ]; + next(); +}, response('rural_location')); + +infrastructureApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +infrastructureApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'id', + resultField: 'city_id', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'filter').addValueToField({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'escola' + } +}, 'dims').addValueToField({ + name: 'state', + table: 'estado', + tableField: 'id', + resultField: 'state_id', + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'escola' + } +}, 'filter').addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'location', + table: 'escola', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'rural_location', + table: 'escola', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'adm_dependency', + table: 'escola', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'escola', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'min_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}); + +function matchQueries(queryTotal, queryPartial) { + let match = []; + queryTotal.forEach((result) => { + let newObj = {}; + let keys = Object.keys(result); + keys.forEach((key) => { + newObj[key] = result[key]; + }); + let index = keys.indexOf('total'); + if(index > -1) keys.splice(index, 1); + let objMatch = null; + + for(let i = 0; i < queryPartial.length; ++i) { + let partial = queryPartial[i]; + let foundMatch = true; + for(let j = 0; j < keys.length; ++j) { + let key = keys[j]; + if(partial[key] !== result[key]) { + foundMatch = false; + break; + } + } + if(foundMatch) { + objMatch = partial; + break; + } + } + + if(objMatch) { + newObj.percentage = (objMatch.total / result.total) * 100; + newObj.partial = objMatch.total; + newObj.total = result.total + match.push(newObj); + } + }); + + return match; +} + +infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.querySet = []; + req.queryIndex = {}; + + // Local de funcionamento + let allSchools = req.sql.clone(); + allSchools.from('escola').field('COUNT(escola.id)', 'total') + .field("'Brasil'", 'name') + .field('escola.ano_censo', 'year') + .group('escola.ano_censo') + .where('escola.situacao_de_funcionamento = 1') + .order('escola.ano_censo'); + req.queryIndex.allSchools = req.querySet.push(allSchools) - 1; + + let schoolPlace = allSchools.clone(); + schoolPlace.where('escola.func_predio_escolar = 1 AND escola.func_salas_empresa = 0 AND escola.func_templo_igreja = 0 AND escola.func_casa_professor = 0 AND escola.func_galpao = 0 AND escola.biblioteca = 1'); + req.queryIndex.schoolPlace = req.querySet.push(schoolPlace) - 1; + + // Bibliotecas + let allLibraries = allSchools.clone(); + allLibraries.where('escola.func_predio_escolar = 1 AND escola.localizacao_id = 1'); + req.queryIndex.allLibraries = req.querySet.push(allLibraries) - 1; + + let haveLibraries = allLibraries.clone(); + haveLibraries.where('escola.biblioteca = 1'); + req.queryIndex.haveLibraries = req.querySet.push(haveLibraries) - 1; + + // Bibliotecas/Sala de leitura + let allLibrariesReadingRoom = allSchools.clone(); + allLibrariesReadingRoom.where('escola.func_predio_escolar = 1 AND escola.localizacao_id = 2'); + req.queryIndex.allLibrariesReadingRoom = req.querySet.push(allLibrariesReadingRoom) - 1; + + let haveLibrariesReadingRoom = allLibrariesReadingRoom.clone(); + haveLibrariesReadingRoom.where('escola.sala_leitura = 1'); + req.queryIndex.haveLibrariesReadingRoom = req.querySet.push(haveLibrariesReadingRoom) - 1; + + // Laboratório de informática + let allInfLab = allSchools.clone(); + allInfLab.where('escola.func_predio_escolar = 1') + .where('escola.reg_fund_ai = 1 OR escola.reg_fund_af = 1 OR escola.reg_medio_medio = 1 OR escola.reg_medio_integrado = 1 OR escola.reg_medio_normal = 1 OR escola.ensino_eja_fund = 1 OR escola.ensino_eja_medio = 1 OR escola.ensino_eja_prof = 1'); + req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1; + + let haveInfLab = allInfLab.clone(); + haveInfLab.where('escola.lab_informatica = 1'); + req.queryIndex.haveInfLab = req.querySet.push(haveInfLab) - 1; + + // Laboratório de ciências + let allScienceLab = allInfLab.clone(); + req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1; + + let haveScienceLab = allScienceLab.clone(); + haveScienceLab.where('escola.lab_ciencias = 1'); + req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1; + + // Parque infantil + let allKidsPark = allSchools.clone(); + allKidsPark.where('escola.func_predio_escolar = 1') + .where('escola.reg_infantil_creche = 1 OR escola.reg_infantil_preescola = 1 OR escola.reg_fund_ai = 1 OR escola.esp_infantil_creche = 1 OR escola.esp_exclusiva_creche = 1 OR escola.reg_esp_exclusiva_fund_ai = 1'); + req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1; + + let haveKidsPark = allKidsPark.clone(); + haveKidsPark.where('escola.parque_infantil = 1'); + req.queryIndex.haveKidsPark = req.querySet.push(haveKidsPark) - 1; + + // Berçário + let allCribs = allSchools.clone(); + allCribs.where('escola.func_predio_escolar = 1') + .where('escola.reg_infantil_creche = 1 OR escola.esp_infantil_creche = 1'); + req.queryIndex.allCribs = req.querySet.push(allCribs) - 1; + + let haveCribs = allCribs.clone(); + haveCribs.where('escola.bercario = 1'); + req.queryIndex.haveCribs = req.querySet.push(haveCribs) - 1; + + // Quadra + let allSportsCourt = allScienceLab.clone(); + allSportsCourt.where('escola.localizacao_id = 1'); + req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1; + + let haveSportsCourt = allSportsCourt.clone(); + haveSportsCourt.where('escola.quadra_esportes = 1'); + req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1; + + // Quadra coberta + req.queryIndex.allCoveredSportsCourt = req.queryIndex.allSportsCourt; + + let haveCoveredSportsCourt = allSportsCourt.clone(); + haveCoveredSportsCourt.where('escola.quadra_esportes_coberta = 1'); + req.queryIndex.haveCoveredSportsCourt = req.querySet.push(haveCoveredSportsCourt) - 1; + + // Quadra Descoberta + let allUncoveredSportsCourt = allSportsCourt.clone(); + allUncoveredSportsCourt.where('escola.quadra_esportes_coberta = 0'); + req.queryIndex.allUncoveredSportsCourt = req.querySet.push(allUncoveredSportsCourt) - 1; + + let haveUncoveredSportsCourt = allUncoveredSportsCourt.clone(); + haveUncoveredSportsCourt.where('escola.quadra_esportes_descoberta = 1'); + req.queryIndex.haveUncoveredSportsCourt = req.querySet.push(haveUncoveredSportsCourt) - 1; + + // Sala de direção + let allDirectorRoom = allSchools.clone(); + allDirectorRoom.where('escola.func_predio_escolar = 1 AND escola.localizacao_id = 1'); + req.queryIndex.allDirectorRoom = req.querySet.push(allDirectorRoom) - 1; + + let haveDirectorRoom = allDirectorRoom.clone(); + haveDirectorRoom.where('escola.sala_diretoria = 1'); + req.queryIndex.haveDirectorRoom = req.querySet.push(haveDirectorRoom) - 1; + + // Secretaria + let allSecretary = allSchools.clone(); + allSecretary.where('escola.func_predio_escolar = 1'); + req.queryIndex.allSecretary = req.querySet.push(allSecretary) - 1; + + let haveSecretary = allSecretary.clone(); + haveSecretary.where('escola.secretaria = 1'); + req.queryIndex.haveSecretary = req.querySet.push(haveSecretary) - 1; + + // Sala de professores + req.queryIndex.allTeacherRoom = req.queryIndex.allSecretary; + + let haveTeacherRoom = allSecretary.clone(); + haveTeacherRoom.where('escola.sala_professor = 1'); + req.queryIndex.haveTeacherRoom = req.querySet.push(haveTeacherRoom) - 1; + + // Cozinha + req.queryIndex.allKitchen = req.queryIndex.allSecretary; + + let haveKitchen = allSecretary.clone(); + haveKitchen.where('escola.cozinha = 1'); + req.queryIndex.haveKitchen = req.querySet.push(haveKitchen) - 1; + + // Despensa + req.queryIndex.allStoreroom = req.queryIndex.allSecretary; + + let haveStoreroom = allSecretary.clone(); + haveStoreroom.where('escola.despensa = 1'); + req.queryIndex.haveStoreroom = req.querySet.push(haveStoreroom) - 1; + + // Almoxarifado + req.queryIndex.allWarehouse = req.queryIndex.allSecretary; + + let haveWarehouse = allSecretary.clone(); + haveWarehouse.where('escola.almoxarifado = 1'); + req.queryIndex.haveWarehouse = req.querySet.push(haveWarehouse) - 1; + + // Internet + req.queryIndex.allInternet = req.queryIndex.allLibrariesReadingRoom; + + let haveInternet = allLibrariesReadingRoom.clone(); + haveInternet.where('escola.internet = 1'); + req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1; + + // Internet banda larga + req.queryIndex.allBroadbandInternet = req.queryIndex.allLibraries; + + let haveBroadbandInternet = allLibraries.clone(); + haveBroadbandInternet.where('escola.internet_banda_larga = 1'); + req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1; + + // Banheiro dentro do prédio + req.queryIndex.allInsideBathroom = req.queryIndex.allSecretary; + + let haveInsideBathroom = allSecretary.clone(); + haveInsideBathroom.where('escola.sanitario_dentro_predio = 1'); + req.queryIndex.haveInsideBathroom = req.querySet.push(haveInsideBathroom) - 1; + + // Banheiro adequado para educação infantil dentro do prédio + req.queryIndex.allInsideKidsBathroom = req.queryIndex.allKidsPark; + + let haveInsideKidsBathroom = allKidsPark.clone(); + haveInsideKidsBathroom.where('escola.sanitario_ei = 1'); + req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1; + + // Fornecimento de energia + req.queryIndex.allEletricEnergy = req.queryIndex.allSecretary; + + let haveEletricEnergy = allSecretary.clone(); + haveEletricEnergy.where('escola.fornecimento_energia = 1'); + req.queryIndex.haveEletricEnergy = req.querySet.push(haveEletricEnergy) - 1; + + // Abastecimento de água + req.queryIndex.allWaterSupply = req.queryIndex.allSecretary; + + let haveWaterSupply = allSecretary.clone(); + haveWaterSupply.where('escola.fornecimento_agua = 1'); + req.queryIndex.haveWaterSupply = req.querySet.push(haveWaterSupply) - 1; + + // Ãgua filtrada + req.queryIndex.allFilteredWater = req.queryIndex.allSecretary; + + let haveFilteredWater = allSecretary.clone(); + haveFilteredWater.where('escola.agua_filtrada = 1'); + req.queryIndex.haveFilteredWater = req.querySet.push(haveFilteredWater) - 1; + + // Coleta de esgoto + req.queryIndex.allSewage = req.queryIndex.allSecretary; + + let haveSewage = allSecretary.clone(); + haveSewage.where('escola.esgoto_sanitario = 1'); + req.queryIndex.haveSewage = req.querySet.push(haveSewage) - 1; + + // Sala de recursos multifuncionais para Atendimento Educacional Especializado + req.queryIndex.allMultifunctionRoom = req.queryIndex.allSecretary; + + let haveMultifunctionRoom = allSecretary.clone(); + haveMultifunctionRoom.where('escola.sala_atendimento_especial = 1'); + req.queryIndex.haveMultifunctionRoom = req.querySet.push(haveMultifunctionRoom) - 1; + + // Banheiros adaptados para pessoas com deficiências + req.queryIndex.allSpecialBathroom = req.queryIndex.allSecretary; + + let haveSpecialBathroom = allSecretary.clone(); + haveSpecialBathroom.where('escola.sanitario_pne = 1'); + req.queryIndex.haveSpecialBathroom = req.querySet.push(haveSpecialBathroom) - 1; + + // Dependências adaptada para pessoas com deficiências + req.queryIndex.allAdaptedBuilding = req.queryIndex.allSecretary; + + let haveAdaptedBuilding = allSecretary.clone(); + haveAdaptedBuilding.where('escola.dependencias_pne = 1'); + req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1; + + next(); +}, multiQuery, (req, res, next) => { + // Faz o matching entre os resultados + let school_place = matchQueries(req.result[req.queryIndex.allSchools], req.result[req.queryIndex.schoolPlace]); + let libraries = matchQueries(req.result[req.queryIndex.allLibraries], req.result[req.queryIndex.haveLibraries]); + let libraries_reading_room = matchQueries(req.result[req.queryIndex.allLibrariesReadingRoom], req.result[req.queryIndex.haveLibrariesReadingRoom]); + let computer_lab = matchQueries(req.result[req.queryIndex.allInfLab], req.result[req.queryIndex.haveInfLab]); + let science_lab = matchQueries(req.result[req.queryIndex.allScienceLab], req.result[req.queryIndex.haveScienceLab]); + let kids_park = matchQueries(req.result[req.queryIndex.allKidsPark], req.result[req.queryIndex.haveKidsPark]); + let nursery = matchQueries(req.result[req.queryIndex.allCribs], req.result[req.queryIndex.haveCribs]); + let sports_court = matchQueries(req.result[req.queryIndex.allSportsCourt], req.result[req.queryIndex.haveSportsCourt]); + let covered_sports_court = matchQueries(req.result[req.queryIndex.allCoveredSportsCourt], req.result[req.queryIndex.haveCoveredSportsCourt]); + let uncovered_sports_court = matchQueries(req.result[req.queryIndex.allUncoveredSportsCourt], req.result[req.queryIndex.haveUncoveredSportsCourt]); + let director_room = matchQueries(req.result[req.queryIndex.allDirectorRoom], req.result[req.queryIndex.haveDirectorRoom]); + let secretary = matchQueries(req.result[req.queryIndex.allSecretary], req.result[req.queryIndex.haveSecretary]); + let teacher_room = matchQueries(req.result[req.queryIndex.allTeacherRoom], req.result[req.queryIndex.haveTeacherRoom]); + let kitchen = matchQueries(req.result[req.queryIndex.allKitchen], req.result[req.queryIndex.haveKitchen]); + let storeroom = matchQueries(req.result[req.queryIndex.allStoreroom], req.result[req.queryIndex.haveStoreroom]); + let warehouse = matchQueries(req.result[req.queryIndex.allWarehouse], req.result[req.queryIndex.haveWarehouse]); + let internet = matchQueries(req.result[req.queryIndex.allInternet], req.result[req.queryIndex.haveInternet]); + let broadband_internet = matchQueries(req.result[req.queryIndex.allBroadbandInternet], req.result[req.queryIndex.haveBroadbandInternet]); + let inside_bathroom = matchQueries(req.result[req.queryIndex.allInsideBathroom], req.result[req.queryIndex.haveInsideBathroom]); + let inside_kids_bathroom = matchQueries(req.result[req.queryIndex.allInsideKidsBathroom], req.result[req.queryIndex.haveInsideKidsBathroom]); + let eletric_energy = matchQueries(req.result[req.queryIndex.allEletricEnergy], req.result[req.queryIndex.haveEletricEnergy]); + let water_supply = matchQueries(req.result[req.queryIndex.allWaterSupply], req.result[req.queryIndex.haveWaterSupply]); + let filtered_water = matchQueries(req.result[req.queryIndex.allFilteredWater], req.result[req.queryIndex.haveFilteredWater]); + let sewage_treatment = matchQueries(req.result[req.queryIndex.allSewage], req.result[req.queryIndex.haveSewage]); + let special_multifunction_room = matchQueries(req.result[req.queryIndex.allMultifunctionRoom], req.result[req.queryIndex.haveMultifunctionRoom]); + let special_bathroom = matchQueries(req.result[req.queryIndex.allSpecialBathroom], req.result[req.queryIndex.haveSpecialBathroom]); + let adapted_building = matchQueries(req.result[req.queryIndex.allAdaptedBuilding], req.result[req.queryIndex.haveAdaptedBuilding]); + + req.result = [{ + school_place, + libraries, + libraries_reading_room, + computer_lab, + science_lab, + kids_park, + nursery, + sports_court, + covered_sports_court, + uncovered_sports_court, + director_room, + secretary, + teacher_room, + kitchen, + storeroom, + warehouse, + internet, + broadband_internet, + inside_bathroom, + inside_kids_bathroom, + eletric_energy, + water_supply, + filtered_water, + sewage_treatment, + special_multifunction_room, + special_bathroom, + adapted_building + }]; + + next(); +}, id2str.multitransform(false), response('infrastructure')); + +module.exports = infrastructureApp; diff --git a/src/libs/routes_v2/liquidEnrollmentRatio.js b/src/libs/routes_v2/liquidEnrollmentRatio.js new file mode 100644 index 00000000..63bd9168 --- /dev/null +++ b/src/libs/routes_v2/liquidEnrollmentRatio.js @@ -0,0 +1,434 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const liquidEnrollmentRatioApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const multiQuery = require(`${libs}/middlewares/multiQuery`); + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +liquidEnrollmentRatioApp.use(cache('15 day')); + +// Complete range of the enrollments dataset. +// Returns a tuple of start and ending years of the complete enrollments dataset. +liquidEnrollmentRatioApp.get('/year_range', (req, res, next) => { + req.sql.from('pnad') + .field('DISTINCT pnad.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('matricula') + .field('DISTINCT matricula.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let distinct_years = []; + let new_result = []; + for (let i = 0; i < req.oldResult.length; i++) { + for (let j = 0; j < req.result.length; j++) { + if(req.oldResult[i].year == req.result[j].year) { + distinct_years.push(req.oldResult[i]); + } + } + } + new_result.push({start_year: distinct_years[distinct_years.length -1].year, end_year: distinct_years[0].year}); + req.result = new_result; + next(); +}, response('range')); + +liquidEnrollmentRatioApp.get('/years', (req, res, next) => { + req.sql.from('pnad') + .field('DISTINCT pnad.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('matricula') + .field('DISTINCT matricula.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let new_result = [] + for (let i = 0; i < req.oldResult.length; i++) { + for (let j = 0; j < req.result.length; j++) { + if(req.oldResult[i].year == req.result[j].year) { + new_result.push(req.oldResult[i]); + } + } + } + req.result = new_result; + next(); +}, response('years')); + +liquidEnrollmentRatioApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'pnad\''); + next(); +}, query, response('source')); + +liquidEnrollmentRatioApp.get('/education_level_short', (req, res, next) => { + req.result = [ + {id: null, name: 'Não classificada'}, + {id: 1, name: 'Creche'}, + {id: 2, name: 'Pré-Escola'}, + {id: 3, name: 'Ensino Fundamental - anos iniciais'}, + {id: 4, name: 'Ensino Fundamental - anos finais'}, + {id: 5, name: 'Ensino Médio'} + ]; + next(); +}, response('education_level_short')); + +liquidEnrollmentRatioApp.get('/gender', (req, res, next) => { + req.result = [ + {id: 1, name: 'Masculino'}, + {id: 2, name: 'Feminino'} + ]; + next(); +}, response('gender')); + +liquidEnrollmentRatioApp.get('/ethnic_group', (req, res, next) => { + req.result = [ + {id: 0, name: 'Sem declaração'}, + {id: 1, name: 'Branca'}, + {id: 2, name: 'Preta'}, + {id: 3, name: 'Parda'}, + {id: 4, name: 'Amarela'}, + {id: 5, name: 'IndÃgena'} + ]; + next(); +}, response('ethnic_group')); + +liquidEnrollmentRatioApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: '@' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}).addValue({ + name: 'ethnic_group', + table: '@', + tableField: 'cor_raca_id', + resultField: 'ethnic_group_id', + where: { + relation: '=', + type: 'integer', + field: 'cor_raca_id' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'gender', + table: '@', + tableField: 'sexo', + resultField: 'gender_id', + where: { + relation: '=', + type: 'integer', + field: 'sexo' + } +}).addValue({ + name: 'location', + table: '@', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'education_level_short', + table: 'matricula', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}); + +function matchQueries(queryTotal, queryPartial) { + let match = []; + queryPartial.forEach((result) => { + let newObj = {}; + let keys = Object.keys(result); + keys.forEach((key) => { + newObj[key] = result[key]; + }); + // console.log('NEW OBJ'); + // console.log(newObj); + // remove total + let index = keys.indexOf('total'); + if(index > -1) keys.splice(index, 1); + // remove education_level_short_id + index = keys.indexOf('education_level_short_id'); + if(index > -1) keys.splice(index, 1); + // remove education_level_short_name + index = keys.indexOf('education_level_short_name'); + if(index > -1) keys.splice(index, 1); + let objMatch = null; + + for(let i = 0; i < queryTotal.length; ++i) { + let total = queryTotal[i]; + let foundMatch = true; + for(let j = 0; j < keys.length; ++j) { + let key = keys[j]; + if(total[key] !== result[key]) { + foundMatch = false; + break; + } + } + if(foundMatch) { + objMatch = total; + break; + } + } + + if(objMatch) { + // console.log('MATCH!!!!'); + // console.log(objMatch); + newObj.total = (result.total / objMatch.total) * 100; + newObj.partial = result.total; + newObj.denominator = objMatch.total + match.push(newObj); + } + }); + // console.log('TAMANHOS'); + // console.log(queryTotal.length); + // console.log(queryPartial.length); + // console.log(match.length); + return match; +} + +function ConvertEnrollment(result) { + if (result == 1) { + return '(matricula.faixa_etaria_31_03 = 1 AND matricula.etapa_resumida = 1)' + } else if (result == 2) { + return '(matricula.faixa_etaria_31_03 = 2 AND matricula.etapa_resumida = 2)' + } else if (result == 4) { + return '(matricula.faixa_etaria_31_03 = 3 AND matricula.etapa_resumida = 3)' + } else if (result == 5) { + return '(matricula.faixa_etaria_31_03 = 4 AND matricula.etapa_resumida = 4)' + } else if (result == 6) { + return '(matricula.faixa_etaria_31_03 = 5 AND matricula.etapa_resumida = 5)' + } +} + + +function convertPnad(result) { + if (result == 1) { + return 'pnad.faixa_etaria_31_03 = 1' + } else if (result == 2) { + return 'pnad.faixa_etaria_31_03 = 2' + } else if (result == 4) { + return 'pnad.faixa_etaria_31_03 = 3' + } else if (result == 5) { + return 'pnad.faixa_etaria_31_03 = 4' + } else if (result == 6) { + return 'pnad.faixa_etaria_31_03 = 5' + } +} + +liquidEnrollmentRatioApp.get('/', rqf.parse(),(req, res, next) => { + req.numerator = {}; + req.denominator = {}; + let liquidEnrollmentRatioApp = {}; + + req.sql.from('matricula') + .field('count(*)', 'total') + .field('matricula.ano_censo', 'year') + .group('matricula.ano_censo') + .order('matricula.ano_censo') + .where('matricula.tipo <= 3') + + if ("education_level_short" in req.filter) { + + if (Array.isArray(req.filter.education_level_short)) { + var stringQuery = ''; + for(let i = 0; i < req.filter.education_level_short.length - 1; i++) { + stringQuery = stringQuery + ConvertEnrollment(req.filter.education_level_short[i]) + ' OR '; + } + + stringQuery = stringQuery + ConvertEnrollment(req.filter.education_level_short[req.filter.education_level_short.length - 1]); + delete req.filter.education_level_short; + req.sql.where(stringQuery); + req.sql.field('matricula.faixa_etaria_31_03', 'age_range') + req.sql.group('matricula.faixa_etaria_31_03', 'age_range'); + } + + } else if ( "education_level_short" in req.dims ) { + + req.sql.field('matricula.faixa_etaria_31_03', 'age_range') + req.sql.where('(matricula.etapa_resumida = 1 AND matricula.faixa_etaria_31_03 = 1) OR (matricula.etapa_resumida = 2 AND matricula.faixa_etaria_31_03 = 2) OR (matricula.etapa_resumida = 3 AND matricula.faixa_etaria_31_03 = 3) OR (matricula.etapa_resumida = 4 AND matricula.faixa_etaria_31_03 = 4) OR (matricula.etapa_resumida = 5 AND matricula.faixa_etaria_31_03 = 5)'); + req.sql.group('matricula.faixa_etaria_31_03', 'age_range'); + + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.numerator = req.result; + req.resetSql(); + req.sql.field('sum(peso)', 'total') + .field('pnad.ano_censo','year') + .from('pnad') + .group('pnad.ano_censo') + .order('pnad.ano_censo') + + //remove education_level_short how filter and add faixa_etaria_31_03 in filter + + if ("education_level_short" in req.filter) { + + if (Array.isArray(req.filter.education_level_short)) { + var stringQuery = ''; + for(let i = 0; i < req.filter.education_level_short.length - 1; i++) { + stringQuery = stringQuery + convertPnad(req.filter.education_level_short[i]) + ' OR '; + } + stringQuery = stringQuery + convertPnad(req.filter.education_level_short[req.filter.education_level_short.length - 1]); + req.sql.where(stringQuery); + } + req.sql.field('pnad.faixa_etaria_31_03', 'age_range') + req.sql.group('pnad.faixa_etaria_31_03', 'age_range'); + + } else if ( "education_level_short" in req.dims ) { + + req.sql.field('pnad.faixa_etaria_31_03','age_range') + req.sql.where('pnad.faixa_etaria_31_03 = 1 OR pnad.faixa_etaria_31_03 = 2 OR pnad.faixa_etaria_31_03 = 3 OR pnad.faixa_etaria_31_03 = 4 OR pnad.faixa_etaria_31_03 = 5') + req.sql.group('pnad.faixa_etaria_31_03', 'age_range'); + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + + next(); +}, rqf.parse(), (req, res, next) => { + if ("education_level_short" in req.filter) { + delete req.filter.education_level_short; + } + if ("education_level_short" in req.dims) { + delete req.dims.education_level_short; + } + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.denominator = req.result; + + //division to generate req.result final + req.result = [] + let liquidEnrollment = matchQueries(req.denominator, req.numerator); + req.result = liquidEnrollment; + next(); +}, response('liquidEnrollmentRatio')); + +module.exports = liquidEnrollmentRatioApp; diff --git a/src/libs/routes_v2/location.js b/src/libs/routes_v2/location.js new file mode 100644 index 00000000..d493c452 --- /dev/null +++ b/src/libs/routes_v2/location.js @@ -0,0 +1,135 @@ +const express = require('express'); + +const locationApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const passport = require('passport'); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +locationApp.use(cache('15 day')) + +let rqf = new ReqQueryFields(); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'id', + table: 'localizacao_escolas', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}, 'dims'); + +locationApp.get('/school', rqf.parse(), (req, res, next) => { + req.dims.city=true; + req.dims.mesoregion=true; + req.dims.microregion=true; + + req.sql.from('localizacao_escolas') + .field('localizacao_escolas.nome', 'name') + .field('localizacao_escolas.id', 'id') + .field('localizacao_escolas.latitude', 'latitude') + .field('localizacao_escolas.longitude', 'longitude') + .group('localizacao_escolas.nome') + .group('localizacao_escolas.id') + .group('localizacao_escolas.latitude') + .group('localizacao_escolas.longitude'); + next(); +}, rqf.build(), query, id2str.transform(), response('location')); + +locationApp.get('/campi', rqf.parse(), (req, res, next) => { + req.dims.city=true; + req.dims.mesoregion=true; + req.dims.microregion=true; + + req.sql.from('localizacao_campi') + .field('localizacao_campi.nome', 'name') + .field('localizacao_campi.id', 'id') + .field('localizacao_campi.ies_id', 'ies_id') + .field('localizacao_campi.latitude', 'latitude') + .field('localizacao_campi.longitude', 'longitude') + .group('localizacao_campi.nome') + .group('localizacao_campi.id') + .group('localizacao_campi.ies_id') + .group('localizacao_campi.latitude') + .group('localizacao_campi.longitude'); + next(); +}, rqf.build(), query, id2str.transform(), response('location')); + +module.exports = locationApp; \ No newline at end of file diff --git a/src/libs/routes_v2/mesoregion.js b/src/libs/routes_v2/mesoregion.js new file mode 100644 index 00000000..001976f2 --- /dev/null +++ b/src/libs/routes_v2/mesoregion.js @@ -0,0 +1,86 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const mesoregionApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +mesoregionApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'municipio' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: 'mesorregiao_id', + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id' + } +}); + +mesoregionApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('municipio') + .field('municipio.nome_mesorregiao', 'name') + .field('municipio.mesorregiao_id', 'id') + .field('municipio.estado_id', 'state_id') + .group('municipio.nome_mesorregiao') + .group('municipio.mesorregiao_id') + .group('municipio.estado_id') + .order('municipio.mesorregiao_id'); + next(); +}, query, response('mesoregion')); + +module.exports = mesoregionApp; diff --git a/src/libs/routes_v2/message.js b/src/libs/routes_v2/message.js new file mode 100644 index 00000000..f9e0e330 --- /dev/null +++ b/src/libs/routes_v2/message.js @@ -0,0 +1,55 @@ +/* +Copyright (C) 2021 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const messageApp = express.Router(); + +const email = require(`../middlewares/email`); + +const log = require(`../log`)(module); + +messageApp.post('/', (req, res, next) => { + var reqName = req.body.name + var reqEmail = req.body.email + var reqContents = req.body.contents + var reqOrigin = req.body.origin ? req.body.origin : ""; + + var sub = "Contato " + reqOrigin + let mailOptions = { + to: ["dadoseducacionais@ufpr.br", reqEmail], + from: `\"${reqName}\" <dadoseducacionais@ufpr.br>`, + text: reqContents, + subject: sub + } + + email(mailOptions, (err, info) => { + if(err) { + log.error(err); + console.log(err); + res.status(500).json({msg: 'Undelivered Contact Mail'}); + } else { + log.info(`Message ${info.messageId} sent: ${info.response}`); + res.json({msg: 'Contact Mail Successfully Delivered'}); + } + }); +}) + +module.exports = messageApp; \ No newline at end of file diff --git a/src/libs/routes_v2/microregion.js b/src/libs/routes_v2/microregion.js new file mode 100644 index 00000000..c4aba0fe --- /dev/null +++ b/src/libs/routes_v2/microregion.js @@ -0,0 +1,99 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const microregionApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +microregionApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'municipio' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: 'mesorregiao_id', + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: 'microrregiao_id', + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id' + } +}); + +microregionApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('municipio') + .field('municipio.nome_microrregiao', 'name') + .field('municipio.microrregiao_id', 'id') + .field('municipio.nome_mesorregiao', 'mesoregion_name') + .field('municipio.mesorregiao_id', 'mesoregion_id') + .field('municipio.estado_id', 'state_id') + .group('municipio.nome_microrregiao') + .group('municipio.microrregiao_id') + .group('municipio.nome_mesorregiao') + .group('municipio.mesorregiao_id') + .group('municipio.estado_id') + .order('municipio.microrregiao_id'); + next(); +}, query, response('microregion')); + +module.exports = microregionApp; diff --git a/src/libs/routes_v2/outOfSchool.js b/src/libs/routes_v2/outOfSchool.js new file mode 100644 index 00000000..fcd57867 --- /dev/null +++ b/src/libs/routes_v2/outOfSchool.js @@ -0,0 +1,377 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const outOfSchoolApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +outOfSchoolApp.use(cache('15 day')); + +outOfSchoolApp.get('/year_range', (req, res, next) => { + req.sql.from('pnad') + .field('MIN(pnad.ano_censo)', 'start_year') + .field('MAX(pnad.ano_censo)', 'end_year') + .where('pnad.ano_censo >= 2007 AND pnad.ano_censo <= 2015'); + next(); +}, query, response('range')); + +outOfSchoolApp.get('/years', (req, res, next) => { + req.sql.from('pnad'). + field('DISTINCT pnad.ano_censo', 'year') + .where('pnad.ano_censo >= 2007 AND pnad.ano_censo <= 2015'); + next(); +}, query, response('years')); + +outOfSchoolApp.get('/full_age_range', (req, res, next) => { + req.result = [ + {id: 1, name: '0 a 3 anos'}, + {id: 2, name: '4 a 5 anos'}, + {id: 3, name: '6 a 10 anos'}, + {id: 4, name: '11 a 14 anos'}, + {id: 5, name: '15 a 17 anos'}, + {id: 6, name: '18 a 24 anos'}, + {id: 7, name: '25 a 29 anos'}, + {id: 8, name: '30 a 40 anos'}, + {id: 9, name: '41 a 50 anos'}, + {id: 10, name: '51 a 64 anos'}, + {id: 11, name: 'Mais de 64 anos'} + ]; + next(); +}, response('full_age_range')); + +outOfSchoolApp.get('/ethnic_group', (req, res, next) => { + req.result = [ + {id: 0, name: 'Sem declaração'}, + {id: 1, name: 'Branca'}, + {id: 2, name: 'Preta'}, + {id: 3, name: 'Parda'}, + {id: 4, name: 'Amarela'}, + {id: 5, name: 'IndÃgena'} + ]; + next(); +}, response('ethnic_group')); + +outOfSchoolApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +outOfSchoolApp.get('/gender', (req, res, next) => { + req.result = [ + {id: 1, name: 'Masculino'}, + {id: 2, name: 'Feminino'} + ]; + next(); +}, response('gender')); + +outOfSchoolApp.get('/fifth_household_income', (req, res, next) => { + req.result = [ + {id: 1, name: '20% menores'}, + {id: 2, name: '2o quinto'}, + {id: 3, name: '3o quinto'}, + {id: 4, name: '4o quinto'}, + {id: 5, name: '20% maiores'}, + {id: -1, name: 'Sem declaração'} + ]; + next(); +},response('fifth_household_income')); + +outOfSchoolApp.get('/extremes_household_income', (req, res, next) => { + req.result = [ + {id: 1, name: '10% menores'}, + {id: 2, name: '10% maiores'}, + {id: -1, name: 'Sem declaração'} + ]; + next(); +}, response('extremes_household_income')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'pnad' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'pnad' + } +}).addValue({ + name: 'ethnic_group', + table: 'pnad', + tableField: 'cor_raca_id', + resultField: 'ethnic_group_id', + where: { + relation: '=', + type: 'integer', + field: 'cor_raca_id' + } +}).addValue({ + name: 'min_year', + table: 'pnad', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'pnad', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'pnad', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'pnad', + field: 'ano_censo' + } +}).addValue({ + name: 'full_age_range', + table: 'pnad', + tableField: 'faixa_etaria_31_03', + resultField: 'full_age_range_id', + where: { + relation: '=', + type: 'integer', + field: 'faixa_etaria_31_03' + } +}).addValue({ + name: 'gender', + table: 'pnad', + tableField: 'sexo', + resultField: 'gender_id', + where: { + relation: '=', + type: 'integer', + field: 'sexo' + } +}).addValue({ + name: 'location', + table: 'pnad', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'extremes_household_income', + table: 'pnad', + tableField: 'extremos_nivel_rendimento', + resultField: 'extremes_household_income_id', + where: { + relation: '=', + type: 'integer', + field: 'extremos_nivel_rendimento' + } +}).addValue({ + name: 'fifth_household_income', + table: 'pnad', + tableField: 'quintil_nivel_rendimento', + resultField: 'fifth_household_income_id', + where: { + relation: '=', + type: 'integer', + field: 'quintil_nivel_rendimento' + } +}); + +outOfSchoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('pnad') + .field('SUM(pnad.peso)', 'total') + .field('pnad.ano_censo', 'year') + .where('pnad.escolaridade_familiar >= 1 AND pnad.escolaridade_familiar <= 4 AND pnad.frequenta_escola_creche = 4') + .group('pnad.ano_censo') + .order('pnad.ano_censo'); + + next(); +}, query, addMissing(rqf), id2str.transform(), response('out_of_school')); + +// Versão para o SimCAQ +let simcaqRqf = new ReqQueryFields(); + +simcaqRqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'brazil_total', + table: 'populacao_fora_da_escola', + tableField: 'brasil', + resultField: 'brazil_total_id', + where: { + relation: '=', + type: 'boolean', + field: 'brasil' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'populacao_fora_da_escola' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'populacao_fora_da_escola' + } +}).addValue({ + name: 'pfe', + table: 'populacao_fora_da_escola', + tableField: 'codigo_pfe', + resultField: 'pfe_id', + where: { + relation: '=', + type: 'integer', + field: 'codigo_pfe' + } +}).addValue({ + name: 'min_year', + table: 'populacao_fora_da_escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'populacao_fora_da_escola', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'populacao_fora_da_escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'populacao_fora_da_escola', + field: 'ano_censo' + } +}); + +outOfSchoolApp.get('/simcaq', simcaqRqf.parse(), (req, res, next) => { + if ('state' in req.filter || 'city' in req.filter || 'state' in req.dims || 'city' in req.dims) { // Query in state/city level + + if ('city' in req.filter && 'state' in req.filter) delete req.filter.state // use only the city filter because of the table particularities + + req.sql.from('populacao_fora_da_escola') + .field('SUM(populacao_fora_da_escola.pop_fora_escola)', 'total') + .field("'Brasil'", 'name') + .field('populacao_fora_da_escola.ano_censo') + .group('populacao_fora_da_escola.ano_censo') + .order('populacao_fora_da_escola.ano_censo'); + } else { // Query in 'Brasil' level + req.sql.from('populacao_fora_da_escola') + .field('SUM(populacao_fora_da_escola.pop_fora_escola)', 'total') + .field("'Brasil'", 'name') + .field('populacao_fora_da_escola.ano_censo') + .where('populacao_fora_da_escola.brasil = 1') + .group('populacao_fora_da_escola.ano_censo') + .order('populacao_fora_da_escola.ano_censo'); + } + + next(); +}, simcaqRqf.build(), query, (req, res, next) => { + req.result.forEach((i) => { + i.total = parseInt(i.total); + }); + next(); +}, addMissing(simcaqRqf), id2str.transform(), response('out_of_school')); + +module.exports = outOfSchoolApp; diff --git a/src/libs/routes_v2/pibpercapita.js b/src/libs/routes_v2/pibpercapita.js new file mode 100644 index 00000000..c5c77a92 --- /dev/null +++ b/src/libs/routes_v2/pibpercapita.js @@ -0,0 +1,250 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const pibpercapitaApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +pibpercapitaApp.use(cache('15 day')); + +pibpercapitaApp.get('/year_range', (req, res, next) => { + req.sql.from('ibge_pib') + .field('MIN(ibge_pib.ano_censo)', 'start_year') + .field('MAX(ibge_pib.ano_censo)', 'end_year') + .where('ibge_pib.ano_censo > 2013'); + next(); +}, query, response('range')); + +pibpercapitaApp.get('/years', (req, res, next) => { + req.sql.from('ibge_pib'). + field('DISTINCT ibge_pib.ano_censo', 'year') + .where('ibge_pib.ano_censo > 2013'); + next(); +}, query, response('years')); + +pibpercapitaApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'ibge_pib\''); + next(); +}, query, response('source')); + +pibpercapitaApp.get('/income_level', (req, res, next) => { + req.result = [ + {id: 1, name: "1º quintil – 20% menores"}, + {id: 2, name: "2º quintil"}, + {id: 3, name: "3º quintil"}, + {id: 4, name: "4º quintil"}, + {id: 5, name: "5º quintil – 20% maiores"}, + ]; + next(); +}, response('income_level')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'ibge_pib' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'ibge_pib' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: '@' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'regiao_id', + table: 'ibge_pib' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'ibge_pib' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'income_level', + table: 'ibge_pib', + tableField: 'nivel_renda_per_capita', + resultField: 'income_level_id', + where: { + relation: '=', + type: 'integer', + field: 'nivel_renda_per_capita' + } +}).addValue({ + name: 'income_level_brasil', + table: 'ibge_pib', + tableField: 'nivel_renda_brasil', + resultField: 'income_level_id', + where: { + relation: '=', + type: 'integer', + field: 'nivel_renda_brasil' + } +}).addValue({ + name: 'income_level_uf', + table: 'ibge_pib', + tableField: 'nivel_renda_uf', + resultField: 'income_level_id', + where: { + relation: '=', + type: 'integer', + field: 'nivel_renda_uf' + } +});; + +pibpercapitaApp.get('/', rqf.parse(), (req, res, next) => { + if ('income_level' in req.dims) { // Retorna os quintis + delete req.dims.income_level + + req.sql.from('pib_quintis') + .field('pib_quintis.valor', 'total') + .field('pib_quintis.tipo', 'income_level_id') + .field('pib_quintis.ano_censo', 'year') + .group('pib_quintis.ano_censo') + .group('pib_quintis.valor') + .group('pib_quintis.tipo') + .order('pib_quintis.tipo') + + if (!('state' in req.filter)) { + req.sql.where('pib_quintis.estado_id = 0') + } + if ('city' in req.filter) { + req.sql.join('ibge_pib', null, 'ibge_pib.nivel_renda_brasil=pib_quintis.tipo AND ibge_pib.ano_censo=pib_quintis.ano_censo') + } + } + + else if (("city" in req.dims) || ("city" in req.filter)) { + req.sql.from('ibge_pib') + .field('ibge_pib.pib_per_capita', 'total') + .field('ibge_pib.ano_censo', 'year') + .group('ibge_pib.ano_censo') + .group('ibge_pib.pib_per_capita') + .order('ibge_pib.ano_censo') + } else { + req.sql.from('ibge_pib') + .field('SUM(ibge_pib.pib)/SUM(ibge_pib.populacao)', 'total') + .field('ibge_pib.ano_censo', 'year') + .group('ibge_pib.ano_censo') + .order('ibge_pib.ano_censo') + } + next(); +}, rqf.build(), query, (req, res, next) => { + req.result.forEach((i) => { + let value = parseFloat(i.total); + let isnum = /^\d+$/.test(value); + if (isnum == true) { + value = value.toFixed(2) + } + // console.log(i.total); + + let res = value.toString().split("."); + //rounding decimal. + let decimal = Math.round(res[1].toString().substring(0,2) + (".") + res[1].toString().substring(2,3)); + //case 0 after comma + if (res[1].toString().substring(0,1) == 0) { + i.total = parseFloat(res[0] + "." + "0" + decimal); + } else { + i.total = parseFloat(res[0] + "." + decimal); + } + // console.log(i.total); + }); + next(); + }, id2str.transform(false), response("pibpercapita")); + + +module.exports = pibpercapitaApp; diff --git a/src/libs/routes_v2/population.js b/src/libs/routes_v2/population.js new file mode 100644 index 00000000..fca3b0d6 --- /dev/null +++ b/src/libs/routes_v2/population.js @@ -0,0 +1,163 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const populationApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +populationApp.use(cache('15 day')); + +populationApp.get('/year_range', (req, res, next) => { + req.sql.from('ibge_pib') + .field('MIN(ibge_pib.ano_censo)', 'start_year') + .field('MAX(ibge_pib.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +populationApp.get('/years', (req, res, next) => { + req.sql.from('ibge_pib'). + field('DISTINCT ibge_pib.ano_censo', 'year'); + next(); +}, query, response('years')); + +// populationApp.get('/city_size', (req, res, next) => { +// req.result = [ +// {id: 1, name: "0 - 5000"}, +// {id: 2, name: "5001 - 10000"}, +// {id: 3, name: "10001 - 20000"}, +// {id: 4, name: "20001 - 50000"}, +// {id: 5, name: "50001 - 100000"}, +// {id: 6, name: "100001 - 500000"}, +// {id: 7, name: "mais que 500000"} +// ]; +// next(); +// }, response('city_size')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'ibge_pib' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'ibge_pib' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'ibge_pib' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'ibge_pib' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'regiao_id', + table: 'ibge_pib' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'ibge_pib' + } +}).addValue({ + name: 'min_year', + table: 'ibge_pib', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'ibge_pib', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}); + +populationApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('ibge_pib') + .field('SUM(ibge_pib.populacao)', 'total') + .field('ibge_pib.ano_censo', 'year') + .group('ibge_pib.ano_censo') + .order('ibge_pib.ano_censo') + + next(); +}, query, addMissing(rqf), id2str.transform(false), response('population')); + +module.exports = populationApp; diff --git a/src/libs/routes_v2/portalMec.js b/src/libs/routes_v2/portalMec.js new file mode 100644 index 00000000..e0e5353e --- /dev/null +++ b/src/libs/routes_v2/portalMec.js @@ -0,0 +1,136 @@ +const express = require('express'); + +const portalMecApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'day', + table: 'docente', + tableField: 'nasc_dia', + resultField: 'born_day_id', + where: { + relation: '=', + type: 'integer', + table: 'docente', + field: 'nasc_dia' + } +}).addValue({ + name: 'month', + table: 'docente', + tableField: 'nasc_mes_id', + resultField: 'born_month', + where: { + relation: '=', + type: 'integer', + table: 'docente', + field: 'nasc_mes' + } +}).addValue({ + name: 'year', + table: 'docente', + tableField: 'nasc_ano_id', + resultField: 'born_year', + where: { + relation: '=', + type: 'integer', + table: 'docente', + field: 'nasc_ano' + } +}).addValue({ + name: 'teacher', + table: 'docente', + tableField: 'id', + resultField: 'teacher_id', + where: { + relation: '=', + type: 'integer', + table: 'docente', + field: 'id' + } +}).addValue({ + name: 'min_year', + table: 'docente', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'docente', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'docente', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'docente', + field: 'ano_censo' + } +}); + +portalMecApp.get('/', rqf.parse(), (req, res, next) => { + + req.sql.field('docente.id_docente') + .field('docente.ano_censo', 'year') + .field('docente.cod_quimica', 'QuÃmica') + .field('docente.cod_fisica', 'FÃsica') + .field('docente.cod_matematica', 'Matemática') + .field('docente.cod_biologia', 'Biologia') + .field('docente.cod_ciencias', 'Ciências') + .field('docente.cod_literat_port', 'LÃngua/ Literatura Portuguesa') + .field('docente.cod_literat_ing', 'LÃngua/ Literatura estrangeira - Inglês') + .field('docente.cod_literat_esp', 'LÃngua/ Literatura estrangeira - Espanhol') + .field('docente.cod_literat_frances', 'LÃngua/ Literatura estrangeira - Francês') + .field('docente.literat_outra', 'LÃngua/ Literatura estrangeira - Outra') + .field('docente.cod_literat_indigena', 'LÃngua/ Literatura estrangeira - LÃngua IndÃgena') + .field('docente.cod_artes', 'Artes (Educação ArtÃstica, Teatro, Dança, Música, Artes Plásticas e outras)') + .field('docente.cod_ed_fisica', 'Educação FÃsica') + .field('docente.cod_hist', 'História') + .field('docente.cod_geo', 'Geografia') + .field('docente.cod_filos', 'Filosofia') + .field('docente.cod_ensino_religioso', 'Ensino Religioso') + .field('docente.cod_estudos_sociais', 'Estudos Sociais') + .field('docente.cod_sociologia', 'Sociologia') + .field('docente.cod_inf_comp', 'Informática/ Computação') + .field('docente.cod_profissionalizante', 'Disciplinas profissionalizantes') + .field('docente.cod_disc_atendimento_especiais', 'Disciplinas voltadas ao atendimento à s necessidades educacionais especÃficas dos alunos que são público alvo da educação especial e à s práticas educacionais inclusivas') + .field('docente.cod_disc_diversidade_socio_cult', 'Disciplinas voltadas à diversidade sociocultural (Disciplinas pedagógicas)') + .field('docente.cod_libras', 'Libras') + .field('docente.cod_disciplina_pedag', 'Disciplinas pedagógicas') + .field('docente.cod_outras_disciplina', 'Outras disciplinas') + .from('docente') + next(); + +}, rqf.build(), query, response('portalMec')); + +module.exports = portalMecApp; diff --git a/src/libs/routes_v2/portalMecInep.js b/src/libs/routes_v2/portalMecInep.js new file mode 100644 index 00000000..2b235891 --- /dev/null +++ b/src/libs/routes_v2/portalMecInep.js @@ -0,0 +1,60 @@ +const express = require('express'); + +const portalMecInepApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'school_cod', + table: 'escola', + tableField: 'id', + resultField: 'school_cod_id', + where: { + relation: '=', + type: 'integer', + table: 'escola', + field: 'id' + } +}); + +portalMecInepApp.get('/', rqf.parse(), (req, res, next) => { + + req.sql.field('DISTINCT escola.id', 'id') + .field('escola.nome_escola', 'name') + .from('escola') + .join('estado', null, 'estado.id=escola.estado_id') + .field('estado.nome', 'state_name') + .join('municipio', null, 'municipio.id=escola.municipio_id') + .field('municipio.nome', 'city_name') + + next(); + +}, rqf.build(), query, response('portalMec_inep')); + +module.exports = portalMecInepApp; diff --git a/src/libs/routes_v2/rateSchool.js b/src/libs/routes_v2/rateSchool.js new file mode 100644 index 00000000..a6a91b7b --- /dev/null +++ b/src/libs/routes_v2/rateSchool.js @@ -0,0 +1,337 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const rateSchoolApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const multiQuery = require(`${libs}/middlewares/multiQuery`); + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +rateSchoolApp.use(cache('15 day')); + +let rqf = new ReqQueryFields(); + +// Complete range of the enrollments dataset. +// Returns a tuple of start and ending years of the complete enrollments dataset. +rateSchoolApp.get('/year_range', (req, res, next) => { + req.sql.from('pnad') + .field('MIN(pnad.ano_censo)', 'start_year') + .field('MAX(pnad.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +rateSchoolApp.get('/years', (req, res, next) => { + req.sql.from('pnad') + .field('DISTINCT pnad.ano_censo', 'year'); + next(); +}, query, response('years')); + +rateSchoolApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'pnad\''); + next(); +}, query, response('source')); + +rateSchoolApp.get('/ethnic_group_pnad', (req, res, next) => { + req.result = [ + {id: 0, name: 'IndÃgena'}, + {id: 1, name: 'Branca e amarela'}, + {id: 2, name: 'Preta e parda'}, + {id: 9, name: 'Sem declaração'} + ]; + next(); +}, response('ethnic_group_pnad')); + +rateSchoolApp.get('/age_range', (req, res, next) => { + req.result = [ + {id: 1, name: '0 a 3 anos'}, + {id: 2, name: '4 a 5 anos'}, + {id: 3, name: '6 a 10 anos'}, + {id: 4, name: '11 a 14 anos'}, + {id: 5, name: '15 a 17 anos'}, + {id: 6, name: '18 a 24 anos'} + ]; + next(); +}, response('age_range')); + +rateSchoolApp.get('/gender', (req, res, next) => { + req.result = [ + {id: 1, name: 'Masculino'}, + {id: 2, name: 'Feminino'} + ]; + next(); +}, response('gender')); + +rateSchoolApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +rateSchoolApp.get('/fifth_household_income', (req, res, next) => { + req.result = [ + {id: 1, name: '20% menores'}, + {id: 2, name: '2o quinto'}, + {id: 3, name: '3o quinto'}, + {id: 4, name: '4o quinto'}, + {id: 5, name: '20% maiores'}, + {id: -1, name: 'Sem declaração'} + ]; + next(); +},response('fifth_household_income')); + +rateSchoolApp.get('/extremes_household_income', (req, res, next) => { + req.result = [ + {id: 1, name: '10% menores'}, + {id: 2, name: '10% maiores'}, + {id: -1, name: 'Sem declaração'} + ]; + next(); +}, response('extremes_household_income')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'pnad' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'pnad' + } +}).addValue({ + name: 'ethnic_group_pnad', + table: 'pnad', + tableField: 'cor_raca', + resultField: 'ethnic_group_pnad_id', + where: { + relation: '=', + type: 'integer', + field: 'cor_raca' + } +}).addValue({ + name: 'min_year', + table: 'pnad', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'pnad', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'pnad', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'pnad', + field: 'ano_censo' + } +}).addValue({ + name: 'age_range', + table: 'pnad', + tableField: 'faixa_etaria_31_03', + resultField: 'age_range_id', + where: { + relation: '=', + type: 'integer', + field: 'faixa_etaria_31_03' + } +}).addValue({ + name: 'gender', + table: 'pnad', + tableField: 'sexo', + resultField: 'gender_id', + where: { + relation: '=', + type: 'integer', + field: 'sexo' + } +}).addValue({ + name: 'location', + table: 'pnad', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'extremes_household_income', + table: 'pnad', + tableField: 'extremos_nivel_rendimento', + resultField: 'extremes_household_income_id', + where: { + relation: '=', + type: 'integer', + field: 'extremos_nivel_rendimento' + } +}).addValue({ + name: 'fifth_household_income', + table: 'pnad', + tableField: 'quintil_nivel_rendimento', + resultField: 'fifth_household_income_id', + where: { + relation: '=', + type: 'integer', + field: 'quintil_nivel_rendimento' + } +}); + +function matchQueries(queryTotal, queryPartial) { + let match = []; + queryTotal.forEach((result) => { + let newObj = {}; + let keys = Object.keys(result); + keys.forEach((key) => { + newObj[key] = result[key]; + }); + // console.log('NEW OBJ'); + // console.log(newObj); + let index = keys.indexOf('total'); + if(index > -1) keys.splice(index, 1); + let objMatch = null; + + for(let i = 0; i < queryPartial.length; ++i) { + let partial = queryPartial[i]; + let foundMatch = true; + for(let j = 0; j < keys.length; ++j) { + let key = keys[j]; + if(partial[key] !== result[key]) { + foundMatch = false; + break; + } + } + if(foundMatch) { + objMatch = partial; + break; + } + } + + if(objMatch) { + // console.log(objMatch); + newObj.denominator = result.total; + newObj.partial = objMatch.total; + newObj.total = (objMatch.total / result.total) * 100; + match.push(newObj); + } + }); + + return match; +} + +rateSchoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.querySet = []; + req.queryIndex = {}; + + log.debug(req.sql.toParam()); + if ("age_range" in req.filter || "age_range" in req.dims) { + let freq_total = req.sql.clone(); + freq_total.field('sum(pnad.peso)', 'total') + .field('pnad.ano_censo','year') + .from('pnad') + .group('pnad.ano_censo') + .order('pnad.ano_censo') + .where('pnad.faixa_etaria_31_03 < 7') + req.queryIndex.freq_total = req.querySet.push(freq_total) - 1; + + let freq_nursery = req.sql.clone(); + freq_nursery.field('sum(pnad.peso)', 'total') + .field('pnad.ano_censo','year') + .from('pnad') + .group('pnad.ano_censo') + .order('pnad.ano_censo') + .where('pnad.frequenta_escola_creche = 2') + .where('pnad.faixa_etaria_31_03 < 7') + req.queryIndex.freq_nursery = req.querySet.push(freq_nursery) - 1; + } + next(); +}, multiQuery, (req, res, next) => { + if ("age_range" in req.filter || "age_range" in req.dims) { + log.debug(req.result[req.queryIndex.freq_total]); + log.debug(req.result[req.queryIndex.freq_nursery]) + let school_attendance_rate = matchQueries(req.result[req.queryIndex.freq_total], req.result[req.queryIndex.freq_nursery]); + req.result = school_attendance_rate; + } else { + res.status(400); + next({ + status: 400, + message: 'Wrong/No filter specified' + }); + } + log.debug(req.result) + next(); +}, id2str.transform(false), response('rateSchool')); + +module.exports = rateSchoolApp; diff --git a/src/libs/routes_v2/region.js b/src/libs/routes_v2/region.js new file mode 100644 index 00000000..5df65e72 --- /dev/null +++ b/src/libs/routes_v2/region.js @@ -0,0 +1,72 @@ +const express = require('express'); + +const regionApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +regionApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'id', + table: '@', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id', + table: '@' + } +}).addValue({ + name: 'id_not', + table: '@', + tableField: 'id', + where: { + relation: '<>', + type: 'integer', + field: 'id', + table: '@' + } +}).addField({ + name: 'search', + field: false, + where: true +}).addValueToField({ + name: 'name', + table: '@', + tableField: 'nome', + where: { + relation: 'LIKE', + type: 'string', + field: 'nome', + table: '@' + } +}, 'search'); + +regionApp.get('/', rqf.parse(), (req, res, next) => { + req.sql.from('regiao') + .field('id') + .field('nome', 'name'); + next(); +}, rqf.build(), query, response('region')); + +module.exports = regionApp; diff --git a/src/libs/routes_v2/resetToken.js b/src/libs/routes_v2/resetToken.js new file mode 100644 index 00000000..34ece845 --- /dev/null +++ b/src/libs/routes_v2/resetToken.js @@ -0,0 +1,81 @@ +const express = require('express'); + +const resetTokenApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const ResetToken = require(`${libs}/models/resetToken`); + +const User = require(`${libs}/models/user`); + +resetTokenApp.get('/:token', (req, res, next) => { + let token = req.params.token; + ResetToken.findOne({token: token}, (err, rToken) => { + if(err) { + log.error(err); + return next(err); + } + if(!rToken) { + // TODO: generate new reset token + res.statusCode = 404; + return next({msg: 'Token not found', status:404}); + } + if (rToken.hasExpired()) { + res.statusCode = 410; + ResetToken.remove({token: token}, (err) => { + if(err) { + log.error(err); + next(err); + } + }) + return next({msg: 'Token expired', status: 410}); + } + User.findById(rToken.userId, (err, user) => { + if(err) { + log.error(err); + next(err); + } + let u = user.toObject(); + delete u.salt; + delete u.hashedPassword; + res.json({user: u}); + }); + }); +}); +resetTokenApp.post('/:token', (req, res, next) => { + let token = req.params.token; + ResetToken.findOne({token: token}, (err, rToken) => { + if(err) { + log.error(err); + return next(err); + } + if(!rToken) { + res.statusCode = 404; + return next({msg: 'Token not found', status:404}); + } + User.findById(rToken.userId, (err, user) => { + if(err) { + log.error(err); + next(err); + } + user.password = req.body.password; + user.save((err) => { + if(err) { + log.error(err); + next(err); + } + ResetToken.remove({token: token}, (err) => { + if(err) { + log.error(err); + next(err); + } + }) + res.json({msg: "Senha alterada com sucesso"}); + }) + }); + }); +}) + +module.exports = resetTokenApp; diff --git a/src/libs/routes/school.js b/src/libs/routes_v2/school.js similarity index 100% rename from src/libs/routes/school.js rename to src/libs/routes_v2/school.js diff --git a/src/libs/routes_v2/schoolInfrastructure.js b/src/libs/routes_v2/schoolInfrastructure.js new file mode 100644 index 00000000..c74f0e30 --- /dev/null +++ b/src/libs/routes_v2/schoolInfrastructure.js @@ -0,0 +1,741 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const infrastructureApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const multiQuery = require(`${libs}/middlewares/multiQuery`); + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +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', (req, res, next) => { + req.sql.from('escola') + .field('DISTINCT escola.ano_censo', 'year'); + next(); +}, query, response('years')); + +infrastructureApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'escola\''); + next(); +}, query, response('source')); + +infrastructureApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +infrastructureApp.get('/rural_location', (req, res, next) => { + req.result = [ + {id: 1, name: "Urbana"}, + {id: 2, name: "Rural"}, + {id: 3, name: "Rural - Ãrea de assentamento"}, + {id: 4, name: "Rural - Terra indÃgena"}, + {id: 5, name: "Rural - Ãrea remanescente de quilombos"}, + {id: 6, name: "Rural - Unidade de uso sustentável"} + ]; + next(); +}, response('rural_location')); + +infrastructureApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +infrastructureApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'id', + resultField: 'city_id', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'escola' + } +}, 'filter').addValueToField({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'escola' + } +}, 'dims').addValueToField({ + name: 'state', + table: 'estado', + tableField: 'id', + resultField: 'state_id', + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'escola' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'escola' + } +}, 'filter').addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'escola' + } +}).addValue({ + name: 'location', + table: 'escola', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'rural_location', + table: 'escola', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'adm_dependency', + table: 'escola', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'escola', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'min_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}); + +function matchQueries(queryTotal, queryPartial, queryNeeded, zeroPercentage=false) { + let match = []; + queryTotal.forEach((result) => { + let newObj = {}; + let keys = Object.keys(result); + keys.forEach((key) => { + newObj[key] = result[key]; + }); + let index = keys.indexOf('total'); + if(index > -1) keys.splice(index, 1); + let partialMatch = null; + let needMatch = null; + + for(let i = 0; i < queryPartial.length; ++i) { + let partial = queryPartial[i]; + let foundMatch = true; + for(let j = 0; j < keys.length; ++j) { + let key = keys[j]; + if(partial[key] !== result[key]) { + foundMatch = false; + break; + } + } + if(foundMatch) { + partialMatch = partial; + break; + } + } + if(queryPartial.length == 0) { + partialMatch = JSON.parse(JSON.stringify(result)); + partialMatch.total = 0; + } + + for(let i = 0; i < queryNeeded.length; ++i) { + let needed = queryNeeded[i]; + let foundMatch = true; + for(let j = 0; j < keys.length; ++j) { + let key = keys[j]; + if(needed[key] !== result[key]) { + foundMatch = false; + break; + } + } + if(foundMatch) { + needMatch = needed; + break; + } + } + + if(queryNeeded.length == 0) { + needMatch = JSON.parse(JSON.stringify(result)); + needMatch.total = 0; + } + + newObj.percentage = ( ( partialMatch ? partialMatch.total : 0) / result.total) * 100; + if(zeroPercentage) newObj.percentage = 0; + newObj.partial = ( partialMatch ? partialMatch.total : 0); + newObj.total = result.total; + newObj.need_adaptation = needMatch ? needMatch.total : 0; + match.push(newObj); + }); + + return match; +} + +infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.querySet = []; + req.queryIndex = {}; + + // Local de funcionamento + let allSchools = req.sql.clone(); + allSchools.from('escola').field('COUNT(escola.id)', 'total') + .field("'Brasil'", 'name') + .field('escola.ano_censo', 'year') + .group('escola.ano_censo') + .where('escola.situacao_de_funcionamento = 1') + .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1') + .where('escola.local_func_predio_escolar = 1') + .where('escola.dependencia_adm_id <= 3') + .order('escola.ano_censo'); + req.queryIndex.allSchools = req.querySet.push(allSchools) - 1; + + let allUrbanSchools = allSchools.clone(); + allUrbanSchools.where('escola.localizacao_id = 1'); + req.queryIndex.allUrbanSchools = req.querySet.push(allUrbanSchools) - 1; + + let allCountrySchools = allSchools.clone(); + allCountrySchools.where('escola.localizacao_id = 2'); + req.queryIndex.allCountrySchools = req.querySet.push(allCountrySchools) - 1; + + let allSchoolsNotSchoolBuilding = req.sql.clone(); + allSchoolsNotSchoolBuilding.from('escola').field('COUNT(escola.id)', 'total') + .field("'Brasil'", 'name') + .field('escola.ano_censo', 'year') + .group('escola.ano_censo') + .where('escola.situacao_de_funcionamento = 1') + .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1') + .where('escola.local_func_predio_escolar = 0') + .where('escola.dependencia_adm_id <= 3') + .order('escola.ano_censo'); + req.queryIndex.allSchoolsNotSchoolBuilding = req.querySet.push(allSchoolsNotSchoolBuilding) - 1; + + // Bibliotecas + req.queryIndex.allLibraries = req.queryIndex.allUrbanSchools; + + let haveLibraries = allUrbanSchools.clone(); + haveLibraries.where('escola.biblioteca = 1'); + req.queryIndex.haveLibraries = req.querySet.push(haveLibraries) - 1; + + let needLibraries = allUrbanSchools.clone(); + needLibraries.where('escola.biblioteca = 0'); + req.queryIndex.needLibraries = req.querySet.push(needLibraries) - 1; + + // Sala de leitura + req.queryIndex.allLibrariesReadingRoom = req.queryIndex.allCountrySchools; + + let haveLibrariesReadingRoom = allCountrySchools.clone(); + haveLibrariesReadingRoom.where('escola.biblioteca_sala_leitura = true'); + req.queryIndex.haveLibrariesReadingRoom = req.querySet.push(haveLibrariesReadingRoom) - 1; + + let needLibrariesReadingRoom = allCountrySchools.clone(); + needLibrariesReadingRoom.where('escola.biblioteca_sala_leitura = false'); + req.queryIndex.needLibrariesReadingRoom = req.querySet.push(needLibrariesReadingRoom) - 1; + + // Laboratório de informática + // Se (situacao_de_funcionamento=1) & (dependencia_adm_id<=3) & (CEBES027P1=1) & + // (ensino_regular=1 | ensino_eja=1 | educacao_profissional=1) & + // ( reg_fund_ai_t1=1 | reg_fund_af_t1=1 | reg_medio_medio_t1=1 | ensino_eja_fund= 1 | ensino_eja_medio= 1 | ensino_eja_prof= 1 | esp_eja_fund=1 | + // esp_eja_medio=1 | ensino_esp_exclusiva_eja_prof=1) então conta id + let allInfLab = allSchools.clone(); + allInfLab.where('reg_fund_ai_t1=1 OR reg_fund_af_t1=1 OR reg_medio_medio_t1=1 OR ensino_eja_fund=1 OR ensino_eja_medio=1 OR ensino_eja_prof=1 OR esp_eja_fund=1 OR esp_eja_medio=1 OR ensino_esp_exclusiva_eja_prof=1'); + req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1; + + let haveInfLab = allInfLab.clone(); + haveInfLab.where('escola.lab_informatica = 1'); + req.queryIndex.haveInfLab = req.querySet.push(haveInfLab) - 1; + + let needInfLab = allInfLab.clone(); + needInfLab.where('escola.lab_informatica = 0'); + req.queryIndex.needInfLab = req.querySet.push(needInfLab) - 1; + + // Laboratório de ciências + let allScienceLab = allSchools.clone(); + allScienceLab.where('reg_fund_af_t1=1 OR reg_medio_medio_t1=1 OR ensino_eja_fund=1 OR ensino_eja_medio=1 OR ensino_eja_prof=1 OR esp_eja_fund=1 OR esp_eja_medio=1 OR ensino_esp_exclusiva_eja_prof=1'); + req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1; + + let haveScienceLab = allScienceLab.clone(); + haveScienceLab.where('escola.lab_ciencias = true'); + req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1; + + let needScienceLab = allScienceLab.clone(); + needScienceLab.where('escola.lab_ciencias = false'); + req.queryIndex.needScienceLab = req.querySet.push(needScienceLab) - 1; + + // Parque infantil + // Se (situacao_de_funcionamento=1) and (ensino_regular=1 OR ensino_eja=1 OR educacao_profissional=1) and + // (local_func_predio_escolar=1) and (dependencia_adm_id<=3) and (reg_infantil_creche_t1=1 or reg_infantil_preescola_t1=1 or reg_fund_ai_t1=1) então conta id + let allKidsPark = allSchools.clone(); + allKidsPark.where('reg_infantil_creche_t1=1 OR reg_infantil_preescola_t1=1 OR reg_fund_ai_t1=1'); + req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1; + + let haveKidsPark = allKidsPark.clone(); + haveKidsPark.where('escola.parque_infantil = 1'); + req.queryIndex.haveKidsPark = req.querySet.push(haveKidsPark) - 1; + + let needKidsPark = allKidsPark.clone(); + needKidsPark.where('escola.parque_infantil = 0'); + req.queryIndex.needKidsPark = req.querySet.push(needKidsPark) - 1; + + // // Berçário + // let allCribs = allSchools.clone(); + // allCribs.where('escola.reg_infantil_creche_t1 = 1'); + // req.queryIndex.allCribs = req.querySet.push(allCribs) - 1; + + // let haveCribs = allCribs.clone(); + // haveCribs.where('escola.bercario = 1'); + // req.queryIndex.haveCribs = req.querySet.push(haveCribs) - 1; + + // let needCribs = allCribs.clone(); + // needCribs.where('escola.bercario = 0'); + // req.queryIndex.needCribs = req.querySet.push(needCribs) - 1; + + // Quadra de esportes + let allSportsCourt = allSchools.clone(); + allSportsCourt.where('reg_fund_ai_t1=1 or reg_fund_af_t1=1 or reg_medio_medio_t1=1 or ensino_eja_fund= 1 or ensino_eja_medio= 1 or ensino_eja_prof= 1 or esp_eja_fund=1 or esp_eja_medio=1 or ensino_esp_exclusiva_eja_prof=1'); + req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1; + + let haveSportsCourt = allSportsCourt.clone(); + haveSportsCourt.where('escola.quadra_esportes = 1'); + req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1; + + let needSportsCourt = allSportsCourt.clone(); + needSportsCourt.where('escola.quadra_esportes = 0'); + req.queryIndex.needSportsCourt = req.querySet.push(needSportsCourt) - 1; + + // Quadras a serem cobertas + // Se (situacao_de_funcionamento=1) and (ensino_regular=1 OR ensino_eja=1 OR educacao_profissional=1) and (local_func_predio_escolar=1) and + // (dependencia_adm_id<=3) and (reg_fund_ai_t1=1 or reg_fund_af_t1=1 or reg_medio_medio_t1=1 or ensino_eja_fund= 1 or ensino_eja_medio= 1 or + // ensino_eja_prof= 1 or esp_eja_fund=1 or esp_eja_medio=1 or ensino_esp_exclusiva_eja_prof=1) and (quadra_esportes_descoberta=1) então conta id + let allSportsCourtCoverage = allSportsCourt.clone(); + allSportsCourtCoverage.where('escola.quadra_esportes_descoberta = 1'); + req.queryIndex.allSportsCourtCoverage = req.querySet.push(allSportsCourtCoverage) -1; + + req.queryIndex.haveSportsCourtCoverage = req.queryIndex.allSportsCourtCoverage; // It must be [] + + req.queryIndex.needSportsCourtCoverage = req.queryIndex.allSportsCourtCoverage; + + // Pátio + req.queryIndex.allCourtyard = req.queryIndex.allSchools; + + let haveCourtyard = allSchools.clone(); + haveCourtyard.where('escola.patio = 1 OR escola.patio = 2'); + req.queryIndex.haveCourtyard = req.querySet.push(haveCourtyard) - 1; + + let needCourtyard = allSchools.clone(); + needCourtyard.where('escola.patio = 0'); + req.queryIndex.needCourtyard = req.querySet.push(needCourtyard) - 1; + + // Pátios a serem cobertos + let allCourtyardCoverage = allSchools.clone(); + allCourtyardCoverage.where('escola.patio = 1'); + req.queryIndex.allCourtyardCoverage = req.querySet.push(allCourtyardCoverage) - 1; + + req.queryIndex.haveCourtyardCoverage = req.queryIndex.allCourtyardCoverage; // It must be [] + + req.queryIndex.needCourtyardCoverage = req.queryIndex.allCourtyardCoverage; + + // Sala de direção + req.queryIndex.allDirectorRoom = req.queryIndex.allUrbanSchools; + + let haveDirectorRoom = allUrbanSchools.clone(); + haveDirectorRoom.where('escola.sala_diretoria = 1'); + req.queryIndex.haveDirectorRoom = req.querySet.push(haveDirectorRoom) - 1; + + let needDirectorRoom = allUrbanSchools.clone(); + needDirectorRoom.where('escola.sala_diretoria = 0'); + req.queryIndex.needDirectorRoom = req.querySet.push(needDirectorRoom) - 1; + + // Secretaria + req.queryIndex.allSecretary = req.queryIndex.allSchools; + + let haveSecretary = allSchools.clone(); + haveSecretary.where('escola.secretaria = 1'); + req.queryIndex.haveSecretary = req.querySet.push(haveSecretary) - 1; + + let needSecretary = allSchools.clone(); + needSecretary.where('escola.secretaria = 0'); + req.queryIndex.needSecretary = req.querySet.push(needSecretary) - 1; + + // Sala de professores + req.queryIndex.allTeacherRoom = req.queryIndex.allSchools; + + let haveTeacherRoom = allSchools.clone(); + haveTeacherRoom.where('escola.sala_professor = 1'); + req.queryIndex.haveTeacherRoom = req.querySet.push(haveTeacherRoom) - 1; + + let needTeacherRoom = allSchools.clone(); + needTeacherRoom.where('escola.sala_professor = 0'); + req.queryIndex.needTeacherRoom = req.querySet.push(needTeacherRoom) - 1; + + // Cozinha + req.queryIndex.allKitchen = req.queryIndex.allSchools; + + let haveKitchen = allSchools.clone(); + haveKitchen.where('escola.cozinha = 1'); + req.queryIndex.haveKitchen = req.querySet.push(haveKitchen) - 1; + + let needKitchen = allSchools.clone(); + needKitchen.where('escola.cozinha = 0'); + req.queryIndex.needKitchen = req.querySet.push(needKitchen) - 1; + + // Despensa + req.queryIndex.allStoreroom = req.queryIndex.allSchools; + + let haveStoreroom = allSchools.clone(); + haveStoreroom.where('escola.despensa = 1'); + req.queryIndex.haveStoreroom = req.querySet.push(haveStoreroom) - 1; + + let needStoreroom = allSchools.clone(); + needStoreroom.where('escola.despensa = 0'); + req.queryIndex.needStoreroom = req.querySet.push(needStoreroom) - 1; + + // Almoxarifado + req.queryIndex.allWarehouse = req.queryIndex.allSchools; + + let haveWarehouse = allSchools.clone(); + haveWarehouse.where('escola.almoxarifado = 1'); + req.queryIndex.haveWarehouse = req.querySet.push(haveWarehouse) - 1; + + let needWarehouse = allSchools.clone(); + needWarehouse.where('escola.almoxarifado = 0'); + req.queryIndex.needWarehouse = req.querySet.push(needWarehouse) - 1; + + // Internet + req.queryIndex.allInternet = req.queryIndex.allCountrySchools; + + let haveInternet = allCountrySchools.clone(); + haveInternet.where('escola.internet = 1'); + req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1; + + let needInternet = allCountrySchools.clone(); + needInternet.where('escola.internet = 0'); + req.queryIndex.needInternet = req.querySet.push(needInternet) - 1; + + // Internet banda larga + // Se (situacao_de_funcionamento=1) and (ensino_regular=1 OR ensino_eja=1 OR educacao_profissional=1) and (local_func_predio_escolar=1) and + // (dependencia_adm_id<=3) and (localizacao_id=2) então conta id + req.queryIndex.allBroadbandInternet = req.queryIndex.allUrbanSchools; + + let haveBroadbandInternet = allUrbanSchools.clone(); + haveBroadbandInternet.where('escola.internet_banda_larga = 1'); + req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1; + + let needBroadbandInternet = allUrbanSchools.clone(); + needBroadbandInternet.where('escola.internet_banda_larga = 0'); + req.queryIndex.needBroadbandInternet = req.querySet.push(needBroadbandInternet) - 1; + + // Banheiro + req.queryIndex.allInsideBathroom = req.queryIndex.allSchools; + + let haveInsideBathroom = allSchools.clone(); + haveInsideBathroom.where('escola.banheiro = 1'); + req.queryIndex.haveInsideBathroom = req.querySet.push(haveInsideBathroom) - 1; + + let needInsideBathroom = allSchools.clone(); + needInsideBathroom.where('escola.banheiro = 0'); + req.queryIndex.needInsideBathroom = req.querySet.push(needInsideBathroom) - 1; + + // Banheiro adequado para educação infantil dentro do prédio + // Se (situacao_de_funcionamento=1) and (ensino_regular=1 OR ensino_eja=1 OR educacao_profissional=1) and (local_func_predio_escolar=1) and + // (dependencia_adm_id<=3) and (reg_infantil_creche_t1=1 or reg_infantil_preescola_t1=1 or reg_fund_ai_t1=1) então conta id + let allInsideKidsBathroom = allSchools.clone(); + allInsideKidsBathroom.where('reg_infantil_creche_t1=1 OR reg_infantil_preescola_t1=1 OR reg_fund_ai_t1=1'); + req.queryIndex.allInsideKidsBathroom = req.querySet.push(allInsideKidsBathroom) - 1; + + let haveInsideKidsBathroom = allInsideKidsBathroom.clone(); + haveInsideKidsBathroom.where('escola.sanitario_ei = 1'); + req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1; + + let needInsideKidsBathroom = allInsideKidsBathroom.clone(); + needInsideKidsBathroom.where('escola.sanitario_ei = 0'); + req.queryIndex.needInsideKidsBathroom = req.querySet.push(needInsideKidsBathroom) - 1; + + // Fornecimento de energia + req.queryIndex.allEletricPower = req.queryIndex.allSchools; + + let haveEletricPower = allSchools.clone(); + haveEletricPower.where('escola.energia_inexistente = 0'); + req.queryIndex.haveEletricPower = req.querySet.push(haveEletricPower) - 1; + + let needEletricPower = allSchools.clone(); + needEletricPower.where('escola.energia_inexistente = 1'); + req.queryIndex.needEletricPower = req.querySet.push(needEletricPower) - 1; + + // Abastecimento de água + req.queryIndex.allWaterSupply = req.queryIndex.allSchools; + + let haveWaterSupply = allSchools.clone(); + haveWaterSupply.where('escola.agua_inexistente = 0'); + req.queryIndex.haveWaterSupply = req.querySet.push(haveWaterSupply) - 1; + + let needWaterSupply = allSchools.clone(); + needWaterSupply.where('escola.agua_inexistente = 1'); + req.queryIndex.needWaterSupply = req.querySet.push(needWaterSupply) - 1; + + // Ãgua Potável + req.queryIndex.allFilteredWater = req.queryIndex.allSchools; + + let haveFilteredWater = allSchools.clone(); + haveFilteredWater.where('escola.agua_potavel = 1'); + req.queryIndex.haveFilteredWater = req.querySet.push(haveFilteredWater) - 1; + + let needFilteredWater = allSchools.clone(); + needFilteredWater.where('escola.agua_potavel = 0'); + req.queryIndex.needFilteredWater = req.querySet.push(needFilteredWater) - 1; + + // Coleta de esgoto + req.queryIndex.allSewage = req.queryIndex.allSchools; + + let haveSewage = allSchools.clone(); + haveSewage.where('escola.esgoto_rede_publica = 1 OR escola.esgoto_fossa_septica = 1'); + req.queryIndex.haveSewage = req.querySet.push(haveSewage) - 1; + + let needSewage = allSchools.clone(); + needSewage.where('escola.esgoto_rede_publica = 0 AND escola.esgoto_fossa_septica = 0'); + req.queryIndex.needSewage = req.querySet.push(needSewage) - 1; + + // Dependências adaptada para pessoas com deficiências + req.queryIndex.allAdaptedBuilding = req.queryIndex.allSchools; + + let haveAdaptedBuilding = allSchools.clone(); + haveAdaptedBuilding.where('escola.acessibilidade_inexistente = 0'); + req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1; + + let needAdaptedBuilding = allSchools.clone(); + needAdaptedBuilding.where('escola.acessibilidade_inexistente = 1'); + req.queryIndex.needAdaptedBuilding = req.querySet.push(needAdaptedBuilding) - 1; + + // Banheiros adaptados para pessoas com deficiências + req.queryIndex.allSpecialBathroom = req.queryIndex.allSchools; + + let haveSpecialBathroom = allSchools.clone(); + haveSpecialBathroom.where('escola.sanitario_pne = 1'); + req.queryIndex.haveSpecialBathroom = req.querySet.push(haveSpecialBathroom) - 1; + + let needSpecialBathroom = allSchools.clone(); + needSpecialBathroom.where('escola.sanitario_pne = 0'); + req.queryIndex.needSpecialBathroom = req.querySet.push(needSpecialBathroom) - 1; + + + next(); +}, multiQuery, (req, res, next) => { + + let schools_in_school_buildings = req.result[req.queryIndex.allSchools]; + let urban_schools_in_school_buildings = req.result[req.queryIndex.allUrbanSchools]; + let country_schools_in_school_buildings = req.result[req.queryIndex.allCountrySchools]; + let schools_not_in_school_buildings = req.result[req.queryIndex.allSchoolsNotSchoolBuilding]; + + // Faz o matching entre os resultados + let libraries = matchQueries(req.result[req.queryIndex.allLibraries], req.result[req.queryIndex.haveLibraries], req.result[req.queryIndex.needLibraries]); + let libraries_reading_room = matchQueries(req.result[req.queryIndex.allLibrariesReadingRoom], req.result[req.queryIndex.haveLibrariesReadingRoom], req.result[req.queryIndex.needLibrariesReadingRoom]); + let computer_lab = matchQueries(req.result[req.queryIndex.allInfLab], req.result[req.queryIndex.haveInfLab], req.result[req.queryIndex.needInfLab]); + let science_lab = matchQueries(req.result[req.queryIndex.allScienceLab], req.result[req.queryIndex.haveScienceLab], req.result[req.queryIndex.needScienceLab]); + let kids_park = matchQueries(req.result[req.queryIndex.allKidsPark], req.result[req.queryIndex.haveKidsPark], req.result[req.queryIndex.needKidsPark]); + // let nursery = matchQueries(req.result[req.queryIndex.allCribs], req.result[req.queryIndex.haveCribs], req.result[req.queryIndex.needCribs]); + let sports_court = matchQueries(req.result[req.queryIndex.allSportsCourt], req.result[req.queryIndex.haveSportsCourt], req.result[req.queryIndex.needSportsCourt]); + let sports_court_coverage = matchQueries(req.result[req.queryIndex.allSportsCourtCoverage], [], req.result[req.queryIndex.needSportsCourtCoverage], true); // have = [] + let courtyard = matchQueries(req.result[req.queryIndex.allCourtyard], req.result[req.queryIndex.haveCourtyard], req.result[req.queryIndex.needCourtyard]); + let courtyard_coverage = matchQueries(req.result[req.queryIndex.allCourtyardCoverage], [], req.result[req.queryIndex.needCourtyardCoverage], true); // have = [] + let director_room = matchQueries(req.result[req.queryIndex.allDirectorRoom], req.result[req.queryIndex.haveDirectorRoom], req.result[req.queryIndex.needDirectorRoom]); + let secretary = matchQueries(req.result[req.queryIndex.allSecretary], req.result[req.queryIndex.haveSecretary], req.result[req.queryIndex.needSecretary]); + let teacher_room = matchQueries(req.result[req.queryIndex.allTeacherRoom], req.result[req.queryIndex.haveTeacherRoom], req.result[req.queryIndex.needTeacherRoom]); + let kitchen = matchQueries(req.result[req.queryIndex.allKitchen], req.result[req.queryIndex.haveKitchen], req.result[req.queryIndex.needKitchen]); + let storeroom = matchQueries(req.result[req.queryIndex.allStoreroom], req.result[req.queryIndex.haveStoreroom], req.result[req.queryIndex.needStoreroom]); + let warehouse = matchQueries(req.result[req.queryIndex.allWarehouse], req.result[req.queryIndex.haveWarehouse], req.result[req.queryIndex.needWarehouse]); + let internet = matchQueries(req.result[req.queryIndex.allInternet], req.result[req.queryIndex.haveInternet], req.result[req.queryIndex.needInternet]); + let broadband_internet = matchQueries(req.result[req.queryIndex.allBroadbandInternet], req.result[req.queryIndex.haveBroadbandInternet], req.result[req.queryIndex.needBroadbandInternet]); + let inside_bathroom = matchQueries(req.result[req.queryIndex.allInsideBathroom], req.result[req.queryIndex.haveInsideBathroom], req.result[req.queryIndex.needInsideBathroom]); + let inside_kids_bathroom = matchQueries(req.result[req.queryIndex.allInsideKidsBathroom], req.result[req.queryIndex.haveInsideKidsBathroom], req.result[req.queryIndex.needInsideKidsBathroom]); + let eletrical_power = matchQueries(req.result[req.queryIndex.allEletricPower], req.result[req.queryIndex.haveEletricPower], req.result[req.queryIndex.needEletricPower]); + let water_supply = matchQueries(req.result[req.queryIndex.allWaterSupply], req.result[req.queryIndex.haveWaterSupply], req.result[req.queryIndex.needWaterSupply]); + let filtered_water = matchQueries(req.result[req.queryIndex.allFilteredWater], req.result[req.queryIndex.haveFilteredWater], req.result[req.queryIndex.needFilteredWater]); + let sewage = matchQueries(req.result[req.queryIndex.allSewage], req.result[req.queryIndex.haveSewage], req.result[req.queryIndex.needSewage]); + let adapted_building = matchQueries(req.result[req.queryIndex.allAdaptedBuilding], req.result[req.queryIndex.haveAdaptedBuilding], req.result[req.queryIndex.needAdaptedBuilding]); + let adapted_bathroom = matchQueries(req.result[req.queryIndex.allSpecialBathroom], req.result[req.queryIndex.haveSpecialBathroom], req.result[req.queryIndex.needSpecialBathroom]); + + req.result = [{ + schools_in_school_buildings, + urban_schools_in_school_buildings, + country_schools_in_school_buildings, + schools_not_in_school_buildings, + libraries, + libraries_reading_room, + computer_lab, + science_lab, + kids_park, + sports_court, + sports_court_coverage, + courtyard, + courtyard_coverage, + director_room, + secretary, + teacher_room, + kitchen, + storeroom, + warehouse, + internet, + broadband_internet, + inside_bathroom, + inside_kids_bathroom, + eletric_energy: eletrical_power, + water_supply, + filtered_water, + sewage_treatment: sewage, + adapted_building, + special_bathroom: adapted_bathroom + }]; + + next(); +}, id2str.multitransform(false), response('infrastructure')); + +module.exports = infrastructureApp; diff --git a/src/libs/routes_v2/schoolLocation.js b/src/libs/routes_v2/schoolLocation.js new file mode 100644 index 00000000..5c0d98ff --- /dev/null +++ b/src/libs/routes_v2/schoolLocation.js @@ -0,0 +1,114 @@ +const express = require('express'); + +const schoolLocationApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const passport = require('passport'); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'id', + table: 'localizacao_escolas', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'localizacao_escolas' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'localizacao_escolas' + } +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: '@' + } +}, 'dims'); + +schoolLocationApp.get('/', rqf.parse(), (req, res, next) => { + req.dims.city=true; + req.dims.mesoregion=true; + req.dims.microregion=true; + + req.sql.from('localizacao_escolas') + .field('localizacao_escolas.nome', 'name') + .field('localizacao_escolas.id', 'id') + .field('localizacao_escolas.latitude', 'latitude') + .field('localizacao_escolas.longitude', 'longitude') + .group('localizacao_escolas.nome') + .group('localizacao_escolas.id') + .group('localizacao_escolas.latitude') + .group('localizacao_escolas.longitude'); + next(); +}, rqf.build(), query, id2str.transform(), response('school_location')); + +module.exports = schoolLocationApp; diff --git a/src/libs/routes_v2/simulation.js b/src/libs/routes_v2/simulation.js new file mode 100644 index 00000000..4b2e40c3 --- /dev/null +++ b/src/libs/routes_v2/simulation.js @@ -0,0 +1,167 @@ +const express = require('express'); + +const simulationApp = express(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const Simulation = require(`${libs}/models/simulation`); + +const PQR = require(`${libs}/models/pqr`); + +const passport = require('passport'); + +simulationApp.get('/time', (req, res, next) => { + const maxTime = parseInt(req.query.max_time, 10); + if(isNaN(maxTime)) { + res.status(400); + next({ + status: 400, + message: 'Invalid value for mandatory parameter max_time' + }); + } + res.json({ + result: Array.apply(null, {length: maxTime}).map(Number.call, Number).map((i)=>i+1) + }); +}); + +simulationApp.get('/pqr', (req, res) => { + PQR.findOne((err, pqr) => { + if(err) { + log.error(err); + return next({err}); + } + + res.json(pqr); + }); +}); + +simulationApp.put('/pqr', passport.authenticate('bearer', { session: false }), (req, res, next) => { + let user = req.user.toObject(); + + PQR.findOne((err, pqr) => { + if(err) { + log.error(err) + return next({err}); + } + + if(!user.admin) { + log.info(`Usuário ${user.email} tentou alterar o PQR, mas não tem privilégio`); + res.statusCode = 401; + return next({err: { msg: 'Unauthorized'}}); + } + pqr.content = req.body.content || pqr.content; + pqr.save((err) => { + if(err) { + log.error(err); + return next({err}); + } + res.json({msg: 'PQR updated'}) + }); + }); +}); + +simulationApp.get('/', passport.authenticate('bearer', { session: false }), (req, res) => { + let user = req.user.toObject(); + let query = Simulation.find({userId: user._id}).select('userId name createdAt updatedAt'); + query.exec((err, simulations) => { + if(err) { + log.error(err); + return next({err}); + } + + res.json(simulations); + }); + + // Simulation.find({userId: user._id}, (err, simulations) => { + // if(err) { + // log.error(err); + // return next({err}); + // } + + // res.json(simulations); + // }); +}); + +simulationApp.post('/', passport.authenticate('bearer', { session: false }), (req, res, next) => { + let user = req.user.toObject(); + + let simulation = new Simulation({ + userId: user._id, + content: req.body.content, + name: req.body.name + }); + + simulation.save((err) => { + if(err) { + log.error(err); + return next({err}); + } + + res.json({msg: 'Simulation created', simulation}); + }) +}); + +simulationApp.get('/:id', passport.authenticate('bearer', { session: false }), (req, res) => { + let user = req.user.toObject(); + + Simulation.findOne({_id: req.params.id, userId: user._id}, (err, simulation) => { + if(err) { + log.error(err); + return next({err}); + } + + res.json(simulation); + }); +}); + +simulationApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { + let user = req.user.toObject(); + + Simulation.findOne({_id: req.params.id, userId: user._id}, (err, simulation) => { + if(err) { + log.error(err); + return next({err}); + } + + if(!simulation) { + res.statusCode = 404; + return next({err: { msg: 'Simulation not found'}}); + } + + simulation.content = req.body.content || simulation.content; + simulation.name = req.body.name || simulation.name; + simulation.updatedAt = Date.now(); + + simulation.save((err) => { + if(err) { + log.error(err); + return next(err); + } + + res.json(simulation); + }); + }); +}); + +simulationApp.delete('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { + let user = req.user.toObject(); + + Simulation.remove({_id: req.params.id, userId: user._id}, (err, simulation) => { + if(err) { + log.error(err); + return next({err}); + } + + res.json({msg: 'Simulation removed'}); + }); +}); + +module.exports = simulationApp; diff --git a/src/libs/routes_v2/siope.js b/src/libs/routes_v2/siope.js new file mode 100644 index 00000000..1ef9f101 --- /dev/null +++ b/src/libs/routes_v2/siope.js @@ -0,0 +1,186 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const siopeApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const multiQuery = require(`${libs}/middlewares/multiQuery`); + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +siopeApp.use(cache('15 day')); + +siopeApp.get('/years', (req, res, next) => { + req.sql.from('siope_mun') + .field('DISTINCT siope_mun.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + req.oldResult = req.result; + + req.sql = squel.select(); + + req.sql.from('siope_uf') + .field('DISTINCT siope_uf.ano_censo', 'year'); + next(); +}, query, (req, res, next) => { + let result = Object.assign(req.oldResult, req.result); + req.result = result; + next(); +}, response('years')); + +rqf.addField({ + name: 'filter', + field: true, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'siope_mun' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'siope_mun' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['id','nome','sigla'], + resultField: ['state_id','state_name','state_abbreviation'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: '@' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: '@' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}); + + + +siopeApp.get('/', rqf.parse(), (req, res, next) => { + req.querySet = []; + req.queryIndex = {}; + + let siopeUf = req.sql.clone(); + siopeUf.from('siope_uf') + .field('siope_uf.ano_censo', 'year') + .field('siope_uf.estado_id', 'state_id') + .field('siope_uf.fundeb', 'fundeb') + .field('siope_uf.total_impostos', 'impostos') + .field('siope_uf.total_mde', 'MDE') + .group('siope_uf.ano_censo') + .group('siope_uf.estado_id') + .group('siope_uf.fundeb') + .group('siope_uf.total_impostos') + .group('siope_uf.total_mde') + .order('siope_uf.ano_censo'); + req.queryIndex.siopeUf = req.querySet.push(siopeUf) - 1; + + let siopeMun = req.sql.clone(); + siopeMun.from('siope_mun') + .field('siope_mun.ano_censo', 'year') + .field('siope_mun.estado_id', 'state_id') + .field('siope_mun.municipio_id', 'city_id') + .field('siope_mun.fundeb', 'fundeb') + .field('siope_mun.total_impostos', 'impostos') + .field('siope_mun.total_mde', 'MDE') + .group('siope_mun.ano_censo') + .group('siope_mun.estado_id') + .group('siope_mun.municipio_id') + .group('siope_mun.fundeb') + .group('siope_mun.total_impostos') + .group('siope_mun.total_mde') + .order('siope_mun.ano_censo'); + req.queryIndex.siopeMun = req.querySet.push(siopeMun) - 1; + + next(); +}, rqf.multibuild(), multiQuery, (req, res, next) => { + + let result = [] + + req.result[req.queryIndex.siopeUf].forEach((item) => { + result.push(item) + }); + req.result[req.queryIndex.siopeMun].forEach((item) => { + result.push(item) + }); + + req.result = result; + next(); + +}, response('siope')); + +module.exports = siopeApp; diff --git a/src/libs/routes_v2/spatial.js b/src/libs/routes_v2/spatial.js new file mode 100644 index 00000000..d4f48fe8 --- /dev/null +++ b/src/libs/routes_v2/spatial.js @@ -0,0 +1,373 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +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) { + resultMap[resultLbl].push(row); + } + } + resultIdx++; + } + 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', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + 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.localizacao_id=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.localizacao_id') + .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_v2/state.js b/src/libs/routes_v2/state.js new file mode 100644 index 00000000..c9830b20 --- /dev/null +++ b/src/libs/routes_v2/state.js @@ -0,0 +1,108 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const stateApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +stateApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'id', + table: 'estado', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'id_not', + table: 'estado', + tableField: 'id', + where: { + relation: '<>', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'regiao_id', + table: 'estado' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'estado' + } +}).addField({ + name: 'search', + field: false, + where: true +}).addValueToField({ + name: 'name', + table: 'estado', + tableField: 'nome', + where: { + relation: 'LIKE', + type: 'string', + field: 'nome' + } +}, 'search'); + +stateApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('estado') + .field('estado.id').group('estado.id') + .field('regiao_id', 'region_id').group('regiao_id') + .field('estado.nome', 'name').group('estado.nome') + .field('estado.sigla', 'abbreviation').group('estado.sigla') + .field('estado.longitude', 'longitude').group('estado.longitude') + .field('estado.latitude', 'latitude').group('estado.latitude') + .where('estado.id <> 99'); + next(); +}, query, response('state')); + +module.exports = stateApp; diff --git a/src/libs/routes_v2/studentsAee.js b/src/libs/routes_v2/studentsAee.js new file mode 100644 index 00000000..2a45a2f5 --- /dev/null +++ b/src/libs/routes_v2/studentsAee.js @@ -0,0 +1,219 @@ +const express = require('express'); + +const studentsAeeApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const passport = require('passport'); + +const download = require(`${libs}/middlewares/downloadDatabase`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); +let rqfCount = new ReqQueryFields(); + +// cubApp.get('/year_range', (req, res, next) => { + +// req.sql.from('cub') +// .field('MIN(cub.ano_censo)', 'start_year') +// .field('MAX(cub.ano_censo)', 'end_year'); +// next(); +// }, query, response('range')); + +// cubApp.get('/years', (req, res, next) => { +// req.sql.from('cub') +// .field('DISTINCT cub.ano_censo', 'year'); +// next(); +// }, query, response('years')); + +// cubApp.get('/months', (req, res, next) => { +// req.sql.from('cub') +// .field('DISTINCT cub.mes_censo', 'month'); +// next(); +// }, query, response('months')); + +// cubApp.get('/years_months', (req, res, next) => { +// req.sql.from('cub') +// .field('DISTINCT cub.ano_censo AS "year", cub.mes_censo AS "month"'); +// next(); +// }, query, response('years_months')); + +// cubApp.get('/price_type', (req, res, next) => { +// req.sql.from('cub') +// .field('DISTINCT cub.tipo_preco', 'price_type'); +// next(); +// }, query, response('price_type')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValueToField({ + name: 'state', // working + table: 'estado', + tableField: ['sigla', 'id'], + resultField: ['sigla_uf', 'cod_uf'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'numero_estudantes_aee' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'numero_estudantes_aee' + } +}, 'filter').addValueToField({ + name: 'city', // working + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'numero_estudantes_aee' + } +}, 'filter').addValue({ + name: 'region', // working + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'numero_estudantes_aee' + } +}).addValueToField({ + name: 'school', // working + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'numero_estudantes_aee' + } +}, 'filter').addValueToField({ + name: 'locale_id', // working + table: 'numero_estudantes_aee', + tableField: 'localidade_area_rural', + resultField: 'locale_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}, 'filter').addValue({ + name: 'ethnic_group', // working + table: 'numero_estudantes_aee', + tableField: 'cor_raca_id', + resultField: 'ethnic_group_id', + where: { + relation: '=', + type: 'integer', + field: 'cor_raca_id' + } +}).addValue({ + name: 'adm_dependency', // working + table: 'numero_estudantes_aee', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name:'age_range_all', // working + table: 'numero_estudantes_aee', + tableField: 'faixa_etaria_31_03', + resultField: 'age_range_all_id', + where: { + relation: '=', + type: 'integer', + field: 'faixa_etaria_31_03' + } + }).addValue({ + name: 'gender', // working + table: 'numero_estudantes_aee', + tableField: 'sexo', + resultField: 'gender_id', + where: { + relation: '=', + type: 'integer', + field: 'sexo' + } +}).addValue({ + name: 'activity_days', // working + table: 'numero_estudantes_aee', + tableField: 'dias_atividade', + resultField: 'activity_days_id', + where: { + relation: '=', + type: 'integer', + field: 'dias_atividade' + } +}).addField({ + name: 'special_service', // working + table: 'numero_estudantes_aee', + tableField: 'disc_atendimento_especiais', + resultField: 'special_service_id', + where: { + relation: '=', + type: 'integer', + field: 'disc_atendimento_especiais' + } +}); + +studentsAeeApp.get('/', rqf.parse(), (req, res, next) => { + req.sql.from('numero_estudantes_aee') + .field('numero_estudantes_aee.ano_censo') + .field('COUNT(distinct numero_estudantes_aee.id_aluno)', 'total') + .group('numero_estudantes_aee.ano_censo') + .order('numero_estudantes_aee.ano_censo') + next(); +}, rqf.build(), (req, res, next) => { + console.log(req.sql.toString()); + next(); +}, query, id2str.transform(), response('studentsAee')); + +module.exports = studentsAeeApp; diff --git a/src/libs/routes_v2/teacher.js b/src/libs/routes_v2/teacher.js new file mode 100644 index 00000000..94e6d86c --- /dev/null +++ b/src/libs/routes_v2/teacher.js @@ -0,0 +1,576 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +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`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const config = require(`${libs}/config`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +teacherApp.use(cache('15 day')); + +// 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('/years', (req, res, next) => { + req.sql.from('docente'). + field('DISTINCT docente.ano_censo', 'year'); + next(); +}, query, response('years')); + +teacherApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'docente\''); + next(); +}, query, response('source')); + +teacherApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +teacherApp.get('/diff_location', (req, res, next) => { + req.result = [ + {id: 0, name: "A escola não está em localidade diferenciada"}, + {id: 1, name: "Ãrea de assentamento"}, + {id: 2, name: "Terra indÃgena"}, + {id: 3, name: "Terra remanescente de quilombos"}, + ]; + next(); +}, response('diff_location')); + +teacherApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 8; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +teacherApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +teacherApp.get('/education_level_mod', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 12; ++i) { + req.result.push({ + id: i, + name: id2str.educationLevelMod(i) + }); + } + req.result.push({ + id: 99, + name: id2str.educationLevelMod(99) + }); + next(); +}, response('education_level_mod')); + +teacherApp.get('/education_level_short', (req, res, next) => { + req.result = [ + {id: null, name: 'Não classificada'}, + {id: 1, name: 'Creche'}, + {id: 2, name: 'Pré-Escola'}, + {id: 3, name: 'Ensino Fundamental - anos iniciais'}, + {id: 4, name: 'Ensino Fundamental - anos finais'}, + {id: 5, name: 'Ensino Médio'}, + {id: 6, name: 'EJA'}, + {id: 7, name: 'EE exclusiva'} + ]; + next(); +}, response('education_level_short')); + +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('/contract_type', (req, res, next) => { + req.result = [{ + id: "null", + contractType: id2str.contractType("null") + }]; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.contractType(i) + }); + } + next(); +}, response('contract_type')); + +teacherApp.get('/ethnic_group', (req, res, next) => { + req.result = []; + for(let i = 0; i <=5; ++i) { + req.result.push({ + id: i, + name: id2str.ethnicGroup(i) + }); + } + next(); +}, response('ethnic_group')); + +teacherApp.get('/initial_training', (req, res, next) => { + req.result = []; + for(let i = 1; i <=5; ++i) { + req.result.push({ + id: i, + name: id2str.initialTraining(i) + }); + } + next(); +}, response('initial_training')); + +teacherApp.get('/pos_training', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.posTraining(i) + }); + } + next(); +}, response('pos_training')); + +teacherApp.get('/licentiate_degree', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 3; ++i) { + req.result.push({ + id: i, + name: id2str.licentiateDegree(i) + }); + } + next(); +}, response('licentiate_degree')); + +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: 'contract_type', + table: 'docente', + tableField: 'tipo_contratacao', + resultField: 'contract_type_id', + where: { + relation: '=', + type: 'integer', + field: 'tipo_contratacao' + } +}).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_level_short', + table: 'docente', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}).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', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_regiao_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_estado_id', + foreignTable: 'docente' + } +}).addValueToField({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}, 'dims').addValueToField({ + name: 'city', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'docente' + } +}, 'filter').addValueToField({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'docente' + } +}, 'dims').addValueToField({ + 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' + } +}, 'filter').addValue({ + name: 'location', + table: 'docente', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'diff_location', + table: 'docente', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).addValue({ + name: 'rural_location', + table: 'docente', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).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', + field: 'cor_raca' + } +}).addValue({ + name: 'initial_training', + table: 'docente', + tableField: 'formacao_inicial_docente', + resultField: 'initial_training_id', + where: { + relation: '=', + type: 'integer', + field: 'formacao_inicial_docente' + } +}).addValue({ + name: 'pos_training', + table: 'docente', + tableField: 'formacao_pos_docente', + resultField: 'pos_training_id', + where: { + relation: '=', + type: 'integer', + field: 'formacao_pos_docente' + } +}).addValue({ + name: 'licentiate_degree', + table: 'docente', + tableField: 'formacao_licenciatura_docente', + resultField: 'licentiate_degree_id', + where: { + relation: '=', + type: 'integer', + field: 'formacao_licenciatura_docente' + } +}); + +const sortYearPtid = (a, b) => { + if (a.year < b.year) + return -1 + if (a.year > b.year) + return 1 + + if (a.pos_training_id < b.pos_training_id) + return -1 + if (a.pos_training_id > b.pos_training_id) + return 1 + return 0 +} + +teacherApp.get('/', rqf.parse(), (req, res, next) => { + req.sql.field('COUNT(DISTINCT docente.id_docente)', 'total') + .field("'Brasil'", 'name') + .field('docente.ano_censo', 'year') + .from('docente') + .join('turma', null, 'docente.turma_id=turma.id AND docente.ano_censo=turma.ano_censo') + .group('docente.ano_censo') + .order('docente.ano_censo') + .where('(docente.tipo_docente = 1 OR docente.tipo_docente = 5) AND \ + ((docente.tipo_turma_id >= 0 AND docente.tipo_turma_id <= 3 AND docente.tipo_turma_atendimento_id is NULL) \ + OR ((docente.tipo_turma_atendimento_id = 1 OR docente.tipo_turma_atendimento_id = 2) AND docente.tipo_turma_id is NULL)) \ + AND (docente.ano_censo <> 2009 or (docente.escola_estado_id <> 42 and docente.escola_estado_id <> 43) )'); // não devemos trazer SC em 2009. + + // if("education_level_mod" in req.dims) { + // req.hadEducationLevelMod = true; + // req.sql.where('docente.etapas_mod_ensino_segmento_id < 11'); + // } + + next(); +}, rqf.build(), query, addMissing(rqf), (req, res, next) => { + // Função criada para preencher valores faltantes no gráfico do indicador de + // formação em pós graduação do MapFOR. + if (req.dims.pos_training){ + var year = req.result[0].year; + var posTrainingIds = req.result.map(obj => { + if (year == obj.year) + return obj.pos_training_id + }).filter(num => num !== undefined) + + var missingValues = []; + for(let i = 1; i <= 4; ++i) { + if ( !posTrainingIds.includes(i) ){ + missingValues.push(i); + } + } + + for (let curYear = 2012; curYear <= 2020; ++curYear){ + for (let ptId of missingValues){ + req.result.push({ + total:0, + name:"Brasil", + year:curYear, + pos_training_id:ptId, + pos_training_name:id2str.posTraining(ptId) + }) + } + } + req.result.sort(sortYearPtid) + + } + next(); +}, id2str.transform(), response('teacher')); + +module.exports = teacherApp; diff --git a/src/libs/routes_v2/transport.js b/src/libs/routes_v2/transport.js new file mode 100644 index 00000000..74c1b095 --- /dev/null +++ b/src/libs/routes_v2/transport.js @@ -0,0 +1,400 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const transportApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +transportApp.use(cache('15 day')); + +transportApp.get('/year_range', (req, res, next) => { + req.sql.from('transporte') + .field('MIN(transporte.ano_censo)', 'start_year') + .field('MAX(transporte.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +transportApp.get('/years', (req, res, next) => { + req.sql.from('transporte') + .field('DISTINCT transporte.ano_censo', 'year'); + next(); +}, query, response('years')); + +transportApp.get('/adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.admDependency(i) + }); + }; + next(); +}, response('adm_dependency')); + +transportApp.get('/adm_dependency_detailed', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.admDependencyPriv(i) + }); + }; + next(); +}, response('adm_dependency_detailed')); + +transportApp.get('/location', (req, res, next) => { + req.result = [ + {id: 1, name: 'Urbana'}, + {id: 2, name: 'Rural'} + ]; + next(); +}, response('location')); + +transportApp.get('/rural_location', (req, res, next) => { + req.result = [ + {id: 1, name: "Urbana"}, + {id: 2, name: "Rural"}, + {id: 3, name: "Rural - Ãrea de assentamento"}, + {id: 4, name: "Rural - Terra indÃgena"}, + {id: 5, name: "Rural - Ãrea remanescente de quilombos"}, + {id: 6, name: "Rural - Unidade de uso sustentável"} + ]; + next(); +}, response('rural_location')); + +transportApp.get('/education_level_mod', (req, res, next) => { + req.result = [ + {id: null, name: 'Não classificada'}, + {id: 1, name: 'Creche'}, + {id: 2, name: 'Pré-Escola'}, + {id: 4, name: 'Ensino Fundamental - anos iniciais'}, + {id: 5, name: 'Ensino Fundamental - anos finais'}, + {id: 6, name: 'Ensino Médio'}, + {id: 7, name: 'Turmas multiseriadas e multietapas'}, + {id: 8, name: 'EJA - Ensino Fundamental'}, + {id: 9, name: 'EJA - Ensino Médio'}, + {id: 10, name: 'Educação Profissional'} + ]; + next(); +}, response('education_level_mod')); + +transportApp.get('/service_type', (req, res, next) => { + req.result = [ + {id: 0, name: 'Não se aplica'}, + {id: 1, name: 'Classe hospitalar'}, + {id: 2, name: 'Unidade de Atendimento Socioeducativo'}, + {id: 3, name: 'Unidade Prisional'}, + {id: 4, name: 'Atividade Complementar '}, + {id: 5, name: 'Atendimento Educacional Especializado (AEE)'} + ]; + next(); +}, response('service_type')); + +transportApp.get('/transportation_manager', (req, res, next) => { + req.result = [ + {id: null, name: 'Não classificada'}, + {id: 1, name: 'Estadual'}, + {id: 2, name: 'Municipal'}, + ]; + next(); +}, response('transportation_manager')); + +transportApp.get('/source', (req, res, next) => { + req.sql.from('fonte') + .field('fonte', 'source') + .where('tabela = \'matricula\''); + next(); +}, query, response('source')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'school', + table: 'escola', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: ['id', 'ano_censo'], + foreign: ['escola_id', 'ano_censo'], + foreignTable: 'transporte' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'transporte' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'municipio_id', + table: 'transporte' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'transporte' + } +}).addValue({ + name: 'state', + table: 'transporte', + tableField: ['estado_nome', 'estado_id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'estado_id', + table: 'transporte' + } +}).addValue({ + name: 'rural_location', + table: 'transporte', + tableField: 'localidade_area_rural', + resultField: 'rural_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'location', + table: 'transporte', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name:'adm_dependency', + table: 'transporte', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed', + table: 'transporte', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'transportation_manager', + table: 'transporte', + tableField: 'responsavel_transp', + resultField: 'transportation_manager_id', + where: { + relation: '=', + type: 'integer', + field: 'responsavel_transp' + } +}).addValue({ + name: 'education_level_mod', + table: 'transporte', + tableField: 'etapas_mod_ensino_segmento_id', + resultField: 'education_level_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'etapas_mod_ensino_segmento_id' + } +}).addValue({ + name: 'service_type', + table: 'transporte', + tableField: 'tipo', + resultField: 'service_type_id', + where: { + relation: '=', + type: 'integer', + field: 'tipo' + } +}).addValue({ + name: 'min_year', + table: 'transporte', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'transporte', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'year', + table: 'transporte', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}); + +transportApp.get('/', rqf.parse(), (req, res, next) => { + req.dims.year = true; + req.sql + .field('sum(transporte.total)', 'total') + .field("'Brasil'", 'name') + .from('transporte') + .where('transporte.transporte_id=0') + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.total = req.result; + req.resetSql(); + next(); +}, rqf.parse(), (req, res, next) => { + req.dims.year = true; + req.sql + .field('sum(transporte.total)', 'total') + .field("'Brasil'", 'name') + .from('transporte') + .where('transporte.transporte_id=1') + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + req.public_total = req.result; + req.resetSql(); + next(); + +}, rqf.parse(), (req, res, next) => { + req.dims.year = true; + req.sql + .field('sum(transporte.total)', 'total') + .field("'Brasil'", 'name') + .field('transporte.transporte_id', 'id') + .from('transporte') + .where('transporte.transporte_id>0') + .group('transporte.transporte_id') + .order('transporte.transporte_id') + next(); +}, rqf.build(), query, id2str.transform(), (req, res, next) => { + let transports = req.result; + + let results = []; + let obj = {}; + for (let i = 1; i < 13; i++) { + obj[id2str.transport(i)] = []; + } + + let i = 0 + while (i < transports.length) { + let result = []; + let j = 0; + let transport = transports[i]; + let totalArray = (transport.id == 1) ? req.total : req.public_total; + let match; + obj[id2str.transport(transport.id)] = result; + while (j < totalArray.length && i < transports.length) { + transport = transports[i]; + let transportTotal = totalArray[j]; + + let currentTransport = {}; + delete transport.id; + match = true; + Object.keys(transport).forEach(function(key) { + currentTransport[key] = transportTotal[key]; + if (key != 'total' && transport[key] != transportTotal[key]) { + match = false; + return; + } + }) + + if (match) { + currentTransport.partial = (match) ? transport.total : 0; + currentTransport.percentage = (match) ? transport.total/transportTotal.total * 100 : 0; + result.push(currentTransport); + i++; + j++; + } + else + j++; + } + } + results.push(obj) + req.result = results; + + next(); +}, response('transports')); + +module.exports = transportApp; diff --git a/src/libs/routes_v2/university.js b/src/libs/routes_v2/university.js new file mode 100644 index 00000000..be7fe771 --- /dev/null +++ b/src/libs/routes_v2/university.js @@ -0,0 +1,347 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const universityApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +const addMissing = require(`${libs}/middlewares/addMissing`); + +let rqf = new ReqQueryFields(); + +let rqfCount = new ReqQueryFields(); + +universityApp.use(cache('15 day')); + +universityApp.get('/upper_adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 7; ++i) { + req.result.push({ + id: i, + name: id2str.upperAdmDependency(i) + }); + }; + next(); +}, response('upper_adm_dependency')); + +universityApp.get('/years', (req, res, next) => { + req.sql.from('ies_ens_superior') + .field('DISTINCT ies_ens_superior.ano_censo', 'year') + next(); +}, query, response('years')); + +universityApp.get('/year_range', (req, res, next) => { + req.sql.from('ies_ens_superior') + .field('MIN(ies_ens_superior.ano_censo)', 'start_year') + .field('MAX(ies_ens_superior.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +universityApp.get('/academic_organization', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 5; ++i) { + req.result.push({ + id: i, + name: id2str.academicOrganization(i) + }); + }; + next(); +}, response('academic_organization')); + +universityApp.get('/capital', (req, res, next) => { + req.result = []; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.booleanVariable(i) + }); + }; + next(); +}, response('capital')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'id', + table: 'ies_ens_superior', + tableField: 'cod_ies', + resultField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'cod_ies' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_municipio_ies', + table: 'ies_ens_superior' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_ies', + foreignTable: 'ies_ens_superior' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_uf_ies', + table: 'ies_ens_superior' + }, + join: { + primary: 'id', + foreign: 'cod_uf_ies', + foreignTable: 'ies_ens_superior' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: 'LIKE', + type: 'string', + field: 'id' + }, + join: { + primary: 'nome', + foreign: 'nome_regiao_ies', + foreignTable: 'ies_ens_superior' + } +}).addValue({ + name: 'year', + table: 'ies_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo', + table: 'ies_ens_superior' + } +}).addField({ + name: 'search', + field: true, + where: true +}).addValueToField({ + name: 'city_name', + table: 'municipio', + tableField: 'nome', + resultField: 'city_name', + dontGroup: true, + where: { + relation: 'LIKE', + type: 'string', + field: 'nome' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_ies', + foreignTable: 'ies_ens_superior' + } +}, 'search') +.addValueToField({ + name: 'state_name', + table: 'estado', + tableField: 'nome', + resultField: 'state_name', + dontGroup: true, + where: { + relation: 'LIKE', + type: 'string', + field: 'sigla' + }, + join: { + primary: 'id', + foreign: 'cod_uf_ies', + foreignTable: 'ies_ens_superior' + } +}, 'search'); + + +rqfCount.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_municipio_ies', + table: 'ies_ens_superior' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_ies', + foreignTable: 'ies_ens_superior' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: 'LIKE', + type: 'string', + field: 'id' + }, + join: { + primary: 'nome', + foreign: 'nome_regiao_ies', + foreignTable: 'ies_ens_superior' + } + +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_uf_ies', + table: '@' + }, + join: { + primary: 'id', + foreign: 'cod_uf_ies', + foreignTable: '@' + } +}).addValue({ + name: 'upper_adm_dependency', + table: 'ies_ens_superior', + tableField: 'par_categoria_administrativa', + resultField: 'upper_adm_dependency_id', + where: { + relation: '=', + type: 'integer', + table: 'ies_ens_superior', + field: 'cod_categoria_administrativa' + } +}).addValue({ + name: 'academic_organization', + table: 'ies_ens_superior', + tableField: 'cod_organizacao_academica', + resultField: 'academic_organization_id', + where: { + relation: '=', + type: 'integer', + table: 'ies_ens_superior', + field: 'cod_organizacao_academica' + } +}).addValue({ + name: 'capital', + table: 'ies_ens_superior', + tableField: 'tfd_capital_ies', + resultField: 'capital_id', + where: { + relation: '=', + type: 'integer', + table: 'ies_ens_superior', + field: 'capital_ies' + } +}); + +universityApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('ies_ens_superior') + .field('ies_ens_superior.cod_ies', 'id') + .field('ies_ens_superior.ano_censo', 'year') + .field('ies_ens_superior.nome_ies', 'name') + .field('ies_ens_superior.cod_uf_ies', 'state_id') + .field('ies_ens_superior.cod_municipio_ies', 'city_id') + .field('ies_ens_superior.cod_uf_ies/10', 'region_id'); + next(); + +}, query, response('university')); + +universityApp.get('/count', rqfCount.parse(), (req, res, next) => { + req.sql.field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('ies_ens_superior.ano_censo', 'year') + .from('ies_ens_superior') + .group('ies_ens_superior.ano_censo') + .order('ies_ens_superior.ano_censo') + + next(); +}, rqfCount.build(), query, addMissing(rqfCount), id2str.transform(), response('university')); + +module.exports = universityApp; diff --git a/src/libs/routes_v2/universityEnrollment.js b/src/libs/routes_v2/universityEnrollment.js new file mode 100644 index 00000000..8df5aded --- /dev/null +++ b/src/libs/routes_v2/universityEnrollment.js @@ -0,0 +1,848 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const universityEnrollmentApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +universityEnrollmentApp.get('/years', (req, res, next) => { + req.sql.from('aluno_ens_superior') + .field('DISTINCT aluno_ens_superior.ano_censo', 'year') + .where('aluno_ens_superior.ano_censo > 2010'); + next(); +}, query, response('years')); + +universityEnrollmentApp.get('/year_range', (req, res, next) => { + req.sql.from('aluno_ens_superior') + .field('MIN(aluno_ens_superior.ano_censo)', 'start_year') + .field('MAX(aluno_ens_superior.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +universityEnrollmentApp.get('/academic_organization', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 5; ++i) { + req.result.push({ + id: i, + name: id2str.academicOrganization(i) + }); + }; + next(); +}, response('academic_organization')); + +universityEnrollmentApp.get('/upper_adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 7; ++i) { + req.result.push({ + id: i, + name: id2str.upperAdmDependency(i) + }); + }; + next(); +}, response('upper_adm_dependency')); + +universityEnrollmentApp.get('/ocde_geral', (req, res, next) => { + req.result = []; + for(let i = 0; i <= 8; ++i) { + req.result.push({ + id: i, + name: id2str.ocdeGeral(i) + }); + }; + next(); +}, response('ocde_geral')); + + +universityEnrollmentApp.get('/finish', (req, res, next) => { + req.result = [] + for (let i = 0; i <= 1; ++i){ + req.result.push({ + id: i, + name: id2str.finishUniversity(i) + }) + } + next(); + +}, response('finish')); + +universityEnrollmentApp.get('/ocde_specific', (req, res, next) => { + req.result = []; + const defaultCase = null; + for(let i = 1; i <= 86; ++i) { + let obj = { + id: i, + name: id2str.ocdeSpecific(i) + }; + if (obj.name !== id2str.ocdeSpecific(defaultCase)){ + req.result.push(obj); + } + }; + req.result.push({ + id: defaultCase, + name: id2str.ocdeSpecific(defaultCase) + }); + next(); +}, response('ocde_specific')); + +universityEnrollmentApp.get('/ocde_detailed', (req, res, next) => { + req.result = []; + const defaultCase = null; + for(let i = 142; i <= 863; ++i) { + let obj = { + id: i, + name: id2str.ocdeDetailed(i) + }; + if (obj.name !== id2str.ocdeDetailed(defaultCase)){ + req.result.push(obj); + } + }; + req.result.push({ + id: defaultCase, + name: id2str.ocdeDetailed(defaultCase) + }); + next(); +}, response('ocde_detailed')); + +universityEnrollmentApp.get('/cine_geral', (req, res, next) => { + req.result = []; + for(let i = 0; i <= 10; ++i) { + req.result.push({ + id: i, + name: id2str.cineGeral(i) + }); + }; + next(); +}, response('cine_geral')); + +universityEnrollmentApp.get('/cine_specific', (req, res, next) => { + req.result = []; + const defaultCase = null; + for(let i = 1; i <= 104; ++i) { + let obj = { + id: i, + name: id2str.cineSpecific(i) + }; + if (obj.name !== id2str.cineSpecific(defaultCase)){ + req.result.push(obj); + } + }; + req.result.push({ + id: defaultCase, + name: id2str.cineSpecific(defaultCase) + }); + next(); +}, response('cine_specific')); + +universityEnrollmentApp.get('/cine_detailed', (req, res, next) => { + req.result = []; + const defaultCase = null; + for(let i = 11; i <= 1041; ++i) { + let obj = { + id: i, + name: id2str.cineDetailed(i) + }; + if (obj.name !== id2str.cineDetailed(defaultCase)){ + req.result.push(obj); + } + }; + req.result.push({ + id: defaultCase, + name: id2str.cineDetailed(defaultCase) + }); + next(); +}, response('cine_detailed')); + +universityEnrollmentApp.get('/upper_turn', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.upperTurn("null") + }]; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.upperTurn(i) + }); + }; + next(); +}, response('upper_turn')); + +universityEnrollmentApp.get('/student_deficiency', (req, res, next) => { + req.result = [{ + id: 9, + name: id2str.studentDeficiency(9) + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.studentDeficiency(i) + }); + }; + next(); +}, response('student_deficiency')); + +universityEnrollmentApp.get('/ethnic_group_ies', (req, res, next) => { + req.result = [{ + id: 9, + name: id2str.ethnicGroupIES(9) + }]; + for(let i = 0; i <=5; ++i) { + req.result.push({ + id: i, + name: id2str.ethnicGroupIES(i) + }); + } + next(); +}, response('ethnic_group_ies')); + +universityEnrollmentApp.get('/school_type', (req, res, next) => { + req.result = [{ + id: 9, + name: id2str.schoolType(9) + }]; + for(let i = 1; i <= 2; ++i) { + req.result.push({ + id: i, + name: id2str.schoolType(i) + }); + }; + next(); +}, response('school_type')); + +universityEnrollmentApp.get('/university', (req, res, next) => { + req.sql.from('aluno_ens_superior') + .field('DISTINCT aluno_ens_superior.nome_ies', 'nome') + .field('aluno_ens_superior.cod_ies', 'cod') + next(); +}, query, response('university')); + +universityEnrollmentApp.get('/academic_level', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.academicLevel(i) + }); + }; + next(); +}, response('academic_level')); + +universityEnrollmentApp.get('/gender_ies', function (req, res, next) { + req.result = []; + for (var i = 1; i <= 2; ++i) { + req.result.push({ + id: i, + name: id2str.genderIES(i) + }); + }; + next(); +}, response('gender_ies')); + +universityEnrollmentApp.get('/upper_education_mod', function (req, res, next) { + req.result = []; + for (var i = 1; i <= 3; ++i) { + req.result.push({ + id: i, + name: id2str.upperEducationMod(i) + }); + }; + next(); +}, response('upper_education_mod')); + +universityEnrollmentApp.get('/age_student_code', function (req, res, next) { + req.result = []; + for (var i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.ageStudentCode(i) + }); + }; + next(); +}, response('age_student_code')); + + +universityEnrollmentApp.get('/enter_situation/student_enter_situation', function (req, res, next) { + req.result = []; + for (var i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.enterSituation(i) + }); + }; + next(); +}, response('student_enter_situation')); + +universityEnrollmentApp.get('/enrollment_situation/student_enter_situation', function (req, res, next) { + req.result = []; + for (var i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.enterSituation(i) + }); + }; + next(); +}, response('student_enter_situation')); + + +universityEnrollmentApp.get('/enter_situation/student_enrollment_situation', function (req, res, next) { + req.result = []; + for (var i = 1; i <= 3; ++i) { + req.result.push({ + id: i, + name: id2str.enrollmentSituation(i) + }); + }; + next(); +}, response('student_enrollment_situation')); + +universityEnrollmentApp.get('/university', (req, res, next) => { + req.sql.from('aluno_ens_superior') + .field('DISTINCT aluno_ens_superior.nome_ies', 'nome') + .field('aluno_ens_superior.cod_ies', 'cod') + next(); +}, query, response('university')); + +universityEnrollmentApp.get('/localoffer', (req, res, next) => { + req.sql.from('localoferta_ens_superior', 'l') + .field('DISTINCT l.nome', 'localoffer_name') + .field('l.cod_local_oferta', 'localoffer_id'); + next(); +}, query, response('localoffer')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'localoferta_cod_municipio', + table: 'localoferta_ens_superior_matricula' + }, + join: { + primary: 'id', + foreign: 'localoferta_cod_municipio', + foreignTable: 'localoferta_ens_superior_matricula' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'localoferta_cod_uf', + table: 'localoferta_ens_superior_matricula' + }, + join: { + primary: 'id', + foreign: 'localoferta_cod_uf', + foreignTable: 'localoferta_ens_superior_matricula' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'localoferta_cod_regiao', + table: 'localoferta_ens_superior_matricula' + }, + join: { + primary: 'id', + foreign: 'localoferta_cod_regiao', + foreignTable: 'localoferta_ens_superior_matricula' + } +}).addValue({ + name: 'localoffer', + table: 'localoferta_ens_superior_matricula', + tableField: ['cod_local_oferta', 'localoferta_nome'], + resultField: ['localoffer_id', 'localoffer_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_local_oferta' + } +}).addValue({ + name: 'campi', + table: 'localoferta_ens_superior_matricula', + tableField: ['cod_local_oferta', 'localoferta_nome'], + resultField: ['campi_id', 'campi_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_local_oferta' + } +}).addValue({ + name: 'university', + table: '@', + tableField: ['cod_ies', 'nome_ies'], + resultField: ['university_id', 'university_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_ies' + } +}).addValue({ + name: 'universityLocalOffer', + table: '@', + tableField: ['cod_ies', 'nome_ies'], + resultField: ['university_id', 'university_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_ies' + } +}).addValue({ + name:'upper_adm_dependency', + table: '@', + tableField: 'par_categoria_administrativa', + resultField: 'upper_adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'par_categoria_administrativa' + } +}).addValue({ + name:'academic_organization', + table: '@', + tableField: 'cod_organizacao_academica', + resultField: 'academic_organization_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_organizacao_academica' + } +}).addValue({ + name:'ocde_specific', + table: '@', + tableField: ['par_cod_ocde_area_especifica'], + resultField: ['ocde_specific_id'], + where: { + relation: '=', + type: 'integer', + field: 'par_cod_ocde_area_especifica' + } +}).addValue({ + name:'ocde_geral', + table: '@', + tableField: ['par_cod_ocde_area_geral'], + resultField: ['ocde_geral_id'], + where: { + relation: '=', + type: 'integer', + field: 'par_cod_ocde_area_geral' + } +}).addValue({ + name:'ocde_detailed', + table: '@', + tableField: ['par_cod_ocde_area_detalhada'], + resultField: ['ocde_detailed_id'], + where: { + relation: '=', + type: 'integer', + field: 'par_cod_ocde_area_detalhada' + } +}).addValue({ + name:'cine_specific', + table: '@', + tableField: ['cod_cine_area_especifica', 'nome_cine_area_especifica'], + resultField: ['cine_specific_id', 'cine_specific_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_cine_area_especifica' + } +}).addValue({ + name:'cine_geral', + table: '@', + tableField: ['cod_cine_area_geral', 'nome_cine_area_geral'], + resultField: ['cine_geral_id', 'cine_geral_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_cine_area_geral' + } +}).addValue({ + name:'cine_detailed', + table: '@', + tableField: ['cod_cine_area_detalhada', 'nome_cine_area_detalhada'], + resultField: ['cine_detailed_id', 'cine_detailed_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_cine_area_detalhada' + } +}).addValue({ + name:'academic_level', + table: '@', + tableField: 'cod_grau_academico', + resultField: 'academic_level_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_grau_academico' + } +}).addValue({ + name:'upper_education_mod', + table: '@', + tableField: 'cod_modalidade_ensino', + resultField: 'upper_education_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_modalidade_ensino' + } +}).addValue({ + name:'is_free', + table: '@', + tableField: 'gratuito', + resultField: 'is_free_id', + where: { + relation: '=', + type: 'boolean', + field: 'gratuito' + } +}).addValue({ + name:'night_time', + table: '@', + tableField: 'noturno_curso_t', + resultField: 'night_time_id', + where: { + relation: '=', + type: 'boolean', + field: 'noturno_curso_t' + } +}).addValue({ + name:'situation', + table: '@', + tableField: 'cod_situacao_curso', + resultField: 'situacao_curso_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_situacao_curso' + } +}).addValue({ + name:'finish', + table: '@', + tableField: 'concluinte', + resultField: 'finish_id', + where: { + relation: '=', + type: 'integer', + field: 'concluinte' + } +}).addValue({ + name:'year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'age_student_code', + table: '@', + tableField: 'idade_aluno_codigo', + resultField: 'age_student_code_id', + where: { + relation: '=', + type: 'integer', + field: 'idade_aluno_codigo' + } +}).addValue({ + name:'upper_turn', + table: '@', + tableField: 'cod_turno_aluno', + resultField: 'upper_turn_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_turno_aluno' + } +}).addValue({ + name:'ethnic_group_ies', + table: '@', + tableField: 'par_cod_cor_raca_aluno', + resultField: 'ethnic_group_ies_id', + where: { + relation: '=', + type: 'integer', + field: 'par_cod_cor_raca_aluno' + } +}).addValue({ + name:'student_deficiency', + table: '@', + tableField: 'par_aluno_deficiencia_transtorno_superdotacao', + resultField: 'student_deficiency_id', + where: { + relation: '=', + type: 'integer', + field: 'par_aluno_deficiencia_transtorno_superdotacao' + } +}).addValue({ + name:'school_type', + table: '@', + tableField: 'par_tipo_escola_ensino_medio', + resultField: 'school_type_id', + where: { + relation: '=', + type: 'integer', + field: 'par_tipo_escola_ensino_medio' + } +}).addValue({ + name: 'gender_ies', + table: '@', + tableField: 'par_genero_aluno', + resultField: 'gender_ies_id', + where: { + relation: '=', + type: 'integer', + field: 'par_genero_aluno' + } +}).addValue({ + name: 'mesoregion', + table: 'municipio', + tableField: ['nome_mesorregiao', 'mesorregiao_id'], + resultField: ['mesoregion_name', 'mesoregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'mesorregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'localoferta_cod_municipio', + foreignTable: 'localoferta_ens_superior_matricula' + } +}).addValue({ + name: 'microregion', + table: 'municipio', + tableField: ['nome_microrregiao', 'microrregiao_id'], + resultField: ['microregion_name', 'microregion_id'], + where: { + relation: '=', + type: 'integer', + field: 'microrregiao_id', + table: 'municipio' + }, + join: { + primary: 'id', + foreign: 'localoferta_cod_municipio', + foreignTable: 'localoferta_ens_superior_matricula' + } +}).addValue({ + name: 'course', + table: 'curso_ens_superior', + tableField: 'nome_curso', + resultField: 'course_name', + where:{ + relation: '=', + type: 'string', + table: 'curso_ens_superior', + field: 'nome_curso' + }, + join:{ + primary: ['ano_censo', 'cod_curso'], + foreign: ['ano_censo', 'cod_curso'], + foreignTable: 'localoferta_ens_superior_matricula' + } +}); + +universityEnrollmentApp.get('/', rqf.parse(), (req, res, next) => { + if ("localoffer" in req.dims) { + if ("university" in req.dims || "universityLocalOffer" in req.dims) { + req.sql.from('localoferta_ens_superior_matricula') + .field('curso_ens_superior.ano_censo', 'year') + .field('COUNT(localoferta_ens_superior.cod_local_oferta)', 'total') + .group('localoferta_ens_superior_matricula.ano_censo') + .where('localoferta_ens_superior_matricula.cod_aluno_situacao = 2 OR localoferta_ens_superior_matricula.cod_aluno_situacao = 6 OR localoferta_ens_superior_matricula.matriculado = 1') + .where('localoferta_ens_superior_matricula.cod_nivel_academico = 1') + .order('localoferta_ens_superior_matricula.ano_censo') + .order('localoferta_ens_superior.cod_local_oferta'); + } else { + req.sql.from('localoferta_ens_superior_matricula') + .field('localoferta_ens_superior_matricula.ano_censo', 'year') + .field('COUNT(*)', 'total') + .field('localoferta_ens_superior_matricula.cod_ies', 'university_id') + .field('localoferta_ens_superior_matricula.nome_ies', 'university_name') + .where('localoferta_ens_superior_matricula.cod_aluno_situacao = 2 OR localoferta_ens_superior_matricula.cod_aluno_situacao = 6 OR localoferta_ens_superior_matricula.matriculado = 1') + .where('localoferta_ens_superior_matricula.cod_nivel_academico = 1') + .group('localoferta_ens_superior_matricula.ano_censo') + .group('localoferta_ens_superior_matricula.cod_ies') + .group('localoferta_ens_superior_matricula.nome_ies') + .order('localoferta_ens_superior_matricula.ano_censo') + .order('localoferta_ens_superior_matricula.cod_local_oferta'); + } + } else if (("state" in req.dims) || ("city" in req.dims) || ("region" in req.dims) || ("mesoregion" in req.dims) || ("microregion" in req.dims) || + ("state" in req.filter) || ("city" in req.filter) || ("region" in req.filter) || ("mesoregion" in req.filter) || ("microregion" in req.filter)) { + req.sql.from('localoferta_ens_superior_matricula') + .field('DISTINCT COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('localoferta_ens_superior_matricula.ano_censo', 'year') + .where('localoferta_ens_superior_matricula.cod_aluno_situacao = 2 OR localoferta_ens_superior_matricula.cod_aluno_situacao = 6 OR localoferta_ens_superior_matricula.matriculado = 1') + .where('localoferta_ens_superior_matricula.cod_nivel_academico = 1') + .group('localoferta_ens_superior_matricula.ano_censo') + .order('localoferta_ens_superior_matricula.ano_censo') + } else if ("university" in req.dims || "universityLocalOffer" in req.dims) { + req.sql.from('aluno_ens_superior') + .field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('aluno_ens_superior.ano_censo', 'year') + .group('aluno_ens_superior.cod_ies') + .group('aluno_ens_superior.ano_censo') + .where('aluno_ens_superior.cod_aluno_situacao = 2 OR aluno_ens_superior.cod_aluno_situacao = 6 OR aluno_ens_superior.matriculado = 1') + .where('aluno_ens_superior.cod_nivel_academico = 1') + .order('aluno_ens_superior.cod_ies') + .order('aluno_ens_superior.ano_censo') + } else { + req.sql.from('localoferta_ens_superior_matricula') + .field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('localoferta_ens_superior_matricula.ano_censo', 'year') + .where('localoferta_ens_superior_matricula.cod_aluno_situacao = 2 OR localoferta_ens_superior_matricula.cod_aluno_situacao = 6 OR localoferta_ens_superior_matricula.matriculado = 1') + .where('localoferta_ens_superior_matricula.cod_nivel_academico = 1') + .group('localoferta_ens_superior_matricula.ano_censo') + .order('localoferta_ens_superior_matricula.ano_censo') + } + next(); +}, rqf.build(), query, (req, res, next) =>{ console.log(req.sql.toString()); next()}, id2str.transform(), addMissing(rqf), (req, res, next) => { + if ('course' in req.dims){ + var total_course = req.result.reduce((total, cur) => {return total += cur.total}, 0) + for (var course of req.result){ + course.percentage = Number((( course.total / total_course ) * 100).toFixed(2)) + } + } + next(); +}, response('universityEnrollment')); + +universityEnrollmentApp.get('/enter_situation', rqf.parse(), (req, res, next) => { + req.sql.from('localoferta_ens_superior_matricula') + .field('SUM(CASE WHEN localoferta_ens_superior_matricula.cod_aluno_situacao=2 AND localoferta_ens_superior_matricula.ingressante=1 THEN 1 ELSE 0 END)', 'cursando') + .field('SUM(CASE WHEN localoferta_ens_superior_matricula.cod_aluno_situacao=6 AND localoferta_ens_superior_matricula.ingressante=1 THEN 1 ELSE 0 END)', 'concluinte') + .field('SUM(CASE WHEN (localoferta_ens_superior_matricula.cod_aluno_situacao=4 OR localoferta_ens_superior_matricula.cod_aluno_situacao=5 OR localoferta_ens_superior_matricula.cod_aluno_situacao=7) AND localoferta_ens_superior_matricula.ingressante=1 THEN 1 ELSE 0 END)', 'evadido') + .field('SUM(CASE WHEN localoferta_ens_superior_matricula.cod_aluno_situacao=3 AND localoferta_ens_superior_matricula.ingressante=1 THEN 1 ELSE 0 END)', 'trancado') + .field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('localoferta_ens_superior_matricula.ano_censo', 'year') + .where('localoferta_ens_superior_matricula.cod_nivel_academico=1') + .where('localoferta_ens_superior_matricula.cod_grau_academico=2 OR localoferta_ens_superior_matricula.cod_grau_academico=4') + .group('localoferta_ens_superior_matricula.ano_censo') + .order('localoferta_ens_superior_matricula.ano_censo') + next() +}, rqf.build(), query, (req, res, next) => { + for (var res of req.result){ + res.cursando = Number(res.cursando); + res.concluinte = Number(res.concluinte); + res.evadido = Number(res.evadido); + res.trancado = Number(res.trancado); + res.total = res.cursando + res.concluinte + res.evadido + res.trancado + res.taxa_evasao = Number( ((res.evadido/res.total) * 100).toFixed(2) ) + } + next(); +}, id2str.transform(), response('enterSituation')); + +universityEnrollmentApp.get('/enrollment_situation', rqf.parse(), (req, res, next) => { + req.sql.from('localoferta_ens_superior_matricula') + .field('SUM(CASE WHEN localoferta_ens_superior_matricula.cod_aluno_situacao=2 THEN 1 ELSE 0 END)', 'cursando') + .field('SUM(CASE WHEN localoferta_ens_superior_matricula.cod_aluno_situacao=6 THEN 1 ELSE 0 END)', 'concluinte') + .field('SUM(CASE WHEN (localoferta_ens_superior_matricula.cod_aluno_situacao=4 OR localoferta_ens_superior_matricula.cod_aluno_situacao=5 OR localoferta_ens_superior_matricula.cod_aluno_situacao=7) THEN 1 ELSE 0 END)', 'evadido') + .field('SUM(CASE WHEN localoferta_ens_superior_matricula.cod_aluno_situacao=3 THEN 1 ELSE 0 END)', 'trancado') + .field('localoferta_ens_superior_matricula.ano_censo', 'year') + .field("'Brasil'", 'name') + .where('localoferta_ens_superior_matricula.cod_nivel_academico=1') + .where('localoferta_ens_superior_matricula.cod_grau_academico=2 OR localoferta_ens_superior_matricula.cod_grau_academico=4') + .group('localoferta_ens_superior_matricula.ano_censo') + .order('localoferta_ens_superior_matricula.ano_censo') + next() +}, rqf.build(),query, (req, res, next) => { + for (var res of req.result){ + res.cursando = Number(res.cursando); + res.concluinte = Number(res.concluinte); + res.evadido = Number(res.evadido); + res.trancado = Number(res.trancado); + res.total = res.cursando + res.concluinte + res.evadido + res.trancado + } + + next(); +}, id2str.transform(), response('enrollmentSituation')); + + + +module.exports = universityEnrollmentApp; diff --git a/src/libs/routes_v2/universityLocalOffer.js b/src/libs/routes_v2/universityLocalOffer.js new file mode 100644 index 00000000..535094c4 --- /dev/null +++ b/src/libs/routes_v2/universityLocalOffer.js @@ -0,0 +1,170 @@ +''/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const universityLocalOfferApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const request = require(`request`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +const addMissing = require(`${libs}/middlewares/addMissing`); + +let rqf = new ReqQueryFields(); + +universityLocalOfferApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_municipio', + table: 'localoferta_ens_superior' + }, + join: { + primary: 'id', + foreign: 'cod_municipio', + foreignTable: 'localoferta_ens_superior' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: 'LIKE', + type: 'string', + field: 'id' + }, + join: { + primary: 'nome', + foreign: 'nome_regiao_ies', + foreignTable: 'localoferta_ens_superior' + } + +}).addValue({ + name: 'min_year', + table: 'localoferta_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: 'localoferta_ens_superior', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'localoferta_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: 'localoferta_ens_superior', + field: 'ano_censo' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_uf', + table: 'localoferta_ens_superior' + }, + join: { + primary: 'id', + foreign: 'cod_uf', + foreignTable: 'localoferta_ens_superior' + } +}).addValueToField({ + name: 'university', + table: 'localoferta_ens_superior', + tableField: 'cod_ies', + resultField: 'university_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_ies', + table: 'localoferta_ens_superior' + } +}, 'filter').addValue({ + name: 'year', + table: 'localoferta_ens_superior', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '=', + type: 'integer', + table: 'localoferta_ens_superior', + field: 'ano_censo' + } +}); + + +universityLocalOfferApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('localoferta_ens_superior') + .field('distinct localoferta_ens_superior.cod_ies', 'id') + .field('localoferta_ens_superior.cod_local_oferta', 'localoffer_id') + .field('localoferta_ens_superior.ano_censo', 'year') + .field('ies_ens_superior.nome_ies', 'name') + .field('localoferta_ens_superior.nome', 'localoffer_name') + .field('localoferta_ens_superior.cod_uf', 'state_id') + .field('localoferta_ens_superior.cod_municipio', 'city_id') + .field('localoferta_ens_superior.cod_regiao', 'region_id') + .join('ies_ens_superior', null, 'localoferta_ens_superior.cod_ies=ies_ens_superior.cod_ies AND localoferta_ens_superior.ano_censo=ies_ens_superior.ano_censo') + .where('localoferta_ens_superior.nome IS NOT NULL AND ies_ens_superior.nome_ies IS NOT NULL'); + next(); + +}, query, response('universityLocalOfferApp')); + +module.exports = universityLocalOfferApp; diff --git a/src/libs/routes_v2/universityTeacher.js b/src/libs/routes_v2/universityTeacher.js new file mode 100644 index 00000000..f65a29b2 --- /dev/null +++ b/src/libs/routes_v2/universityTeacher.js @@ -0,0 +1,517 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const teacherEnrollmentApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const id2str = require(`${libs}/middlewares/id2str`); + +const addMissing = require(`${libs}/middlewares/addMissing`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +teacherEnrollmentApp.get('/years', (req, res, next) => { + req.sql.from('docente_ens_superior') + .field('DISTINCT docente_ens_superior.ano_censo', 'year'); + next(); +}, query, response('years')); + +teacherEnrollmentApp.get('/year_range', (req, res, next) => { + req.sql.from('docente_ens_superior') + .field('MIN(docente_ens_superior.ano_censo)', 'start_year') + .field('MAX(docente_ens_superior.ano_censo)', 'end_year'); + next(); +}, query, response('range')); + +teacherEnrollmentApp.get('/academic_organization', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 5; ++i) { + req.result.push({ + id: i, + name: id2str.academicOrganization(i) + }); + }; + next(); +}, response('academic_organization')); + +teacherEnrollmentApp.get('/upper_adm_dependency', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 7; ++i) { + req.result.push({ + id: i, + name: id2str.upperAdmDependency(i) + }); + }; + next(); +}, response('upper_adm_dependency')); + +teacherEnrollmentApp.get('/teacher_situation', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 6; ++i) { + req.result.push({ + id: i, + name: id2str.teacherSituation(i) + }); + }; + next(); +}, response('teacher_situation')); + +teacherEnrollmentApp.get('/work_regime', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.workRegime("null") + }]; + for(let i = 1; i <= 4; ++i) { + req.result.push({ + id: i, + name: id2str.workRegime(i) + }); + }; + next(); +}, response('work_regime')); + +teacherEnrollmentApp.get('/substitute', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.booleanVariable("null") + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.booleanVariable(i) + }); + }; + next(); +}, response('substitute')); + +teacherEnrollmentApp.get('/visitor', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.booleanVariable("null") + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.booleanVariable(i) + }); + }; + next(); +}, response('visitor')); + +teacherEnrollmentApp.get('/ead_teacher', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.booleanVariable("null") + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.booleanVariable(i) + }); + }; + next(); +}, response('ead_teacher')); + +teacherEnrollmentApp.get('/graduation_presential', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.booleanVariable("null") + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.booleanVariable(i) + }); + }; + next(); +}, response('graduation_presential')); + +teacherEnrollmentApp.get('/postgraduate_ead_teacher', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.booleanVariable("null") + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.booleanVariable(i) + }); + }; + next(); +}, response('postgraduate_ead_teacher')); + +teacherEnrollmentApp.get('/postgraduate_presential_teacher', (req, res, next) => { + req.result = [{ + id: "null", + name: id2str.booleanVariable("null") + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.booleanVariable(i) + }); + }; + next(); +}, response('postgraduate_presential_teacher')); + +teacherEnrollmentApp.get('/deficiency', (req, res, next) => { + req.result = [{ + id: 9, + name: id2str.studentDeficiency(9) + }]; + for(let i = 0; i <= 1; ++i) { + req.result.push({ + id: i, + name: id2str.studentDeficiency(i) + }); + }; + next(); +}, response('deficiency')); + +teacherEnrollmentApp.get('/ethnic_group_teacher_ies', (req, res, next) => { + req.result = [{ + id: 9, + name: id2str.ethnicGroupTeacherIES(9) + }]; + for(let i = 0; i <= 5; ++i) { + req.result.push({ + id: i, + name: id2str.ethnicGroupTeacherIES(i) + }); + }; + next(); +}, response('ethnic_group_teacher_ies')); + +teacherEnrollmentApp.get('/teacher_schooling', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 5; ++i) { + req.result.push({ + id: i, + name: id2str.teacherSchooling(i) + }); + }; + next(); +}, response('teacher_schooling')); + +teacherEnrollmentApp.get('/gender_ies', (req, res, next) => { + req.result = []; + for(let i = 1; i <= 2; ++i) { + req.result.push({ + id: i, + name: id2str.genderIES(i) + }); + }; + next(); +}, response('gender_ies')); + + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'min_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: '@', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + table: '@', + field: 'ano_censo' + } +}).addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_uf_ies', + table: '@' + }, + join: { + primary: 'id', + foreign: 'cod_uf_ies', + foreignTable: '@' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'cod_municipio_ies', + table: '@' + }, + join: { + primary: 'id', + foreign: 'cod_municipio_ies', + foreignTable: '@' + } +}).addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'cod_regiao_ies', + foreignTable: 'docente_ens_superior' + } +}).addValue({ + name: 'university', + table: 'docente_ens_superior', + tableField: ['cod_ies', 'nome_ies'], + resultField: ['university_id', 'university_name'], + where: { + relation: '=', + type: 'integer', + field: 'cod_ies' + } +}).addValue({ + name: 'upper_adm_dependency', + table: 'docente_ens_superior', + tableField: 'par_categoria_administrativa', + resultField: 'upper_adm_dependency_id', + where: { + relation: '=', + type: 'integer', + table: 'docente_ens_superior', + field: 'par_categoria_administrativa' + } +}).addValue({ + name: 'academic_organization', + table: 'docente_ens_superior', + tableField: 'cod_organizacao_academica', + resultField: 'academic_organization_id', + where: { + relation: '=', + type: 'integer', + table: 'docente_ens_superior', + field: 'cod_organizacao_academica' + } +}).addValue({ + name:'academic_level', + table: 'docente_ens_superior', + tableField: 'cod_grau_academico', + resultField: 'academic_level_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_grau_academico' + } +}).addValue({ + name:'upper_education_mod', + table: 'docente_ens_superior', + tableField: 'cod_modalidade_ensino', + resultField: 'upper_education_mod_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_modalidade_ensino' + } +}).addValue({ + name:'teacher_situation', + table: 'docente_ens_superior', + tableField: 'par_situacao_docente', + resultField: 'teacher_situation_id', + where: { + relation: '=', + type: 'integer', + field: 'par_situacao_docente' + } +}).addValue({ + name:'work_regime', + table: 'docente_ens_superior', + tableField: 'cod_regime_trabalho', + resultField: 'work_regime_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_regime_trabalho' + } +}).addValue({ + name:'substitute', + table: 'docente_ens_superior', + tableField: 'docente_substituto', + resultField: 'substitute_id', + where: { + relation: '=', + type: 'boolean', + field: 'docente_substituto' + } +}).addValue({ + name:'visitor', + table: 'docente_ens_superior', + tableField: 'docente_visitante', + resultField: 'visitor_id', + where: { + relation: '=', + type: 'boolean', + field: 'docente_visitante' + } +}).addValue({ + name:'ead_teacher', + table: 'docente_ens_superior', + tableField: 'ministra_aula_ead', + resultField: 'ead_teacher_id', + where: { + relation: '=', + type: 'boolean', + field: 'ministra_aula_ead' + } +}).addValue({ + name:'graduation_presential', + table: 'docente_ens_superior', + tableField: 'atua_atividade_graduacao_presencial', + resultField: 'graduation_presential_id', + where: { + relation: '=', + type: 'boolean', + field: 'atua_atividade_graduacao_presencial' + } +}).addValue({ + name:'postgraduate_ead_teacher', + table: 'docente_ens_superior', + tableField: 'atua_atividade_posgraduacao_distancia', + resultField: 'postgraduate_ead_teacher_id', + where: { + relation: '=', + type: 'boolean', + field: 'atua_atividade_posgraduacao_distancia' + } +}).addValue({ + name:'postgraduate_presential_teacher', + table: 'docente_ens_superior', + tableField: 'atua_atividade_posgraduacao_presencial', + resultField: 'postgraduate_presential_teacher_id', + where: { + relation: '=', + type: 'boolean', + field: 'atua_atividade_posgraduacao_presencial' + } +}).addValue({ + name:'teacher_schooling', + table: 'docente_ens_superior', + tableField: 'cod_escolaridade_docente', + resultField: 'teacher_schooling_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_escolaridade_docente' + } +}).addValue({ + name:'ethnic_group_teacher_ies', + table: 'docente_ens_superior', + tableField: 'cod_cor_raca_docente', + resultField: 'ethnic_group_teacher_ies_id', + where: { + relation: '=', + type: 'integer', + field: 'cod_cor_raca_docente' + } +}).addValue({ + name:'gender_ies', + table: 'docente_ens_superior', + tableField: 'sexo_docente', + resultField: 'gender_ies_id', + where: { + relation: '=', + type: 'integer', + field: 'sexo_docente' + } +}).addValue({ + name:'deficiency', + table: 'docente_ens_superior', + tableField: 'par_docente_deficiencia', + resultField: 'deficiency_id', + where: { + relation: '=', + type: 'integer', + field: 'par_docente_deficiencia' + } +}); + +teacherEnrollmentApp.get('/', rqf.parse(), (req, res, next) => { + + if ("university" in req.dims) { + req.sql.field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('docente_ens_superior.ano_censo', 'year') + .from('docente_ens_superior') + .group('docente_ens_superior.cod_ies') + .group('docente_ens_superior.ano_censo') + .order('docente_ens_superior.cod_ies') + .order('docente_ens_superior.ano_censo') + } + else { + req.sql.field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('docente_ens_superior.ano_censo', 'year') + .from('docente_ens_superior') + .group('docente_ens_superior.ano_censo') + .order('docente_ens_superior.ano_censo') + } + + next(); +}, rqf.build(), query, addMissing(rqf), id2str.transform(false), response('teacherEnrollment')); + +module.exports = teacherEnrollmentApp; diff --git a/src/libs/routes_v2/user.js b/src/libs/routes_v2/user.js new file mode 100644 index 00000000..7ff088ee --- /dev/null +++ b/src/libs/routes_v2/user.js @@ -0,0 +1,305 @@ +const express = require('express'); + +const userApp = express(); + +const libs = `${process.cwd()}/libs`; + +const config = require(`${libs}/config`); + +const log = require(`${libs}/log`)(module); + +const User = require(`${libs}/models/user`); + +const VerificationToken = require(`${libs}/models/verificationToken`); + +const ResetToken = require(`${libs}/models/resetToken`); + +const response = require(`${libs}/middlewares/response`); + +const email = require(`${libs}/middlewares/email`); + +const passport = require('passport'); + +function emailSyntax(email) { + const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + return regex.test(email); +} + +userApp.get('/schooling', (req, res, next) => { + req.result = [ + 'Não estudou', + 'Ensino Fundamental Incompleto', + 'Ensino Fundamental Completo', + 'Ensino Médio', + 'Graduação', + 'Mestrado', + 'Doutorado' + ]; + next(); +}, response('schooling')); + +userApp.get('/segment', (req, res, next) => { + req.result = [ + 'Gestores e equipe gestora das secretarias e ministério da Educação', + 'Gestores dos órgãos de planejamento e finanças (das três esferas de governo)', + 'Agentes do poder legislativo', + 'Agentes dos conselhos de educação', + 'Profissionais da educação', + 'Sindicato', + 'Sociedade civil interessada no financiamento da Educação Básica de qualidade', + 'Comunidade acadêmica', + 'Imprensa', + 'Outro [citar segmento]' + ]; + next(); +}, response('segment')); + +userApp.get('/role', (req, res, next) => { + req.result = [ + {"Gestores e equipe gestora das secretarias e ministério da Educação" : ["Dirigente municipal, estadual e federal", "Secretário do MEC", "Servidor da área de planejamento educacional", "Membro de associação de gestores (Ex. Undime, Consed, etc)", "Outro [citar função]"]}, + {"Gestores dos órgãos de planejamento e finanças (das três esferas de governo)" : ["Equipe gestora dos órgãos de planejamento", "Equipe gestora dos órgãos de finanças", "Outro [citar função]"]}, + {"Agentes do poder legislativo" : ["Parlamentar", "Assessor/a parlamentar", "Auditor/a dos tribunais de conta", "Conselheiro/a de tribunais de conta.", "Outro [citar função]"]}, + {"Agentes dos conselhos de educação" : ["Conselheiro/a municipais, estaduais e federais", "Conselheiro/a do Fundeb", "Outro [citar função]"]}, + {"Profissionais da educação" : ["Professor/a da Educação Básica", "Profissional da educação não-docente", "Outro [citar função]"]}, + {"Sindicato" : ["Agente de sindicatos"]}, + {"Sociedade civil interessada no financiamento da Educação Básica de qualidade" : ["Membro de fóruns educacionais", "Membro de ONGs e demais entidades sem fins lucrativos", "Estudante da educação básica e membro de entidades estudantis", "Pais e membros de entidades de pais", "Outro [citar função]"]}, + {"Comunidade acadêmica" : ["Pesquisador/a", "Estudantes de graduação e pós-graduação", "Representantes de entidades de pesquisa (Ex.: ANPED, ANPAE e FINEDUCA)", "Outro [citar função]"]}, + {"Imprensa" : ["Jornalista", "Outro [citar função]"]}, + {"Outro [citar segmento]" : []} + ] + next(); +}, response('role')); + +/* +userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, next) => { + User.find((err, users) => { + if(err) { + log.error(err); + return next(err); + } + + let result = []; + users.forEach((user) => { + let u = user.toObject(); + delete u.hashedPassword; + delete u.salt; + result.push(u); + }); + req.result = result; + next(); + }); +}, response('users')); +*/ + +userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => { + let user = req.user.toObject(); + delete user.hashedPassword; + delete user.salt; + req.result = user; + next(); +}, response('user')); + +userApp.get('/:id', (req, res, next) => { + User.findById(req.params.id, (err, user) => { + if(err) { + log.error(err); + return next(err); + } + if(!user) { + req.statusCode = 404; + next({msg: 'User not found'}); + } else { + let u = user.toObject; + delete u.hashedPassword; + delete u.salt; + req.result = u; + next(); + } + }); +}, response('user')); + +userApp.post('/', (req, res, next) => { + let user = new User({ + email: req.body.email, + password: req.body.password, + name: req.body.name, + nickname: req.body.nickname, + cpf: req.body.cpf, + cep: req.body.cep, + complement: req.body.complement, + address: req.body.address, + phone: req.body.phone, + schooling: req.body.schooling, + course: req.body.course, + segment: req.body.segment, + role: req.body.role, + institutionName: req.body.institutionName, + state: req.body.state, + city: req.body.city, + receiveEmails: false || req.body.receiveEmails, + origin: req.body.origin, + citesegment: req.body.citesegment, + citerole: req.body.citerole, + admin: false + }); + + if (typeof req.body.password === 'undefined' || !req.body.password) { + res.statusCode = 400; + return res.json({errors: ["O campo senha é obrigatório"]}); + } else { + user.save((err) => { + if(err) { + log.error(err); + let errors = []; + for(let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); + res.statusCode = 400; + return res.json({err, errors}); + } + + // Create verification token + let verificationToken = new VerificationToken({ + userId: user._id + }); + + verificationToken.createVerificationToken((err, token) => { + if(err) { + log.error(err); + return next(err); + } + let url = config.default.lde.url + '/verify'; + let text = `Olá, ${user.name}, seja bem vindo/a ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${token}`; + // Send confirmation email + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Confirme seu cadastro - Laboratório de Dados Educacionais", + text + } + email(mailOptions, (err, info) => { + if(err) { + log.error(err); + res.json({msg: 'User created'}); + } + if(info) { + log.info(`Message ${info.messageId} sent: ${info.response}`); + log.info(`Usuário ${user.email} foi criado`); + } + res.json({msg: 'User created'}); + }); + }); + }); + } + +}); + +userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => { + User.findById(req.params.id, (err, user) => { + if (err) { + log.error(err); + return next({err}); + } + + if(!user) { + res.statusCode = 404; + return next({err: { + message: 'Usuário não encontrado' + }}); + } + + user.email = req.body.email || user.email; + user.name = req.body.name || user.name; + user.nickname = req.body.nickname || user.nickname || user.name; + user.cep = req.body.cep || user.cep; + user.complement = req.body.complement || user.complement; + user.address = req.body.address || user.address; + user.phone = req.body.phone || user.phone; + user.schooling = req.body.schooling || user.schooling; + user.course = req.body.course || user.course; + user.segment = req.body.segment || user.segment; + user.role = req.body.role || user.role; + user.institutionName = req.body.institutionName || user.institutionName; + user.state = req.body.state || user.state; + user.city = req.body.city || user.city; + user.receiveEmails = req.body.receiveEmails || user.receiveEmails; + user.citesegment = req.body.citesegment || user.citesegment; + user.citerole = req.body.citerole || user.citerole; + + if ((req.body.password) && (req.body.newpassword)) { + if (req.body.password != req.body.newpassword) { + if (user.checkPassword(req.body.password)) { + user.password = req.body.newpassword; + } else { + res.statusCode = 500; + return res.json({error: { + message: 'A senha atual está incorreta' + }}); + } + } else { + res.statusCode = 500; + return res.json({error: { + message: 'A nova senha é a mesma da senha atual' + }}); + } + } + + user.save(err => { + if(err) { + log.error(err); + return next({message: 'Erro ao atualizar usuário'}); + } + let u = user.toObject(); + delete u.hashedPassword; + delete u.salt; + res.json({user: u}); + }) + }) +}); + +userApp.get('/reset/password', (req, res, next) => { + let emailAddress = req.query.email; + User.findOne({email: emailAddress}, (err, user)=> { + if(err) { + log.error(err); + let errors = []; + for(let errName in err.errors) { + errors.push(err.errors[errName].message); + } + res.statusCode = 400; + return res.json({err, errors}); + } + if (!user) { + res.statusCode = 404; + res.json({msg: "O usuário não está cadastrado"}); + } + else { + let resetToken = new ResetToken({ + userId: user._id + }); + resetToken.createResetToken((err, token) => { + if (err) { + log.error(err); + return next(err); + } + let url = config.default.lde.url + '/reset-password'; + let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${token}`; + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Redefinição de Senha - Laboratório de Dados Educacionais", + text + } + email(mailOptions, (err, info) => { + if(err) { + log.error(err); + res.json({msg: 'Undelivered Reset Password Mail'}); + } + log.info(`Message ${info.messageId} sent: ${info.response}`); + res.json({msg: 'Reset Password Mail Successfully Delivered'}); + }); + }) + } + }) +}) + +module.exports = userApp; diff --git a/src/libs/routes_v2/verifyToken.js b/src/libs/routes_v2/verifyToken.js new file mode 100644 index 00000000..d54f64aa --- /dev/null +++ b/src/libs/routes_v2/verifyToken.js @@ -0,0 +1,52 @@ +const express = require('express'); + +const verifyTokenApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const log = require(`${libs}/log`)(module); + +const VerificationToken = require(`${libs}/models/verificationToken`); + +const User = require(`${libs}/models/user`); + +verifyTokenApp.get('/:token', (req, res, next) => { + let token = req.params.token; + VerificationToken.findOne({token: token}, (err, vToken) => { + if(err) { + log.error(err); + return next(err); + } + if(!vToken) { + // TODO: generate new verification token + res.statusCode = 404; + return next({msg: 'Token not found', status:404}); + } + User.findById(vToken.userId, (err, user) => { + if(err) { + log.error(err); + next(err); + } + user.verified = true; + user.save((err) => { + if(err) { + log.error(err); + next(err); + } + }); + let u = user.toObject(); + delete u.salt; + delete u.hashedPassword; + vToken.verified = true; + vToken.save((err) => { + if(err) { + log.error(err); + next(err); + } + }); + res.json({msg: 'User verified', user: u}); + }); + }); +}); + +module.exports = verifyTokenApp; -- GitLab From bf9af7457d8fe8af3430ebc292067fa23d630eba Mon Sep 17 00:00:00 2001 From: ppc19 <ppc19@inf.ufpr.br> Date: Wed, 8 Mar 2023 09:25:29 -0300 Subject: [PATCH 055/123] add adm dependency data do school dim --- src/libs/routes_v2/classroomCount.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 4f76bed3..95e1d693 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -116,8 +116,8 @@ rqf.addField({ }, 'dims').addValueToField({ name: 'school', table: 'escola', - tableField: ['nome_escola', 'id'], - resultField: ['school_name', 'school_id'], + tableField: ['nome_escola', 'id', 'dependencia_adm_id'], // Dado de dependencia administrativa sempre deve ser retornado com escola + resultField: ['school_name', 'school_id', 'adm_dependcy_id'], where: { relation: '=', type: 'integer', -- GitLab From 7c3dd69878604323f434bf673f0722ccc676b90b Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Wed, 8 Mar 2023 09:54:14 -0300 Subject: [PATCH 056/123] adm_dependency dim added in classroom count --- src/libs/routes_v2/classroomCount.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 95e1d693..59fc53c8 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -117,7 +117,7 @@ rqf.addField({ name: 'school', table: 'escola', tableField: ['nome_escola', 'id', 'dependencia_adm_id'], // Dado de dependencia administrativa sempre deve ser retornado com escola - resultField: ['school_name', 'school_id', 'adm_dependcy_id'], + resultField: ['school_name', 'school_id', 'adm_dependency_id'], where: { relation: '=', type: 'integer', @@ -432,6 +432,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { if (req.dims.school){ obj.school_id = integral_time.school_id obj.school_name = integral_time.school_name + obj.adm_dependency_id = integral_time.adm_dependency_id } req.integral_time[code] = obj currentCodeObj = obj; @@ -517,7 +518,8 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }; if (req.dims.school){ obj.school_id = classroom.school_id, - obj.school_name = classroom.school_name + obj.school_name = classroom.school_name, + obj.adm_dependency_id = classroom.adm_dependency_id } if (req.teacherCalc) obj.percentage_teacher_career = []; -- GitLab From 2bebadbe91fa97e6440567551ec2eff732c09686 Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Wed, 8 Mar 2023 10:06:58 -0300 Subject: [PATCH 057/123] adm_dependency_name added in classroom count route --- src/libs/routes_v2/classroomCount.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 59fc53c8..0af32828 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -433,6 +433,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { obj.school_id = integral_time.school_id obj.school_name = integral_time.school_name obj.adm_dependency_id = integral_time.adm_dependency_id + obj.adm_dependency_name = integral_time.adm_dependency_name } req.integral_time[code] = obj currentCodeObj = obj; @@ -519,7 +520,8 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { if (req.dims.school){ obj.school_id = classroom.school_id, obj.school_name = classroom.school_name, - obj.adm_dependency_id = classroom.adm_dependency_id + obj.adm_dependency_id = classroom.adm_dependency_id, + obj.adm_dependency_name = classroom.adm_dependency_name } if (req.teacherCalc) obj.percentage_teacher_career = []; -- GitLab From 628bb714c7f6a559fe67d08236a8b4f609f57be6 Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Mon, 6 Mar 2023 11:26:46 -0300 Subject: [PATCH 058/123] filter added --- src/libs/routes_v1/school.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libs/routes_v1/school.js b/src/libs/routes_v1/school.js index 73b765e2..cbb1b289 100644 --- a/src/libs/routes_v1/school.js +++ b/src/libs/routes_v1/school.js @@ -308,6 +308,16 @@ rqf.addField({ type: 'integer', field: 'localizacao_diferenciada_par' } +}).addValue({ + name: 'adm_dependency', + table: 'escola', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } }); rqfCount.addField({ -- GitLab From bcec2ad0517ffa21b94bbd55b04d842df801ab3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 6 Mar 2023 10:26:06 -0300 Subject: [PATCH 059/123] Add reqBody middleware processing to school route in v2 --- src/libs/routes_v2/school.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libs/routes_v2/school.js b/src/libs/routes_v2/school.js index 172361c1..2c60d9c0 100644 --- a/src/libs/routes_v2/school.js +++ b/src/libs/routes_v2/school.js @@ -16,6 +16,8 @@ const id2str = require(`${libs}/middlewares/id2str`); const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); +const ReqBody = require(`${libs}/middlewares/reqBody`); + const request = require(`request`); const config = require(`${libs}/config`); @@ -28,6 +30,7 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i let rqf = new ReqQueryFields(); let rqfCount = new ReqQueryFields(); +let reqBody = new ReqBody(); // Return location schoolApp.get('/year_range', cache('15 day'), (req, res, next) => { @@ -655,11 +658,14 @@ schoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { next(); }, query, response('school')); -schoolApp.get('/count', cache('15 day'), rqfCount.parse(), (req, res, next) => { +schoolApp.get('/count', cache('15 day'), rqfCount.parse(), reqBody.parse(), (req, res, next) => { let arrang = ["arranjo_creche", "arranjo_pre", "arranjo_fundamental_ai", "arranjo_fundamental_af", "arranjo_multietapa", "arranjo_ensino_medio", "ensino_eja", "educacao_profissional", "ensino_especial"]; + if (!req.hasMetrics) { + req.sql.field('COUNT(escola.id)', 'total'); + } + req.sql.from('escola') - .field('COUNT(escola.id)', 'total') .field("'Brasil'", 'name') .field('escola.ano_censo', 'year') .group('escola.ano_censo') -- GitLab From 9bdcd5ebe534c4264fc0574af1e64d7f4e318584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 7 Mar 2023 10:21:30 -0300 Subject: [PATCH 060/123] Add v2 school infrastructure route --- src/libs/routes_v1/school.js | 30 ++++ src/libs/routes_v2/school.js | 157 ++++++++++-------- src/libs/routes_v2/schoolInfrastructure.js | 180 ++++++++++----------- 3 files changed, 212 insertions(+), 155 deletions(-) diff --git a/src/libs/routes_v1/school.js b/src/libs/routes_v1/school.js index cbb1b289..768325c3 100644 --- a/src/libs/routes_v1/school.js +++ b/src/libs/routes_v1/school.js @@ -261,6 +261,36 @@ rqf.addField({ field: 'ano_censo', table: 'escola' } +}).addValue({ + name: 'min_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'escola', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'adm_dependency', + table: 'escola', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } }).addField({ name: 'search', field: true, diff --git a/src/libs/routes_v2/school.js b/src/libs/routes_v2/school.js index 2c60d9c0..54126d80 100644 --- a/src/libs/routes_v2/school.js +++ b/src/libs/routes_v2/school.js @@ -34,22 +34,22 @@ let reqBody = new ReqBody(); // Return location schoolApp.get('/year_range', cache('15 day'), (req, res, next) => { - req.sql.from('escola') - .field('MIN(escola.ano_censo)', 'start_year') - .field('MAX(escola.ano_censo)', 'end_year'); + req.sql.from('escola_agregada') + .field('MIN(escola_agregada.ano_censo)', 'start_year') + .field('MAX(escola_agregada.ano_censo)', 'end_year'); next(); }, query, response('range')); schoolApp.get('/years', cache('15 day'), (req, res, next) => { - req.sql.from('escola'). - field('DISTINCT escola.ano_censo', 'year'); + req.sql.from('escola_agregada'). + field('DISTINCT escola_agregada.ano_censo', 'year'); next(); }, query, response('years')); schoolApp.get('/source', (req, res, next) => { req.sql.from('fonte') .field('fonte', 'source') - .where('tabela = \'escola\''); + .where('tabela = \'escola_agregada\''); next(); }, query, response('source')); @@ -214,7 +214,7 @@ rqf.addField({ where: true }).addValue({ name: 'id', - table: 'escola', + table: 'escola_agregada', tableField: 'id', where: { relation: '=', @@ -230,12 +230,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'state', @@ -246,23 +246,53 @@ rqf.addField({ relation: '=', type: 'integer', field: 'estado_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { relation: '=', type: 'integer', field: 'ano_censo', - table: 'escola' + table: 'escola_agregada' + } +}).addValue({ + name: 'min_year', + table: 'escola_agregada', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '>=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'max_year', + table: 'escola_agregada', + tableField: 'ano_censo', + resultField: 'year', + where: { + relation: '<=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'adm_dependency', + table: 'escola_agregada', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' } }).addValue({ name: 'min_year', @@ -302,7 +332,7 @@ rqf.addField({ join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'search') .addValueToField({ @@ -319,11 +349,11 @@ rqf.addField({ join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'search').addValue({ name: 'diff_location', - table: 'escola', + table: 'escola_agregada', tableField: 'localizacao_diferenciada_par', resultField: 'diff_location_id', where: { @@ -343,7 +373,7 @@ rqfCount.addField({ where: false }).addValue({ name: 'id', - table: 'escola', + table: 'escola_agregada', tableField: 'id', where: { relation: '=', @@ -359,12 +389,12 @@ rqfCount.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'dims').addValueToField({ name: 'city', @@ -375,12 +405,12 @@ rqfCount.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'filter').addValue({ name: 'state', @@ -391,12 +421,12 @@ rqfCount.addField({ relation: '=', type: 'integer', field: 'estado_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'mesoregion', @@ -412,7 +442,7 @@ rqfCount.addField({ join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'microregion', @@ -428,7 +458,7 @@ rqfCount.addField({ join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'region', @@ -443,22 +473,22 @@ rqfCount.addField({ join: { primary: 'id', foreign: 'regiao_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { relation: '=', type: 'integer', field: 'ano_censo', - table: 'escola' + table: 'escola_agregada' } }).addValue({ name: 'location', - table: 'escola', + table: 'escola_agregada', tableField: 'localizacao_id', resultField: 'location_id', where: { @@ -468,7 +498,7 @@ rqfCount.addField({ } }).addValue({ name: 'diff_location', - table: 'escola', + table: 'escola_agregada', tableField: 'localizacao_diferenciada_par', resultField: 'diff_location_id', where: { @@ -478,7 +508,7 @@ rqfCount.addField({ } }).addValue({ name: 'rural_location', - table: 'escola', + table: 'escola_agregada', tableField: 'localidade_area_rural', resultField: 'rural_location_id', where: { @@ -488,7 +518,7 @@ rqfCount.addField({ } }).addValue({ name: 'arrangement', - table: 'escola', + table: 'escola_agregada', tableField: 'arranjo', resultField: 'arrangement_id', where: { @@ -498,7 +528,7 @@ rqfCount.addField({ } }).addValue({ name: 'adm_dependency', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_id', resultField: 'adm_dependency_id', where: { @@ -508,7 +538,7 @@ rqfCount.addField({ } }).addValue({ name: 'adm_dependency_detailed', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_priv', resultField: 'adm_dependency_detailed_id', where: { @@ -518,7 +548,7 @@ rqfCount.addField({ } }).addValue({ name: 'government_agreement', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_convenio_publico', resultField: 'government_agreement_id', where: { @@ -528,7 +558,7 @@ rqfCount.addField({ } }).addValue({ name: 'integral_time', - table: 'escola', + table: 'escola_agregada', tableField: 'tempo_integral', resultField: 'integral_time_id', where: { @@ -538,7 +568,7 @@ rqfCount.addField({ } }).addValue({ name: 'agreement', - table: 'escola', + table: 'escola_agregada', tableField: 'tipo_convenio_pp', resultField: 'agreement_id', where: { @@ -548,7 +578,7 @@ rqfCount.addField({ } }).addValue({ name: 'education_day_care_child', - table: 'escola', + table: 'escola_agregada', tableField: 'reg_infantil_creche_t1', resultField: 'education_day_care_child_id', where: { @@ -558,7 +588,7 @@ rqfCount.addField({ } }).addValue({ name: 'education_preschool_child', - table: 'escola', + table: 'escola_agregada', tableField: 'reg_infantil_preescola_t1', resultField: 'education_preschool_child_id', where: { @@ -568,7 +598,7 @@ rqfCount.addField({ } }).addValue({ name: 'education_begin_elementary_school', - table: 'escola', + table: 'escola_agregada', tableField: 'reg_fund_ai_t1', resultField: 'education_begin_elementary_school_id', where: { @@ -578,7 +608,7 @@ rqfCount.addField({ } }).addValue({ name: 'education_end_elementary_school', - table: 'escola', + table: 'escola_agregada', tableField: 'reg_fund_af_t1', resultField: 'education_end_elementary_school_id', where: { @@ -588,7 +618,7 @@ rqfCount.addField({ } }).addValue({ name: 'education_middle_school', - table: 'escola', + table: 'escola_agregada', tableField: 'reg_medio_medio_t1', resultField: 'education_middle_school_id', where: { @@ -598,7 +628,7 @@ rqfCount.addField({ } }).addValue({ name: 'education_professional', - table: 'escola', + table: 'escola_agregada', tableField: 'educacao_profissional', resultField: 'education_professional_id', where: { @@ -608,7 +638,7 @@ rqfCount.addField({ } }).addValue({ name: 'education_eja', - table: 'escola', + table: 'escola_agregada', tableField: 'ensino_eja', resultField: 'education_eja_id', where: { @@ -618,7 +648,7 @@ rqfCount.addField({ } }).addValue({ name: 'min_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -628,7 +658,7 @@ rqfCount.addField({ } }).addValue({ name: 'max_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -638,7 +668,7 @@ rqfCount.addField({ } }).addValue({ name: 'school_building', - table: 'escola', + table: 'escola_agregada', tableField: 'local_func_predio_escolar', resultField: 'school_building', where: { @@ -649,37 +679,34 @@ rqfCount.addField({ }); schoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { - req.sql.from('escola') - .field('escola.id') - .field('escola.ano_censo', 'year') - .field('escola.nome_escola', 'name') - .field('escola.estado_id', 'state_id') - .field('escola.municipio_id', 'city_id'); + req.sql.from('escola_agregada') + .field('escola_agregada.id') + .field('escola_agregada.ano_censo', 'year') + .field('escola_agregada.nome_escola', 'name') + .field('escola_agregada.estado_id', 'state_id') + .field('escola_agregada.municipio_id', 'city_id'); next(); }, query, response('school')); -schoolApp.get('/count', cache('15 day'), rqfCount.parse(), reqBody.parse(), (req, res, next) => { +schoolApp.get('/count', cache('15 day'), rqfCount.parse(), (req, res, next) => { let arrang = ["arranjo_creche", "arranjo_pre", "arranjo_fundamental_ai", "arranjo_fundamental_af", "arranjo_multietapa", "arranjo_ensino_medio", "ensino_eja", "educacao_profissional", "ensino_especial"]; - if (!req.hasMetrics) { - req.sql.field('COUNT(escola.id)', 'total'); - } - - req.sql.from('escola') + req.sql.from('escola_agregada') + .field('COUNT(escola_agregada.id)', 'total') .field("'Brasil'", 'name') - .field('escola.ano_censo', 'year') - .group('escola.ano_censo') - .order('escola.ano_censo') - .where('escola.situacao_funcionamento_pareada = 1 AND (escola.ensino_regular = 1 OR escola.ensino_eja=1 or escola.educacao_profissional=1)') + .field('escola_agregada.ano_censo', 'year') + .group('escola_agregada.ano_censo') + .order('escola_agregada.ano_censo') + .where('escola_agregada.situacao_funcionamento_pareada = 1 AND (escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja=1 or escola_agregada.educacao_profissional=1)') //Transforma a query em OR se tiver o filtro do arranjo if (req.filter.arrangement) { let arrangementQuery = ""; for (let i = 0; i < req.filter.arrangement.length - 1; i++) { - arrangementQuery += 'escola.' + arrang[req.filter.arrangement[i]] + ' = 1 OR '; + arrangementQuery += 'escola_agregada.' + arrang[req.filter.arrangement[i]] + ' = 1 OR '; } // o ultimo elemento precisa ser sem o OR - arrangementQuery += 'escola.' + arrang[req.filter.arrangement[req.filter.arrangement.length - 1]] + ' = 1'; + arrangementQuery += 'escola_agregada.' + arrang[req.filter.arrangement[req.filter.arrangement.length - 1]] + ' = 1'; req.sql.where('' + arrangementQuery); } delete req.filter.arrangement diff --git a/src/libs/routes_v2/schoolInfrastructure.js b/src/libs/routes_v2/schoolInfrastructure.js index c74f0e30..da4d4593 100644 --- a/src/libs/routes_v2/schoolInfrastructure.js +++ b/src/libs/routes_v2/schoolInfrastructure.js @@ -47,22 +47,22 @@ let rqf = new ReqQueryFields(); 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'); + req.sql.from('escola_agregada') + .field('MIN(escola_agregada.ano_censo)', 'start_year') + .field('MAX(escola_agregada.ano_censo)', 'end_year'); next(); }, query, response('range')); infrastructureApp.get('/years', (req, res, next) => { - req.sql.from('escola') - .field('DISTINCT escola.ano_censo', 'year'); + req.sql.from('escola_agregada') + .field('DISTINCT escola_agregada.ano_censo', 'year'); next(); }, query, response('years')); infrastructureApp.get('/source', (req, res, next) => { req.sql.from('fonte') .field('fonte', 'source') - .where('tabela = \'escola\''); + .where('tabela = \'escola_agregada\''); next(); }, query, response('source')); @@ -125,12 +125,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'dims').addValueToField({ name: 'city', @@ -141,12 +141,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'filter').addValueToField({ name: 'state', @@ -157,12 +157,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'estado_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'dims').addValueToField({ name: 'state', @@ -173,12 +173,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'estado_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'filter').addValue({ name: 'region', @@ -193,11 +193,11 @@ rqf.addField({ join: { primary: 'id', foreign: 'regiao_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'location', - table: 'escola', + table: 'escola_agregada', tableField: 'localizacao_id', resultField: 'location_id', where: { @@ -207,7 +207,7 @@ rqf.addField({ } }).addValue({ name: 'rural_location', - table: 'escola', + table: 'escola_agregada', tableField: 'localidade_area_rural', resultField: 'rural_location_id', where: { @@ -217,7 +217,7 @@ rqf.addField({ } }).addValue({ name: 'adm_dependency', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_id', resultField: 'adm_dependency_id', where: { @@ -227,7 +227,7 @@ rqf.addField({ } }).addValue({ name: 'adm_dependency_detailed', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_priv', resultField: 'adm_dependency_detailed_id', where: { @@ -237,7 +237,7 @@ rqf.addField({ } }).addValue({ name: 'min_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -247,7 +247,7 @@ rqf.addField({ } }).addValue({ name: 'max_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -328,57 +328,57 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Local de funcionamento let allSchools = req.sql.clone(); - allSchools.from('escola').field('COUNT(escola.id)', 'total') + allSchools.from('escola_agregada').field('COUNT(escola_agregada.id)', 'total') .field("'Brasil'", 'name') - .field('escola.ano_censo', 'year') - .group('escola.ano_censo') - .where('escola.situacao_de_funcionamento = 1') - .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1') - .where('escola.local_func_predio_escolar = 1') - .where('escola.dependencia_adm_id <= 3') - .order('escola.ano_censo'); + .field('escola_agregada.ano_censo', 'year') + .group('escola_agregada.ano_censo') + .where('escola_agregada.situacao_de_funcionamento = 1') + .where('escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1') + .where('escola_agregada.local_func_predio_escolar = 1') + .where('escola_agregada.dependencia_adm_id <= 3') + .order('escola_agregada.ano_censo'); req.queryIndex.allSchools = req.querySet.push(allSchools) - 1; let allUrbanSchools = allSchools.clone(); - allUrbanSchools.where('escola.localizacao_id = 1'); + allUrbanSchools.where('escola_agregada.localizacao_id = 1'); req.queryIndex.allUrbanSchools = req.querySet.push(allUrbanSchools) - 1; let allCountrySchools = allSchools.clone(); - allCountrySchools.where('escola.localizacao_id = 2'); + allCountrySchools.where('escola_agregada.localizacao_id = 2'); req.queryIndex.allCountrySchools = req.querySet.push(allCountrySchools) - 1; let allSchoolsNotSchoolBuilding = req.sql.clone(); - allSchoolsNotSchoolBuilding.from('escola').field('COUNT(escola.id)', 'total') + allSchoolsNotSchoolBuilding.from('escola_agregada').field('COUNT(escola_agregada.id)', 'total') .field("'Brasil'", 'name') - .field('escola.ano_censo', 'year') - .group('escola.ano_censo') - .where('escola.situacao_de_funcionamento = 1') - .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1') - .where('escola.local_func_predio_escolar = 0') - .where('escola.dependencia_adm_id <= 3') - .order('escola.ano_censo'); + .field('escola_agregada.ano_censo', 'year') + .group('escola_agregada.ano_censo') + .where('escola_agregada.situacao_de_funcionamento = 1') + .where('escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1') + .where('escola_agregada.local_func_predio_escolar = 0') + .where('escola_agregada.dependencia_adm_id <= 3') + .order('escola_agregada.ano_censo'); req.queryIndex.allSchoolsNotSchoolBuilding = req.querySet.push(allSchoolsNotSchoolBuilding) - 1; // Bibliotecas req.queryIndex.allLibraries = req.queryIndex.allUrbanSchools; let haveLibraries = allUrbanSchools.clone(); - haveLibraries.where('escola.biblioteca = 1'); + haveLibraries.where('escola_agregada.biblioteca = 1'); req.queryIndex.haveLibraries = req.querySet.push(haveLibraries) - 1; let needLibraries = allUrbanSchools.clone(); - needLibraries.where('escola.biblioteca = 0'); + needLibraries.where('escola_agregada.biblioteca = 0'); req.queryIndex.needLibraries = req.querySet.push(needLibraries) - 1; // Sala de leitura req.queryIndex.allLibrariesReadingRoom = req.queryIndex.allCountrySchools; let haveLibrariesReadingRoom = allCountrySchools.clone(); - haveLibrariesReadingRoom.where('escola.biblioteca_sala_leitura = true'); + haveLibrariesReadingRoom.where('escola_agregada.biblioteca_sala_leitura = true'); req.queryIndex.haveLibrariesReadingRoom = req.querySet.push(haveLibrariesReadingRoom) - 1; let needLibrariesReadingRoom = allCountrySchools.clone(); - needLibrariesReadingRoom.where('escola.biblioteca_sala_leitura = false'); + needLibrariesReadingRoom.where('escola_agregada.biblioteca_sala_leitura = false'); req.queryIndex.needLibrariesReadingRoom = req.querySet.push(needLibrariesReadingRoom) - 1; // Laboratório de informática @@ -391,11 +391,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1; let haveInfLab = allInfLab.clone(); - haveInfLab.where('escola.lab_informatica = 1'); + haveInfLab.where('escola_agregada.lab_informatica = 1'); req.queryIndex.haveInfLab = req.querySet.push(haveInfLab) - 1; let needInfLab = allInfLab.clone(); - needInfLab.where('escola.lab_informatica = 0'); + needInfLab.where('escola_agregada.lab_informatica = 0'); req.queryIndex.needInfLab = req.querySet.push(needInfLab) - 1; // Laboratório de ciências @@ -404,11 +404,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1; let haveScienceLab = allScienceLab.clone(); - haveScienceLab.where('escola.lab_ciencias = true'); + haveScienceLab.where('escola_agregada.lab_ciencias = true'); req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1; let needScienceLab = allScienceLab.clone(); - needScienceLab.where('escola.lab_ciencias = false'); + needScienceLab.where('escola_agregada.lab_ciencias = false'); req.queryIndex.needScienceLab = req.querySet.push(needScienceLab) - 1; // Parque infantil @@ -419,24 +419,24 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1; let haveKidsPark = allKidsPark.clone(); - haveKidsPark.where('escola.parque_infantil = 1'); + haveKidsPark.where('escola_agregada.parque_infantil = 1'); req.queryIndex.haveKidsPark = req.querySet.push(haveKidsPark) - 1; let needKidsPark = allKidsPark.clone(); - needKidsPark.where('escola.parque_infantil = 0'); + needKidsPark.where('escola_agregada.parque_infantil = 0'); req.queryIndex.needKidsPark = req.querySet.push(needKidsPark) - 1; // // Berçário // let allCribs = allSchools.clone(); - // allCribs.where('escola.reg_infantil_creche_t1 = 1'); + // allCribs.where('escola_agregada.reg_infantil_creche_t1 = 1'); // req.queryIndex.allCribs = req.querySet.push(allCribs) - 1; // let haveCribs = allCribs.clone(); - // haveCribs.where('escola.bercario = 1'); + // haveCribs.where('escola_agregada.bercario = 1'); // req.queryIndex.haveCribs = req.querySet.push(haveCribs) - 1; // let needCribs = allCribs.clone(); - // needCribs.where('escola.bercario = 0'); + // needCribs.where('escola_agregada.bercario = 0'); // req.queryIndex.needCribs = req.querySet.push(needCribs) - 1; // Quadra de esportes @@ -445,11 +445,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1; let haveSportsCourt = allSportsCourt.clone(); - haveSportsCourt.where('escola.quadra_esportes = 1'); + haveSportsCourt.where('escola_agregada.quadra_esportes = 1'); req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1; let needSportsCourt = allSportsCourt.clone(); - needSportsCourt.where('escola.quadra_esportes = 0'); + needSportsCourt.where('escola_agregada.quadra_esportes = 0'); req.queryIndex.needSportsCourt = req.querySet.push(needSportsCourt) - 1; // Quadras a serem cobertas @@ -457,7 +457,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // (dependencia_adm_id<=3) and (reg_fund_ai_t1=1 or reg_fund_af_t1=1 or reg_medio_medio_t1=1 or ensino_eja_fund= 1 or ensino_eja_medio= 1 or // ensino_eja_prof= 1 or esp_eja_fund=1 or esp_eja_medio=1 or ensino_esp_exclusiva_eja_prof=1) and (quadra_esportes_descoberta=1) então conta id let allSportsCourtCoverage = allSportsCourt.clone(); - allSportsCourtCoverage.where('escola.quadra_esportes_descoberta = 1'); + allSportsCourtCoverage.where('escola_agregada.quadra_esportes_descoberta = 1'); req.queryIndex.allSportsCourtCoverage = req.querySet.push(allSportsCourtCoverage) -1; req.queryIndex.haveSportsCourtCoverage = req.queryIndex.allSportsCourtCoverage; // It must be [] @@ -468,16 +468,16 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allCourtyard = req.queryIndex.allSchools; let haveCourtyard = allSchools.clone(); - haveCourtyard.where('escola.patio = 1 OR escola.patio = 2'); + haveCourtyard.where('escola_agregada.patio = 1 OR escola_agregada.patio = 2'); req.queryIndex.haveCourtyard = req.querySet.push(haveCourtyard) - 1; let needCourtyard = allSchools.clone(); - needCourtyard.where('escola.patio = 0'); + needCourtyard.where('escola_agregada.patio = 0'); req.queryIndex.needCourtyard = req.querySet.push(needCourtyard) - 1; // Pátios a serem cobertos let allCourtyardCoverage = allSchools.clone(); - allCourtyardCoverage.where('escola.patio = 1'); + allCourtyardCoverage.where('escola_agregada.patio = 1'); req.queryIndex.allCourtyardCoverage = req.querySet.push(allCourtyardCoverage) - 1; req.queryIndex.haveCourtyardCoverage = req.queryIndex.allCourtyardCoverage; // It must be [] @@ -488,77 +488,77 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allDirectorRoom = req.queryIndex.allUrbanSchools; let haveDirectorRoom = allUrbanSchools.clone(); - haveDirectorRoom.where('escola.sala_diretoria = 1'); + haveDirectorRoom.where('escola_agregada.sala_diretoria = 1'); req.queryIndex.haveDirectorRoom = req.querySet.push(haveDirectorRoom) - 1; let needDirectorRoom = allUrbanSchools.clone(); - needDirectorRoom.where('escola.sala_diretoria = 0'); + needDirectorRoom.where('escola_agregada.sala_diretoria = 0'); req.queryIndex.needDirectorRoom = req.querySet.push(needDirectorRoom) - 1; // Secretaria req.queryIndex.allSecretary = req.queryIndex.allSchools; let haveSecretary = allSchools.clone(); - haveSecretary.where('escola.secretaria = 1'); + haveSecretary.where('escola_agregada.secretaria = 1'); req.queryIndex.haveSecretary = req.querySet.push(haveSecretary) - 1; let needSecretary = allSchools.clone(); - needSecretary.where('escola.secretaria = 0'); + needSecretary.where('escola_agregada.secretaria = 0'); req.queryIndex.needSecretary = req.querySet.push(needSecretary) - 1; // Sala de professores req.queryIndex.allTeacherRoom = req.queryIndex.allSchools; let haveTeacherRoom = allSchools.clone(); - haveTeacherRoom.where('escola.sala_professor = 1'); + haveTeacherRoom.where('escola_agregada.sala_professor = 1'); req.queryIndex.haveTeacherRoom = req.querySet.push(haveTeacherRoom) - 1; let needTeacherRoom = allSchools.clone(); - needTeacherRoom.where('escola.sala_professor = 0'); + needTeacherRoom.where('escola_agregada.sala_professor = 0'); req.queryIndex.needTeacherRoom = req.querySet.push(needTeacherRoom) - 1; // Cozinha req.queryIndex.allKitchen = req.queryIndex.allSchools; let haveKitchen = allSchools.clone(); - haveKitchen.where('escola.cozinha = 1'); + haveKitchen.where('escola_agregada.cozinha = 1'); req.queryIndex.haveKitchen = req.querySet.push(haveKitchen) - 1; let needKitchen = allSchools.clone(); - needKitchen.where('escola.cozinha = 0'); + needKitchen.where('escola_agregada.cozinha = 0'); req.queryIndex.needKitchen = req.querySet.push(needKitchen) - 1; // Despensa req.queryIndex.allStoreroom = req.queryIndex.allSchools; let haveStoreroom = allSchools.clone(); - haveStoreroom.where('escola.despensa = 1'); + haveStoreroom.where('escola_agregada.despensa = 1'); req.queryIndex.haveStoreroom = req.querySet.push(haveStoreroom) - 1; let needStoreroom = allSchools.clone(); - needStoreroom.where('escola.despensa = 0'); + needStoreroom.where('escola_agregada.despensa = 0'); req.queryIndex.needStoreroom = req.querySet.push(needStoreroom) - 1; // Almoxarifado req.queryIndex.allWarehouse = req.queryIndex.allSchools; let haveWarehouse = allSchools.clone(); - haveWarehouse.where('escola.almoxarifado = 1'); + haveWarehouse.where('escola_agregada.almoxarifado = 1'); req.queryIndex.haveWarehouse = req.querySet.push(haveWarehouse) - 1; let needWarehouse = allSchools.clone(); - needWarehouse.where('escola.almoxarifado = 0'); + needWarehouse.where('escola_agregada.almoxarifado = 0'); req.queryIndex.needWarehouse = req.querySet.push(needWarehouse) - 1; // Internet req.queryIndex.allInternet = req.queryIndex.allCountrySchools; let haveInternet = allCountrySchools.clone(); - haveInternet.where('escola.internet = 1'); + haveInternet.where('escola_agregada.internet = 1'); req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1; let needInternet = allCountrySchools.clone(); - needInternet.where('escola.internet = 0'); + needInternet.where('escola_agregada.internet = 0'); req.queryIndex.needInternet = req.querySet.push(needInternet) - 1; // Internet banda larga @@ -567,22 +567,22 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allBroadbandInternet = req.queryIndex.allUrbanSchools; let haveBroadbandInternet = allUrbanSchools.clone(); - haveBroadbandInternet.where('escola.internet_banda_larga = 1'); + haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1'); req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1; let needBroadbandInternet = allUrbanSchools.clone(); - needBroadbandInternet.where('escola.internet_banda_larga = 0'); + needBroadbandInternet.where('escola_agregada.internet_banda_larga = 0'); req.queryIndex.needBroadbandInternet = req.querySet.push(needBroadbandInternet) - 1; // Banheiro req.queryIndex.allInsideBathroom = req.queryIndex.allSchools; let haveInsideBathroom = allSchools.clone(); - haveInsideBathroom.where('escola.banheiro = 1'); + haveInsideBathroom.where('escola_agregada.banheiro = 1'); req.queryIndex.haveInsideBathroom = req.querySet.push(haveInsideBathroom) - 1; let needInsideBathroom = allSchools.clone(); - needInsideBathroom.where('escola.banheiro = 0'); + needInsideBathroom.where('escola_agregada.banheiro = 0'); req.queryIndex.needInsideBathroom = req.querySet.push(needInsideBathroom) - 1; // Banheiro adequado para educação infantil dentro do prédio @@ -593,77 +593,77 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInsideKidsBathroom = req.querySet.push(allInsideKidsBathroom) - 1; let haveInsideKidsBathroom = allInsideKidsBathroom.clone(); - haveInsideKidsBathroom.where('escola.sanitario_ei = 1'); + haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1'); req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1; let needInsideKidsBathroom = allInsideKidsBathroom.clone(); - needInsideKidsBathroom.where('escola.sanitario_ei = 0'); + needInsideKidsBathroom.where('escola_agregada.sanitario_ei = 0'); req.queryIndex.needInsideKidsBathroom = req.querySet.push(needInsideKidsBathroom) - 1; // Fornecimento de energia req.queryIndex.allEletricPower = req.queryIndex.allSchools; let haveEletricPower = allSchools.clone(); - haveEletricPower.where('escola.energia_inexistente = 0'); + haveEletricPower.where('escola_agregada.energia_inexistente = 0'); req.queryIndex.haveEletricPower = req.querySet.push(haveEletricPower) - 1; let needEletricPower = allSchools.clone(); - needEletricPower.where('escola.energia_inexistente = 1'); + needEletricPower.where('escola_agregada.energia_inexistente = 1'); req.queryIndex.needEletricPower = req.querySet.push(needEletricPower) - 1; // Abastecimento de água req.queryIndex.allWaterSupply = req.queryIndex.allSchools; let haveWaterSupply = allSchools.clone(); - haveWaterSupply.where('escola.agua_inexistente = 0'); + haveWaterSupply.where('escola_agregada.agua_inexistente = 0'); req.queryIndex.haveWaterSupply = req.querySet.push(haveWaterSupply) - 1; let needWaterSupply = allSchools.clone(); - needWaterSupply.where('escola.agua_inexistente = 1'); + needWaterSupply.where('escola_agregada.agua_inexistente = 1'); req.queryIndex.needWaterSupply = req.querySet.push(needWaterSupply) - 1; // Ãgua Potável req.queryIndex.allFilteredWater = req.queryIndex.allSchools; let haveFilteredWater = allSchools.clone(); - haveFilteredWater.where('escola.agua_potavel = 1'); + haveFilteredWater.where('escola_agregada.agua_potavel = 1'); req.queryIndex.haveFilteredWater = req.querySet.push(haveFilteredWater) - 1; let needFilteredWater = allSchools.clone(); - needFilteredWater.where('escola.agua_potavel = 0'); + needFilteredWater.where('escola_agregada.agua_potavel = 0'); req.queryIndex.needFilteredWater = req.querySet.push(needFilteredWater) - 1; // Coleta de esgoto req.queryIndex.allSewage = req.queryIndex.allSchools; let haveSewage = allSchools.clone(); - haveSewage.where('escola.esgoto_rede_publica = 1 OR escola.esgoto_fossa_septica = 1'); + haveSewage.where('escola_agregada.esgoto_rede_publica = 1 OR escola_agregada.esgoto_fossa_septica = 1'); req.queryIndex.haveSewage = req.querySet.push(haveSewage) - 1; let needSewage = allSchools.clone(); - needSewage.where('escola.esgoto_rede_publica = 0 AND escola.esgoto_fossa_septica = 0'); + needSewage.where('escola_agregada.esgoto_rede_publica = 0 AND escola_agregada.esgoto_fossa_septica = 0'); req.queryIndex.needSewage = req.querySet.push(needSewage) - 1; // Dependências adaptada para pessoas com deficiências req.queryIndex.allAdaptedBuilding = req.queryIndex.allSchools; let haveAdaptedBuilding = allSchools.clone(); - haveAdaptedBuilding.where('escola.acessibilidade_inexistente = 0'); + haveAdaptedBuilding.where('escola_agregada.acessibilidade_inexistente = 0'); req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1; let needAdaptedBuilding = allSchools.clone(); - needAdaptedBuilding.where('escola.acessibilidade_inexistente = 1'); + needAdaptedBuilding.where('escola_agregada.acessibilidade_inexistente = 1'); req.queryIndex.needAdaptedBuilding = req.querySet.push(needAdaptedBuilding) - 1; // Banheiros adaptados para pessoas com deficiências req.queryIndex.allSpecialBathroom = req.queryIndex.allSchools; let haveSpecialBathroom = allSchools.clone(); - haveSpecialBathroom.where('escola.sanitario_pne = 1'); + haveSpecialBathroom.where('escola_agregada.sanitario_pne = 1'); req.queryIndex.haveSpecialBathroom = req.querySet.push(haveSpecialBathroom) - 1; let needSpecialBathroom = allSchools.clone(); - needSpecialBathroom.where('escola.sanitario_pne = 0'); + needSpecialBathroom.where('escola_agregada.sanitario_pne = 0'); req.queryIndex.needSpecialBathroom = req.querySet.push(needSpecialBathroom) - 1; -- GitLab From e91d3829c89124908ba50bf41cc4a70c47441152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 7 Mar 2023 10:42:43 -0300 Subject: [PATCH 061/123] Change classCount to use new table --- src/libs/routes_v2/classCount.js | 14 +++++++------- src/libs/routes_v2/dailyChargeAmount.js | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libs/routes_v2/classCount.js b/src/libs/routes_v2/classCount.js index ffdbe34f..77716328 100644 --- a/src/libs/routes_v2/classCount.js +++ b/src/libs/routes_v2/classCount.js @@ -196,7 +196,7 @@ rqf.addField({ } }).addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: ['nome_escola', 'id'], resultField: ['school_name', 'school_id'], where: { @@ -211,7 +211,7 @@ rqf.addField({ } }, 'dims').addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: 'nome_escola', resultField: 'school_name', where: { @@ -227,15 +227,15 @@ rqf.addField({ }, 'filter'); classCountApp.get('/year_range', (req, res, next) => { - req.sql.from('escola') - .field('MIN(escola.ano_censo)', 'start_year') - .field('MAX(escola.ano_censo)', 'end_year'); + req.sql.from('escola_agregada') + .field('MIN(escola_agregada.ano_censo)', 'start_year') + .field('MAX(escola_agregada.ano_censo)', 'end_year'); next(); }, query, response('range')); classCountApp.get('/years', (req, res, next) => { - req.sql.from('escola') - .field('DISTINCT escola.ano_censo', 'year'); + req.sql.from('escola_agregada') + .field('DISTINCT escola_agregada.ano_censo', 'year'); next(); }, query, response('years')); diff --git a/src/libs/routes_v2/dailyChargeAmount.js b/src/libs/routes_v2/dailyChargeAmount.js index 4af6cb7d..78115e48 100644 --- a/src/libs/routes_v2/dailyChargeAmount.js +++ b/src/libs/routes_v2/dailyChargeAmount.js @@ -207,7 +207,7 @@ rqf.addField({ } }).addValue({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: ['nome_escola', 'id'], resultField: ['school_name', 'school_id'], where: { -- GitLab From a371083b0f95666bf094523e3abbcb75e0a41ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 7 Mar 2023 10:49:56 -0300 Subject: [PATCH 062/123] Change infrastructure to use new table --- src/libs/routes_v2/infrastructure.js | 130 +++++++++++++-------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/src/libs/routes_v2/infrastructure.js b/src/libs/routes_v2/infrastructure.js index 1ececa91..cc4c5931 100644 --- a/src/libs/routes_v2/infrastructure.js +++ b/src/libs/routes_v2/infrastructure.js @@ -47,22 +47,22 @@ let rqf = new ReqQueryFields(); 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'); + req.sql.from('escola_agregada') + .field('MIN(escola_agregada.ano_censo)', 'start_year') + .field('MAX(escola_agregada.ano_censo)', 'end_year'); next(); }, query, response('range')); infrastructureApp.get('/years', (req, res, next) => { - req.sql.from('escola') - .field('DISTINCT escola.ano_censo', 'year'); + req.sql.from('escola_agregada') + .field('DISTINCT escola_agregada.ano_censo', 'year'); next(); }, query, response('years')); infrastructureApp.get('/source', (req, res, next) => { req.sql.from('fonte') .field('fonte', 'source') - .where('tabela = \'escola\''); + .where('tabela = \'escola_agregada\''); next(); }, query, response('source')); @@ -125,12 +125,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'dims').addValueToField({ name: 'city', @@ -141,12 +141,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'filter').addValueToField({ name: 'state', @@ -157,12 +157,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'estado_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'dims').addValueToField({ name: 'state', @@ -173,12 +173,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'estado_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'filter').addValue({ name: 'region', @@ -193,11 +193,11 @@ rqf.addField({ join: { primary: 'id', foreign: 'regiao_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'location', - table: 'escola', + table: 'escola_agregada', tableField: 'localizacao_id', resultField: 'location_id', where: { @@ -207,7 +207,7 @@ rqf.addField({ } }).addValue({ name: 'rural_location', - table: 'escola', + table: 'escola_agregada', tableField: 'localidade_area_rural', resultField: 'rural_location_id', where: { @@ -217,7 +217,7 @@ rqf.addField({ } }).addValue({ name: 'adm_dependency', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_id', resultField: 'adm_dependency_id', where: { @@ -227,7 +227,7 @@ rqf.addField({ } }).addValue({ name: 'adm_dependency_detailed', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_priv', resultField: 'adm_dependency_detailed_id', where: { @@ -237,7 +237,7 @@ rqf.addField({ } }).addValue({ name: 'min_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -247,7 +247,7 @@ rqf.addField({ } }).addValue({ name: 'max_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -302,44 +302,44 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Local de funcionamento let allSchools = req.sql.clone(); - allSchools.from('escola').field('COUNT(escola.id)', 'total') + allSchools.from('escola_agregada').field('COUNT(escola_agregada.id)', 'total') .field("'Brasil'", 'name') - .field('escola.ano_censo', 'year') - .group('escola.ano_censo') - .where('escola.situacao_de_funcionamento = 1') - .order('escola.ano_censo'); + .field('escola_agregada.ano_censo', 'year') + .group('escola_agregada.ano_censo') + .where('escola_agregada.situacao_de_funcionamento = 1') + .order('escola_agregada.ano_censo'); req.queryIndex.allSchools = req.querySet.push(allSchools) - 1; let schoolPlace = allSchools.clone(); - schoolPlace.where('escola.func_predio_escolar = 1 AND escola.func_salas_empresa = 0 AND escola.func_templo_igreja = 0 AND escola.func_casa_professor = 0 AND escola.func_galpao = 0 AND escola.biblioteca = 1'); + schoolPlace.where('escola_agregada.func_predio_escolar = 1 AND escola_agregada.func_salas_empresa = 0 AND escola_agregada.func_templo_igreja = 0 AND escola_agregada.func_casa_professor = 0 AND escola_agregada.func_galpao = 0 AND escola_agregada.biblioteca = 1'); req.queryIndex.schoolPlace = req.querySet.push(schoolPlace) - 1; // Bibliotecas let allLibraries = allSchools.clone(); - allLibraries.where('escola.func_predio_escolar = 1 AND escola.localizacao_id = 1'); + allLibraries.where('escola_agregada.func_predio_escolar = 1 AND escola_agregada.localizacao_id = 1'); req.queryIndex.allLibraries = req.querySet.push(allLibraries) - 1; let haveLibraries = allLibraries.clone(); - haveLibraries.where('escola.biblioteca = 1'); + haveLibraries.where('escola_agregada.biblioteca = 1'); req.queryIndex.haveLibraries = req.querySet.push(haveLibraries) - 1; // Bibliotecas/Sala de leitura let allLibrariesReadingRoom = allSchools.clone(); - allLibrariesReadingRoom.where('escola.func_predio_escolar = 1 AND escola.localizacao_id = 2'); + allLibrariesReadingRoom.where('escola_agregada.func_predio_escolar = 1 AND escola_agregada.localizacao_id = 2'); req.queryIndex.allLibrariesReadingRoom = req.querySet.push(allLibrariesReadingRoom) - 1; let haveLibrariesReadingRoom = allLibrariesReadingRoom.clone(); - haveLibrariesReadingRoom.where('escola.sala_leitura = 1'); + haveLibrariesReadingRoom.where('escola_agregada.sala_leitura = 1'); req.queryIndex.haveLibrariesReadingRoom = req.querySet.push(haveLibrariesReadingRoom) - 1; // Laboratório de informática let allInfLab = allSchools.clone(); - allInfLab.where('escola.func_predio_escolar = 1') - .where('escola.reg_fund_ai = 1 OR escola.reg_fund_af = 1 OR escola.reg_medio_medio = 1 OR escola.reg_medio_integrado = 1 OR escola.reg_medio_normal = 1 OR escola.ensino_eja_fund = 1 OR escola.ensino_eja_medio = 1 OR escola.ensino_eja_prof = 1'); + allInfLab.where('escola_agregada.func_predio_escolar = 1') + .where('escola_agregada.reg_fund_ai = 1 OR escola_agregada.reg_fund_af = 1 OR escola_agregada.reg_medio_medio = 1 OR escola_agregada.reg_medio_integrado = 1 OR escola_agregada.reg_medio_normal = 1 OR escola_agregada.ensino_eja_fund = 1 OR escola_agregada.ensino_eja_medio = 1 OR escola_agregada.ensino_eja_prof = 1'); req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1; let haveInfLab = allInfLab.clone(); - haveInfLab.where('escola.lab_informatica = 1'); + haveInfLab.where('escola_agregada.lab_informatica = 1'); req.queryIndex.haveInfLab = req.querySet.push(haveInfLab) - 1; // Laboratório de ciências @@ -347,175 +347,175 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1; let haveScienceLab = allScienceLab.clone(); - haveScienceLab.where('escola.lab_ciencias = 1'); + haveScienceLab.where('escola_agregada.lab_ciencias = 1'); req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1; // Parque infantil let allKidsPark = allSchools.clone(); - allKidsPark.where('escola.func_predio_escolar = 1') - .where('escola.reg_infantil_creche = 1 OR escola.reg_infantil_preescola = 1 OR escola.reg_fund_ai = 1 OR escola.esp_infantil_creche = 1 OR escola.esp_exclusiva_creche = 1 OR escola.reg_esp_exclusiva_fund_ai = 1'); + allKidsPark.where('escola_agregada.func_predio_escolar = 1') + .where('escola_agregada.reg_infantil_creche = 1 OR escola_agregada.reg_infantil_preescola = 1 OR escola_agregada.reg_fund_ai = 1 OR escola_agregada.esp_infantil_creche = 1 OR escola_agregada.esp_exclusiva_creche = 1 OR escola_agregada.reg_esp_exclusiva_fund_ai = 1'); req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1; let haveKidsPark = allKidsPark.clone(); - haveKidsPark.where('escola.parque_infantil = 1'); + haveKidsPark.where('escola_agregada.parque_infantil = 1'); req.queryIndex.haveKidsPark = req.querySet.push(haveKidsPark) - 1; // Berçário let allCribs = allSchools.clone(); - allCribs.where('escola.func_predio_escolar = 1') - .where('escola.reg_infantil_creche = 1 OR escola.esp_infantil_creche = 1'); + allCribs.where('escola_agregada.func_predio_escolar = 1') + .where('escola_agregada.reg_infantil_creche = 1 OR escola_agregada.esp_infantil_creche = 1'); req.queryIndex.allCribs = req.querySet.push(allCribs) - 1; let haveCribs = allCribs.clone(); - haveCribs.where('escola.bercario = 1'); + haveCribs.where('escola_agregada.bercario = 1'); req.queryIndex.haveCribs = req.querySet.push(haveCribs) - 1; // Quadra let allSportsCourt = allScienceLab.clone(); - allSportsCourt.where('escola.localizacao_id = 1'); + allSportsCourt.where('escola_agregada.localizacao_id = 1'); req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1; let haveSportsCourt = allSportsCourt.clone(); - haveSportsCourt.where('escola.quadra_esportes = 1'); + haveSportsCourt.where('escola_agregada.quadra_esportes = 1'); req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1; // Quadra coberta req.queryIndex.allCoveredSportsCourt = req.queryIndex.allSportsCourt; let haveCoveredSportsCourt = allSportsCourt.clone(); - haveCoveredSportsCourt.where('escola.quadra_esportes_coberta = 1'); + haveCoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 1'); req.queryIndex.haveCoveredSportsCourt = req.querySet.push(haveCoveredSportsCourt) - 1; // Quadra Descoberta let allUncoveredSportsCourt = allSportsCourt.clone(); - allUncoveredSportsCourt.where('escola.quadra_esportes_coberta = 0'); + allUncoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 0'); req.queryIndex.allUncoveredSportsCourt = req.querySet.push(allUncoveredSportsCourt) - 1; let haveUncoveredSportsCourt = allUncoveredSportsCourt.clone(); - haveUncoveredSportsCourt.where('escola.quadra_esportes_descoberta = 1'); + haveUncoveredSportsCourt.where('escola_agregada.quadra_esportes_descoberta = 1'); req.queryIndex.haveUncoveredSportsCourt = req.querySet.push(haveUncoveredSportsCourt) - 1; // Sala de direção let allDirectorRoom = allSchools.clone(); - allDirectorRoom.where('escola.func_predio_escolar = 1 AND escola.localizacao_id = 1'); + allDirectorRoom.where('escola_agregada.func_predio_escolar = 1 AND escola_agregada.localizacao_id = 1'); req.queryIndex.allDirectorRoom = req.querySet.push(allDirectorRoom) - 1; let haveDirectorRoom = allDirectorRoom.clone(); - haveDirectorRoom.where('escola.sala_diretoria = 1'); + haveDirectorRoom.where('escola_agregada.sala_diretoria = 1'); req.queryIndex.haveDirectorRoom = req.querySet.push(haveDirectorRoom) - 1; // Secretaria let allSecretary = allSchools.clone(); - allSecretary.where('escola.func_predio_escolar = 1'); + allSecretary.where('escola_agregada.func_predio_escolar = 1'); req.queryIndex.allSecretary = req.querySet.push(allSecretary) - 1; let haveSecretary = allSecretary.clone(); - haveSecretary.where('escola.secretaria = 1'); + haveSecretary.where('escola_agregada.secretaria = 1'); req.queryIndex.haveSecretary = req.querySet.push(haveSecretary) - 1; // Sala de professores req.queryIndex.allTeacherRoom = req.queryIndex.allSecretary; let haveTeacherRoom = allSecretary.clone(); - haveTeacherRoom.where('escola.sala_professor = 1'); + haveTeacherRoom.where('escola_agregada.sala_professor = 1'); req.queryIndex.haveTeacherRoom = req.querySet.push(haveTeacherRoom) - 1; // Cozinha req.queryIndex.allKitchen = req.queryIndex.allSecretary; let haveKitchen = allSecretary.clone(); - haveKitchen.where('escola.cozinha = 1'); + haveKitchen.where('escola_agregada.cozinha = 1'); req.queryIndex.haveKitchen = req.querySet.push(haveKitchen) - 1; // Despensa req.queryIndex.allStoreroom = req.queryIndex.allSecretary; let haveStoreroom = allSecretary.clone(); - haveStoreroom.where('escola.despensa = 1'); + haveStoreroom.where('escola_agregada.despensa = 1'); req.queryIndex.haveStoreroom = req.querySet.push(haveStoreroom) - 1; // Almoxarifado req.queryIndex.allWarehouse = req.queryIndex.allSecretary; let haveWarehouse = allSecretary.clone(); - haveWarehouse.where('escola.almoxarifado = 1'); + haveWarehouse.where('escola_agregada.almoxarifado = 1'); req.queryIndex.haveWarehouse = req.querySet.push(haveWarehouse) - 1; // Internet req.queryIndex.allInternet = req.queryIndex.allLibrariesReadingRoom; let haveInternet = allLibrariesReadingRoom.clone(); - haveInternet.where('escola.internet = 1'); + haveInternet.where('escola_agregada.internet = 1'); req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1; // Internet banda larga req.queryIndex.allBroadbandInternet = req.queryIndex.allLibraries; let haveBroadbandInternet = allLibraries.clone(); - haveBroadbandInternet.where('escola.internet_banda_larga = 1'); + haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1'); req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1; // Banheiro dentro do prédio req.queryIndex.allInsideBathroom = req.queryIndex.allSecretary; let haveInsideBathroom = allSecretary.clone(); - haveInsideBathroom.where('escola.sanitario_dentro_predio = 1'); + haveInsideBathroom.where('escola_agregada.sanitario_dentro_predio = 1'); req.queryIndex.haveInsideBathroom = req.querySet.push(haveInsideBathroom) - 1; // Banheiro adequado para educação infantil dentro do prédio req.queryIndex.allInsideKidsBathroom = req.queryIndex.allKidsPark; let haveInsideKidsBathroom = allKidsPark.clone(); - haveInsideKidsBathroom.where('escola.sanitario_ei = 1'); + haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1'); req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1; // Fornecimento de energia req.queryIndex.allEletricEnergy = req.queryIndex.allSecretary; let haveEletricEnergy = allSecretary.clone(); - haveEletricEnergy.where('escola.fornecimento_energia = 1'); + haveEletricEnergy.where('escola_agregada.fornecimento_energia = 1'); req.queryIndex.haveEletricEnergy = req.querySet.push(haveEletricEnergy) - 1; // Abastecimento de água req.queryIndex.allWaterSupply = req.queryIndex.allSecretary; let haveWaterSupply = allSecretary.clone(); - haveWaterSupply.where('escola.fornecimento_agua = 1'); + haveWaterSupply.where('escola_agregada.fornecimento_agua = 1'); req.queryIndex.haveWaterSupply = req.querySet.push(haveWaterSupply) - 1; // Ãgua filtrada req.queryIndex.allFilteredWater = req.queryIndex.allSecretary; let haveFilteredWater = allSecretary.clone(); - haveFilteredWater.where('escola.agua_filtrada = 1'); + haveFilteredWater.where('escola_agregada.agua_filtrada = 1'); req.queryIndex.haveFilteredWater = req.querySet.push(haveFilteredWater) - 1; // Coleta de esgoto req.queryIndex.allSewage = req.queryIndex.allSecretary; let haveSewage = allSecretary.clone(); - haveSewage.where('escola.esgoto_sanitario = 1'); + haveSewage.where('escola_agregada.esgoto_sanitario = 1'); req.queryIndex.haveSewage = req.querySet.push(haveSewage) - 1; // Sala de recursos multifuncionais para Atendimento Educacional Especializado req.queryIndex.allMultifunctionRoom = req.queryIndex.allSecretary; let haveMultifunctionRoom = allSecretary.clone(); - haveMultifunctionRoom.where('escola.sala_atendimento_especial = 1'); + haveMultifunctionRoom.where('escola_agregada.sala_atendimento_especial = 1'); req.queryIndex.haveMultifunctionRoom = req.querySet.push(haveMultifunctionRoom) - 1; // Banheiros adaptados para pessoas com deficiências req.queryIndex.allSpecialBathroom = req.queryIndex.allSecretary; let haveSpecialBathroom = allSecretary.clone(); - haveSpecialBathroom.where('escola.sanitario_pne = 1'); + haveSpecialBathroom.where('escola_agregada.sanitario_pne = 1'); req.queryIndex.haveSpecialBathroom = req.querySet.push(haveSpecialBathroom) - 1; // Dependências adaptada para pessoas com deficiências req.queryIndex.allAdaptedBuilding = req.queryIndex.allSecretary; let haveAdaptedBuilding = allSecretary.clone(); - haveAdaptedBuilding.where('escola.dependencias_pne = 1'); + haveAdaptedBuilding.where('escola_agregada.dependencias_pne = 1'); req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1; next(); -- GitLab From 35cf2b8631f80ef06574f471471b603cee64d6cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 7 Mar 2023 11:10:24 -0300 Subject: [PATCH 063/123] Change class to use new table --- src/libs/routes_v2/class.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/routes_v2/class.js b/src/libs/routes_v2/class.js index 4eca8cc3..326bcf18 100644 --- a/src/libs/routes_v2/class.js +++ b/src/libs/routes_v2/class.js @@ -346,7 +346,7 @@ rqfCount.addField({ } }).addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: ['nome_escola', 'id'], resultField: ['school_name', 'school_id'], where: { @@ -361,7 +361,7 @@ rqfCount.addField({ } }, 'dims').addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: 'nome_escola', resultField: 'school_name', where: { -- GitLab From b0b494acd7097806e2ba584a68c5de8d776c9d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 23 Mar 2023 11:32:42 -0300 Subject: [PATCH 064/123] Create first report route --- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/simcaqFirstReport.js | 136 ++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 src/libs/routes_v2/simcaqFirstReport.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 906af9cf..5365e80e 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -134,6 +134,8 @@ const message = require(`${libs}/routes_v2/message`); const courseStudents = require(`${libs}/routes_v2/courseStudents`); +const simcaqFirstReport = require(`${libs}/routes_v2/simcaqFirstReport`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -192,5 +194,6 @@ api.use('/disciplines', disciplines); api.use('/universityLocalOffer', universityLocalOffer); api.use('/message', message); api.use('/course_students', courseStudents); +api.use('/simcaq_first_report', simcaqFirstReport); module.exports = api; diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js new file mode 100644 index 00000000..db300da5 --- /dev/null +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -0,0 +1,136 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqFirstReportApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +simcaqFirstReportApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'year', + table: 'simcaq_relatorio_1', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'adm_dependency', + table: 'simcaq_relatorio_1', + tableField: 'dependencia_adm_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'city', + table: 'simcaq_relatorio_1', + tableField: 'municipio_id', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id' + } +}).addValue({ + name: 'state', + table: 'simcaq_relatorio_1', + tableField: 'estado_id', + where: { + relation: '=', + type: 'integer', + field: 'estado_id' + } +}).addValue({ + name: 'school', + table: 'simcaq_relatorio_1', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'location', + table: 'simcaq_relatorio_1', + tableField: 'localizacao_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'stage', + table: 'simcaq_relatorio_1', + tableField: 'etapa', + where: { + relation: '=', + type: 'integer', + field: 'etapa' + } +}).addValue({ + name: 'shift', + table: 'simcaq_relatorio_1', + tableField: 'turno', + where: { + relation: '=', + type: 'integer', + field: 'turno' + } +}); + +simcaqFirstReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_relatorio_1') + .field('simcaq_relatorio_1.etapa', 'stage') + .field('simcaq_relatorio_1.turno', 'shift') + .field('simcaq_relatorio_1.localizacao_id', 'location') + .field('SUM(simcaq_relatorio_1.num_matriculas)', 'num_enrollments') + .field('SUM(simcaq_relatorio_1.num_escolas)', 'num_schools') + .group('simcaq_relatorio_1.etapa') + .group('simcaq_relatorio_1.turno') + .group('simcaq_relatorio_1.localizacao_id'); + next(); +}, query, response('simcaqFirstReport')); + +module.exports = simcaqFirstReportApp; -- GitLab From 9698bb016b7d6fa9bd168d46b393909a3053f0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 24 Mar 2023 11:48:03 -0300 Subject: [PATCH 065/123] Add enrollment diagnosis route --- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/enrollment_diagnosis.js | 133 +++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 src/libs/routes_v2/enrollment_diagnosis.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 5365e80e..071f8ffa 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -136,6 +136,8 @@ const courseStudents = require(`${libs}/routes_v2/courseStudents`); const simcaqFirstReport = require(`${libs}/routes_v2/simcaqFirstReport`); +const enrollmentDiagnosis = require(`${libs}/routes_v2/enrollment_diagnosis`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -195,5 +197,6 @@ api.use('/universityLocalOffer', universityLocalOffer); api.use('/message', message); api.use('/course_students', courseStudents); api.use('/simcaq_first_report', simcaqFirstReport); +api.use('/enrollment_diagnosis', enrollmentDiagnosis); module.exports = api; diff --git a/src/libs/routes_v2/enrollment_diagnosis.js b/src/libs/routes_v2/enrollment_diagnosis.js new file mode 100644 index 00000000..221549e5 --- /dev/null +++ b/src/libs/routes_v2/enrollment_diagnosis.js @@ -0,0 +1,133 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const enrollmentDiagnosisApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +enrollmentDiagnosisApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'year', + table: 'simcaq_diagnostico_de_matricula', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'simcaq_diagnostico_de_matricula', + tableField: 'municipio_id', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id' + } +}).addValue({ + name: 'state', + table: 'simcaq_diagnostico_de_matricula', + tableField: 'estado_id', + where: { + relation: '=', + type: 'integer', + field: 'estado_id' + } +}).addValue({ + name: 'school', + table: 'simcaq_diagnostico_de_matricula', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'stage', + table: 'simcaq_diagnostico_de_matricula', + tableField: 'etapa', + where: { + relation: '=', + type: 'integer', + field: 'etapa' + } +}).addValue({ + name: 'location', + table: 'simcaq_diagnostico_de_matricula', + tableField: 'localizacao_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'adm_dependency', + table: 'simcaq_diagnostico_de_matricula', + tableField: 'dependencia_adm_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}); + +enrollmentDiagnosisApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_diagnostico_de_matricula') + .field('simcaq_diagnostico_de_matricula.etapa', 'stage') + .field('SUM(simcaq_diagnostico_de_matricula.total)', 'total') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_federal)', 'federal_enrollments') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_estadual)', 'state_enrollments') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_municipal)', 'city_enrollments') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_priv_conv_sem_fin)', 'private_affiliated_non_profit_enrollments') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_priv_conv_com_fin)', 'private_affiliated_for_profit_enrollments') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_priv_nao_conv_sem_fin)', 'private_not_affiliated_non_profit_enrollments') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_priv_nao_conv_com_fin)', 'private_not_affiliated_for_profit_enrollments') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_urbana)', 'urban_enrollments') + .field('SUM(simcaq_diagnostico_de_matricula.matriculas_rural)', 'rural_enrollments') + .group('simcaq_diagnostico_de_matricula.etapa'); + + console.log(req.sql.toString()); + next(); +}, query, response('enrollmentDiagnosis')); + +module.exports = enrollmentDiagnosisApp; -- GitLab From 64a3d1b2ea3f4982dbd503885014b897a456eeab Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Mon, 27 Mar 2023 09:59:40 -0300 Subject: [PATCH 066/123] simcaq second report route added and some fixes --- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/simcaqFirstReport.js | 1 + src/libs/routes_v2/simcaqSecondReport.js | 110 +++++++++++++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 src/libs/routes_v2/simcaqSecondReport.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 071f8ffa..cb19b9a4 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -138,6 +138,8 @@ const simcaqFirstReport = require(`${libs}/routes_v2/simcaqFirstReport`); const enrollmentDiagnosis = require(`${libs}/routes_v2/enrollment_diagnosis`); +const simcaqSecondReport = require(`${libs}/routes_v2/simcaqSecondReport`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -198,5 +200,6 @@ api.use('/message', message); api.use('/course_students', courseStudents); api.use('/simcaq_first_report', simcaqFirstReport); api.use('/enrollment_diagnosis', enrollmentDiagnosis); +api.use('/simcaq_second_report', simcaqSecondReport); module.exports = api; diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js index db300da5..c4c4b978 100644 --- a/src/libs/routes_v2/simcaqFirstReport.js +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -127,6 +127,7 @@ simcaqFirstReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .field('simcaq_relatorio_1.localizacao_id', 'location') .field('SUM(simcaq_relatorio_1.num_matriculas)', 'num_enrollments') .field('SUM(simcaq_relatorio_1.num_escolas)', 'num_schools') + .where('situacao_funcionamento_pareada = 1 AND (ensino_regular = 1 OR ensino_eja = 1 OR educacao_profissional = 1)') .group('simcaq_relatorio_1.etapa') .group('simcaq_relatorio_1.turno') .group('simcaq_relatorio_1.localizacao_id'); diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js new file mode 100644 index 00000000..51907e33 --- /dev/null +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -0,0 +1,110 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqSecondReportApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +simcaqSecondReportApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addValue({ + name: 'year', + table: 'simcaq_relatorio_2', + tableField: 'ano_censo', + where : { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'school', + table: 'simcaq_relatorio_2', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + } +}).addValue({ + name: 'city', + table:'simcaq_relatorio_2', + tableField: 'municipio_id', + where: { + relation: '=', + type: 'integer', + field: 'municipio_id' + } +}).addValue({ + name: 'adm_dependency', + table: 'simcaq_relatorio_2', + tableField: 'dependencia_adm_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'state', + table: 'simcaq_relatorio_2', + tableField: 'estado_id', + where: { + relation: '=', + type: 'integer', + field: 'estado_id' + } +}); + +simcaqSecondReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_relatorio_2') + .field('sum(num_matriculas_total)' ,'num_enrollments_total') + .field('sum(num_matriculas_rural)' ,'num_enrollments_rural') + .field('sum(num_matriculas_urbana)' ,'num_enrollments_urban') + .field('sum(num_escolas_total)' ,'num_schools_total') + .field('sum(num_escolas_rural)' ,'num_schools_rural') + .field('sum(num_escolas_urbana)' ,'num_schools_urban') + .field('dependencia_adm_priv', 'private_adm_dependency') + .where('situacao_funcionamento_pareada = 1 AND (ensino_regular = 1 OR ensino_eja = 1 OR educacao_profissional = 1)') + .group('dependencia_adm_priv') + next(); +}, query, response('simcaqSecondReport')); + +module.exports = simcaqSecondReportApp; -- GitLab From fd0274da876fd97cddd493b3a4bc1f0c48de7872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 27 Mar 2023 11:10:07 -0300 Subject: [PATCH 067/123] Fix issue with private_adm_dependency --- src/libs/routes_v2/simcaqFirstReport.js | 1 - src/libs/routes_v2/simcaqSecondReport.js | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js index c4c4b978..db300da5 100644 --- a/src/libs/routes_v2/simcaqFirstReport.js +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -127,7 +127,6 @@ simcaqFirstReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .field('simcaq_relatorio_1.localizacao_id', 'location') .field('SUM(simcaq_relatorio_1.num_matriculas)', 'num_enrollments') .field('SUM(simcaq_relatorio_1.num_escolas)', 'num_schools') - .where('situacao_funcionamento_pareada = 1 AND (ensino_regular = 1 OR ensino_eja = 1 OR educacao_profissional = 1)') .group('simcaq_relatorio_1.etapa') .group('simcaq_relatorio_1.turno') .group('simcaq_relatorio_1.localizacao_id'); diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js index 51907e33..6babe383 100644 --- a/src/libs/routes_v2/simcaqSecondReport.js +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -102,8 +102,7 @@ simcaqSecondReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .field('sum(num_escolas_rural)' ,'num_schools_rural') .field('sum(num_escolas_urbana)' ,'num_schools_urban') .field('dependencia_adm_priv', 'private_adm_dependency') - .where('situacao_funcionamento_pareada = 1 AND (ensino_regular = 1 OR ensino_eja = 1 OR educacao_profissional = 1)') - .group('dependencia_adm_priv') + .group('dependencia_adm_priv'); next(); }, query, response('simcaqSecondReport')); -- GitLab From 9c7176ac43d91d9b2c4764db337b6cd9afada9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 27 Mar 2023 11:23:58 -0300 Subject: [PATCH 068/123] Fix routes to use escola_id field instead of id, removed unnecessary console logs --- src/libs/routes_v2/api.js | 4 ++-- ...t_diagnosis.js => simcaqEnrollmentDiagnosis.js} | 14 ++++++-------- src/libs/routes_v2/simcaqFirstReport.js | 4 ++-- src/libs/routes_v2/simcaqSecondReport.js | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-) rename src/libs/routes_v2/{enrollment_diagnosis.js => simcaqEnrollmentDiagnosis.js} (93%) diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index cb19b9a4..f6804584 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -136,7 +136,7 @@ const courseStudents = require(`${libs}/routes_v2/courseStudents`); const simcaqFirstReport = require(`${libs}/routes_v2/simcaqFirstReport`); -const enrollmentDiagnosis = require(`${libs}/routes_v2/enrollment_diagnosis`); +const simcaqEnrollmentDiagnosis = require(`${libs}/routes_v2/simcaqEnrollmentDiagnosis`); const simcaqSecondReport = require(`${libs}/routes_v2/simcaqSecondReport`); @@ -199,7 +199,7 @@ api.use('/universityLocalOffer', universityLocalOffer); api.use('/message', message); api.use('/course_students', courseStudents); api.use('/simcaq_first_report', simcaqFirstReport); -api.use('/enrollment_diagnosis', enrollmentDiagnosis); +api.use('/simcaq_enrollment_diagnosis', simcaqEnrollmentDiagnosis); api.use('/simcaq_second_report', simcaqSecondReport); module.exports = api; diff --git a/src/libs/routes_v2/enrollment_diagnosis.js b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js similarity index 93% rename from src/libs/routes_v2/enrollment_diagnosis.js rename to src/libs/routes_v2/simcaqEnrollmentDiagnosis.js index 221549e5..bd23cf25 100644 --- a/src/libs/routes_v2/enrollment_diagnosis.js +++ b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js @@ -20,7 +20,7 @@ along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. const express = require('express'); -const enrollmentDiagnosisApp = express.Router(); +const simcaqEnrollmentDiagnosisApp = express.Router(); const libs = `${process.cwd()}/libs`; @@ -40,7 +40,7 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i let rqf = new ReqQueryFields(); -enrollmentDiagnosisApp.use(cache('15 day')); +simcaqEnrollmentDiagnosisApp.use(cache('15 day')); rqf.addField({ name: 'filter', @@ -76,11 +76,11 @@ rqf.addField({ }).addValue({ name: 'school', table: 'simcaq_diagnostico_de_matricula', - tableField: 'id', + tableField: 'escola_id', where: { relation: '=', type: 'integer', - field: 'id' + field: 'escola_id' } }).addValue({ name: 'stage', @@ -111,7 +111,7 @@ rqf.addField({ } }); -enrollmentDiagnosisApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { +simcaqEnrollmentDiagnosisApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.sql.from('simcaq_diagnostico_de_matricula') .field('simcaq_diagnostico_de_matricula.etapa', 'stage') .field('SUM(simcaq_diagnostico_de_matricula.total)', 'total') @@ -125,9 +125,7 @@ enrollmentDiagnosisApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .field('SUM(simcaq_diagnostico_de_matricula.matriculas_urbana)', 'urban_enrollments') .field('SUM(simcaq_diagnostico_de_matricula.matriculas_rural)', 'rural_enrollments') .group('simcaq_diagnostico_de_matricula.etapa'); - - console.log(req.sql.toString()); next(); }, query, response('enrollmentDiagnosis')); -module.exports = enrollmentDiagnosisApp; +module.exports = simcaqEnrollmentDiagnosisApp; diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js index db300da5..b6bde164 100644 --- a/src/libs/routes_v2/simcaqFirstReport.js +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -85,11 +85,11 @@ rqf.addField({ }).addValue({ name: 'school', table: 'simcaq_relatorio_1', - tableField: 'id', + tableField: 'escola_id', where: { relation: '=', type: 'integer', - field: 'id' + field: 'escola_id' } }).addValue({ name: 'location', diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js index 6babe383..fdd583d6 100644 --- a/src/libs/routes_v2/simcaqSecondReport.js +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -58,11 +58,11 @@ rqf.addField({ }).addValue({ name: 'school', table: 'simcaq_relatorio_2', - tableField: 'id', + tableField: 'escola_id', where: { relation: '=', type: 'integer', - field: 'id' + field: 'escola_id' } }).addValue({ name: 'city', -- GitLab From 94f3e0e818db144c46ef0fa1e4b2a648bf5c8f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 27 Mar 2023 11:37:40 -0300 Subject: [PATCH 069/123] add year field to new routes default queries --- src/libs/routes_v2/simcaqEnrollmentDiagnosis.js | 6 ++++-- src/libs/routes_v2/simcaqFirstReport.js | 6 ++++-- src/libs/routes_v2/simcaqSecondReport.js | 2 ++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js index bd23cf25..7c13d9b4 100644 --- a/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js +++ b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js @@ -83,7 +83,7 @@ rqf.addField({ field: 'escola_id' } }).addValue({ - name: 'stage', + name: 'education_level_short_id', table: 'simcaq_diagnostico_de_matricula', tableField: 'etapa', where: { @@ -113,7 +113,7 @@ rqf.addField({ simcaqEnrollmentDiagnosisApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.sql.from('simcaq_diagnostico_de_matricula') - .field('simcaq_diagnostico_de_matricula.etapa', 'stage') + .field('simcaq_diagnostico_de_matricula.etapa', 'education_level_short_id') .field('SUM(simcaq_diagnostico_de_matricula.total)', 'total') .field('SUM(simcaq_diagnostico_de_matricula.matriculas_federal)', 'federal_enrollments') .field('SUM(simcaq_diagnostico_de_matricula.matriculas_estadual)', 'state_enrollments') @@ -124,6 +124,8 @@ simcaqEnrollmentDiagnosisApp.get('/', rqf.parse(), rqf.build(), (req, res, next) .field('SUM(simcaq_diagnostico_de_matricula.matriculas_priv_nao_conv_com_fin)', 'private_not_affiliated_for_profit_enrollments') .field('SUM(simcaq_diagnostico_de_matricula.matriculas_urbana)', 'urban_enrollments') .field('SUM(simcaq_diagnostico_de_matricula.matriculas_rural)', 'rural_enrollments') + .field('ano_censo', 'year') + .group('ano_censo') .group('simcaq_diagnostico_de_matricula.etapa'); next(); }, query, response('enrollmentDiagnosis')); diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js index b6bde164..b3bca02b 100644 --- a/src/libs/routes_v2/simcaqFirstReport.js +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -101,7 +101,7 @@ rqf.addField({ field: 'localizacao_id' } }).addValue({ - name: 'stage', + name: 'education_level_short_id', table: 'simcaq_relatorio_1', tableField: 'etapa', where: { @@ -122,11 +122,13 @@ rqf.addField({ simcaqFirstReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.sql.from('simcaq_relatorio_1') - .field('simcaq_relatorio_1.etapa', 'stage') + .field('simcaq_relatorio_1.etapa', 'education_level_short_id') .field('simcaq_relatorio_1.turno', 'shift') .field('simcaq_relatorio_1.localizacao_id', 'location') .field('SUM(simcaq_relatorio_1.num_matriculas)', 'num_enrollments') .field('SUM(simcaq_relatorio_1.num_escolas)', 'num_schools') + .field('ano_censo', 'year') + .group('ano_censo') .group('simcaq_relatorio_1.etapa') .group('simcaq_relatorio_1.turno') .group('simcaq_relatorio_1.localizacao_id'); diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js index fdd583d6..1aa89412 100644 --- a/src/libs/routes_v2/simcaqSecondReport.js +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -102,6 +102,8 @@ simcaqSecondReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .field('sum(num_escolas_rural)' ,'num_schools_rural') .field('sum(num_escolas_urbana)' ,'num_schools_urban') .field('dependencia_adm_priv', 'private_adm_dependency') + .field('ano_censo', 'year') + .group('ano_censo') .group('dependencia_adm_priv'); next(); }, query, response('simcaqSecondReport')); -- GitLab From 2a51e27ecc5e487c1c1d4a5205a4d2f0e25f3a1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 28 Mar 2023 09:48:11 -0300 Subject: [PATCH 070/123] Add shift converter --- src/libs/convert/shift.js | 30 +++++++++++++++++++++++++ src/libs/middlewares/id2str.js | 7 ++++-- src/libs/routes_v2/simcaqFirstReport.js | 13 ++++++++--- 3 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 src/libs/convert/shift.js diff --git a/src/libs/convert/shift.js b/src/libs/convert/shift.js new file mode 100644 index 00000000..effe0a52 --- /dev/null +++ b/src/libs/convert/shift.js @@ -0,0 +1,30 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +module.exports = function shift(id) { + switch(id) { + case 1: + return 'Parcial'; + case 2: + return 'Integral'; + default: + return 'Não especificado'; + } +} \ No newline at end of file diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js index bd5c83c0..b59f6463 100644 --- a/src/libs/middlewares/id2str.js +++ b/src/libs/middlewares/id2str.js @@ -95,6 +95,7 @@ const enrollmentSituation = require(`${libs}/convert/enrollmentSituation`); const diffLocation = require(`${libs}/convert/diffLocation`); const peePorCategoria = require(`${libs}/convert/peePorCategoria`); const pee = require(`${libs}/convert/booleanVariable`); +const shift = require(`${libs}/convert/shift`); const ids = { gender_id: gender, @@ -181,7 +182,8 @@ const ids = { enrollment_situation: enrollmentSituation, diff_location_id: diffLocation, pee_por_categoria: peePorCategoria, - pee_id: pee + pee_id: pee, + shift_id: shift }; function transform(removeId=false) { @@ -295,5 +297,6 @@ module.exports = { enrollmentSituation, diffLocation, peePorCategoria, - pee + pee, + shift }; diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js index b3bca02b..7f99fbd6 100644 --- a/src/libs/routes_v2/simcaqFirstReport.js +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -40,6 +40,8 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i let rqf = new ReqQueryFields(); +const id2str = require(`${libs}/middlewares/id2str`); + simcaqFirstReportApp.use(cache('15 day')); rqf.addField({ @@ -110,7 +112,7 @@ rqf.addField({ field: 'etapa' } }).addValue({ - name: 'shift', + name: 'shift_id', table: 'simcaq_relatorio_1', tableField: 'turno', where: { @@ -123,7 +125,7 @@ rqf.addField({ simcaqFirstReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.sql.from('simcaq_relatorio_1') .field('simcaq_relatorio_1.etapa', 'education_level_short_id') - .field('simcaq_relatorio_1.turno', 'shift') + .field('simcaq_relatorio_1.turno', 'shift_id') .field('simcaq_relatorio_1.localizacao_id', 'location') .field('SUM(simcaq_relatorio_1.num_matriculas)', 'num_enrollments') .field('SUM(simcaq_relatorio_1.num_escolas)', 'num_schools') @@ -133,6 +135,11 @@ simcaqFirstReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .group('simcaq_relatorio_1.turno') .group('simcaq_relatorio_1.localizacao_id'); next(); -}, query, response('simcaqFirstReport')); +}, query, (req, res, next) => { + req.result.forEach((result) => { + result.shift = id2str.shift(result.shift_id); + }); + next(); +}, response('simcaqFirstReport')); module.exports = simcaqFirstReportApp; -- GitLab From 0d7b853a2ad2ef97a70c3ab1dd6d379e486d16ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 28 Mar 2023 10:38:01 -0300 Subject: [PATCH 071/123] Add dimensions to first report route --- src/libs/routes_v2/simcaqFirstReport.js | 43 ++++++++++++++++++------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js index 7f99fbd6..16640eee 100644 --- a/src/libs/routes_v2/simcaqFirstReport.js +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -48,6 +48,10 @@ rqf.addField({ name: 'filter', field: false, where: true +}).addField({ + name: 'dims', + field: true, + where: false }).addValue({ name: 'year', table: 'simcaq_relatorio_1', @@ -68,32 +72,47 @@ rqf.addField({ } }).addValue({ name: 'city', - table: 'simcaq_relatorio_1', - tableField: 'municipio_id', + table: 'municipio', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'municipio_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_relatorio_1' } -}).addValue({ +}, 'dims').addValue({ name: 'state', - table: 'simcaq_relatorio_1', - tableField: 'estado_id', + table: 'estado', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'estado_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_relatorio_1' } -}).addValue({ +}, 'dims').addValue({ name: 'school', - table: 'simcaq_relatorio_1', - tableField: 'escola_id', + table: 'escola_agregada', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'escola_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_relatorio_1' } -}).addValue({ +}, 'dims').addValue({ name: 'location', table: 'simcaq_relatorio_1', tableField: 'localizacao_id', -- GitLab From b993f5cd9cddee5a576d03e655af6ed582d0d9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 28 Mar 2023 10:44:51 -0300 Subject: [PATCH 072/123] Add dims to second report and enrollment diagnosis routes --- .../routes_v2/simcaqEnrollmentDiagnosis.js | 43 +++++++++++---- src/libs/routes_v2/simcaqSecondReport.js | 55 +++++++++++++------ 2 files changed, 68 insertions(+), 30 deletions(-) diff --git a/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js index 7c13d9b4..1fb30b61 100644 --- a/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js +++ b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js @@ -46,6 +46,10 @@ rqf.addField({ name: 'filter', field: false, where: true +}).addField({ + name: 'dims', + field: true, + where: false }).addValue({ name: 'year', table: 'simcaq_diagnostico_de_matricula', @@ -57,32 +61,47 @@ rqf.addField({ } }).addValue({ name: 'city', - table: 'simcaq_diagnostico_de_matricula', - tableField: 'municipio_id', + table: 'municipio', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'municipio_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_diagnostico_de_matricula' } -}).addValue({ +}, 'dims').addValue({ name: 'state', - table: 'simcaq_diagnostico_de_matricula', - tableField: 'estado_id', + table: 'estado', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'estado_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_diagnostico_de_matricula' } -}).addValue({ +}, 'dims').addValue({ name: 'school', - table: 'simcaq_diagnostico_de_matricula', - tableField: 'escola_id', + table: 'escola_agregada', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'escola_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_diagnostico_de_matricula' } -}).addValue({ +}, 'dims').addValue({ name: 'education_level_short_id', table: 'simcaq_diagnostico_de_matricula', tableField: 'etapa', diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js index 1aa89412..ccdd2f9b 100644 --- a/src/libs/routes_v2/simcaqSecondReport.js +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -46,6 +46,10 @@ rqf.addField({ name: 'filter', field: false, where: true +}).addField({ + name: 'dims', + field: true, + where: false }).addValue({ name: 'year', table: 'simcaq_relatorio_2', @@ -56,40 +60,55 @@ rqf.addField({ field: 'ano_censo' } }).addValue({ - name: 'school', - table: 'simcaq_relatorio_2', - tableField: 'escola_id', + name: 'city', + table: 'municipio', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'escola_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_relatorio_2' } -}).addValue({ - name: 'city', - table:'simcaq_relatorio_2', - tableField: 'municipio_id', +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'municipio_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_relatorio_2' } -}).addValue({ - name: 'adm_dependency', - table: 'simcaq_relatorio_2', - tableField: 'dependencia_adm_id', +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', where: { relation: '=', type: 'integer', - field: 'dependencia_adm_id' + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_relatorio_2' } -}).addValue({ - name: 'state', +}, 'dims').addValue({ + name: 'adm_dependency', table: 'simcaq_relatorio_2', - tableField: 'estado_id', + tableField: 'dependencia_adm_id', where: { relation: '=', type: 'integer', - field: 'estado_id' + field: 'dependencia_adm_id' } }); -- GitLab From c372fbacadf1a5161aa9d3b4201041bade07acc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 28 Mar 2023 11:37:11 -0300 Subject: [PATCH 073/123] Fix issue when calling id2str methods --- src/libs/routes_v2/simcaqEnrollmentDiagnosis.js | 4 +++- src/libs/routes_v2/simcaqFirstReport.js | 9 ++------- src/libs/routes_v2/simcaqSecondReport.js | 4 +++- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js index 1fb30b61..d77aa191 100644 --- a/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js +++ b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js @@ -40,6 +40,8 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i let rqf = new ReqQueryFields(); +const id2str = require(`${libs}/middlewares/id2str`); + simcaqEnrollmentDiagnosisApp.use(cache('15 day')); rqf.addField({ @@ -147,6 +149,6 @@ simcaqEnrollmentDiagnosisApp.get('/', rqf.parse(), rqf.build(), (req, res, next) .group('ano_censo') .group('simcaq_diagnostico_de_matricula.etapa'); next(); -}, query, response('enrollmentDiagnosis')); +}, query, id2str.transform(), response('enrollmentDiagnosis')); module.exports = simcaqEnrollmentDiagnosisApp; diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js index 16640eee..d8e3cf0f 100644 --- a/src/libs/routes_v2/simcaqFirstReport.js +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -145,7 +145,7 @@ simcaqFirstReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.sql.from('simcaq_relatorio_1') .field('simcaq_relatorio_1.etapa', 'education_level_short_id') .field('simcaq_relatorio_1.turno', 'shift_id') - .field('simcaq_relatorio_1.localizacao_id', 'location') + .field('simcaq_relatorio_1.localizacao_id', 'location_id') .field('SUM(simcaq_relatorio_1.num_matriculas)', 'num_enrollments') .field('SUM(simcaq_relatorio_1.num_escolas)', 'num_schools') .field('ano_censo', 'year') @@ -154,11 +154,6 @@ simcaqFirstReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .group('simcaq_relatorio_1.turno') .group('simcaq_relatorio_1.localizacao_id'); next(); -}, query, (req, res, next) => { - req.result.forEach((result) => { - result.shift = id2str.shift(result.shift_id); - }); - next(); -}, response('simcaqFirstReport')); +}, query, id2str.transform(), response('simcaqFirstReport')); module.exports = simcaqFirstReportApp; diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js index ccdd2f9b..4e8e75f9 100644 --- a/src/libs/routes_v2/simcaqSecondReport.js +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -40,6 +40,8 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i let rqf = new ReqQueryFields(); +const id2str = require(`${libs}/middlewares/id2str`); + simcaqSecondReportApp.use(cache('15 day')); rqf.addField({ @@ -125,6 +127,6 @@ simcaqSecondReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .group('ano_censo') .group('dependencia_adm_priv'); next(); -}, query, response('simcaqSecondReport')); +}, query, id2str.transform(), response('simcaqSecondReport')); module.exports = simcaqSecondReportApp; -- GitLab From ea6c6101497305d915be38f42c68adf573a7437d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 28 Mar 2023 11:56:53 -0300 Subject: [PATCH 074/123] Fix issue with id2str in simcaqSecondReport route --- src/libs/routes_v2/simcaqSecondReport.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js index 4e8e75f9..cfe27ddd 100644 --- a/src/libs/routes_v2/simcaqSecondReport.js +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -122,7 +122,7 @@ simcaqSecondReportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .field('sum(num_escolas_total)' ,'num_schools_total') .field('sum(num_escolas_rural)' ,'num_schools_rural') .field('sum(num_escolas_urbana)' ,'num_schools_urban') - .field('dependencia_adm_priv', 'private_adm_dependency') + .field('dependencia_adm_priv', 'adm_dependency_detailed_id') .field('ano_censo', 'year') .group('ano_censo') .group('dependencia_adm_priv'); -- GitLab From e05e3e4af7ccf99640d2dbc8c016008ad36d9b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 30 Mar 2023 09:17:51 -0300 Subject: [PATCH 075/123] Add division of responsibility route --- src/libs/convert/admDependencyPub.js | 32 +++++ src/libs/middlewares/id2str.js | 5 +- src/libs/routes_v2/api.js | 3 + .../simcaqDivisionOfResponsibility.js | 127 ++++++++++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 src/libs/convert/admDependencyPub.js create mode 100644 src/libs/routes_v2/simcaqDivisionOfResponsibility.js diff --git a/src/libs/convert/admDependencyPub.js b/src/libs/convert/admDependencyPub.js new file mode 100644 index 00000000..0522b237 --- /dev/null +++ b/src/libs/convert/admDependencyPub.js @@ -0,0 +1,32 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +module.exports = function admDependencyPub(id) { + switch (id) { + case 1: + return 'Rede pública'; + case 2: + return 'Rede estadual'; + case 3: + return 'Rede municipal'; + default: + return 'Não classificada'; + } +}; diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js index b59f6463..43cc1e0f 100644 --- a/src/libs/middlewares/id2str.js +++ b/src/libs/middlewares/id2str.js @@ -96,6 +96,7 @@ const diffLocation = require(`${libs}/convert/diffLocation`); const peePorCategoria = require(`${libs}/convert/peePorCategoria`); const pee = require(`${libs}/convert/booleanVariable`); const shift = require(`${libs}/convert/shift`); +const admDependencyPub = require(`${libs}/convert/admDependencyPub`); const ids = { gender_id: gender, @@ -107,6 +108,7 @@ const ids = { education_level_short_id: educationLevelShort, adm_dependency_id: admDependency, adm_dependency_detailed_id: admDependencyPriv, + adm_dependency_public_id: admDependencyPub, location_id: location, rural_location_id: ruralLocation, location_detailed_id: ruralLocation, @@ -298,5 +300,6 @@ module.exports = { diffLocation, peePorCategoria, pee, - shift + shift, + admDependencyPub }; diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index f6804584..33822b82 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -140,6 +140,8 @@ const simcaqEnrollmentDiagnosis = require(`${libs}/routes_v2/simcaqEnrollmentDia const simcaqSecondReport = require(`${libs}/routes_v2/simcaqSecondReport`); +const simcaqDivisionOfResponsibility = require(`${libs}/routes_v2/simcaqDivisionOfResponsibility`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -201,5 +203,6 @@ api.use('/course_students', courseStudents); api.use('/simcaq_first_report', simcaqFirstReport); api.use('/simcaq_enrollment_diagnosis', simcaqEnrollmentDiagnosis); api.use('/simcaq_second_report', simcaqSecondReport); +api.use('/simcaq_division_of_responsibility', simcaqDivisionOfResponsibility); module.exports = api; diff --git a/src/libs/routes_v2/simcaqDivisionOfResponsibility.js b/src/libs/routes_v2/simcaqDivisionOfResponsibility.js new file mode 100644 index 00000000..e115ed41 --- /dev/null +++ b/src/libs/routes_v2/simcaqDivisionOfResponsibility.js @@ -0,0 +1,127 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqDivisionOfResponsibilityApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqDivisionOfResponsibilityApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_divisao_de_responsabilidade' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_divisao_de_responsabilidade' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_divisao_de_responsabilidade' + } +}, 'dims').addValue({ + name: 'education_level_short_id', + table: 'simcaq_divisao_de_responsabilidade', + tableField: 'etapa', + where: { + relation: '=', + type: 'integer', + field: 'etapa' + } +}).addValue({ + name: 'adm_dependency_public_id', + table: 'simcaq_divisao_de_responsabilidade', + tableField: 'rede', + where: { + relation: '=', + type: 'integer', + field: 'rede' + } +}); + +simcaqDivisionOfResponsibilityApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_divisao_de_responsabilidade') + .field('SUM(simcaq_divisao_de_responsabilidade.total_matriculas)', 'enrollments') + .field('simcaq_divisao_de_responsabilidade.etapa', 'education_level_short_id') + .field('simcaq_divisao_de_responsabilidade.rede', 'adm_dependency_public_id') + .group('simcaq_divisao_de_responsabilidade.etapa') + .group('simcaq_divisao_de_responsabilidade.rede'); + next(); +}, query, id2str.transform(), response('divisionOfResponsibility')); + +module.exports = simcaqDivisionOfResponsibilityApp; -- GitLab From c310e021602b30c40c1a4fbfdba78014c6bf5661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 3 Apr 2023 11:00:49 -0300 Subject: [PATCH 076/123] Add city_name, city_id, state_name, state_id fields to new routes --- src/libs/routes_v2/simcaqDivisionOfResponsibility.js | 6 ++++-- src/libs/routes_v2/simcaqEnrollmentDiagnosis.js | 6 ++++-- src/libs/routes_v2/simcaqFirstReport.js | 6 ++++-- src/libs/routes_v2/simcaqSecondReport.js | 6 ++++-- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/libs/routes_v2/simcaqDivisionOfResponsibility.js b/src/libs/routes_v2/simcaqDivisionOfResponsibility.js index e115ed41..ca7b7c12 100644 --- a/src/libs/routes_v2/simcaqDivisionOfResponsibility.js +++ b/src/libs/routes_v2/simcaqDivisionOfResponsibility.js @@ -55,7 +55,8 @@ rqf.addField({ }).addValue({ name: 'city', table: 'municipio', - tableField: 'id', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], where: { relation: '=', type: 'integer', @@ -69,7 +70,8 @@ rqf.addField({ }, 'dims').addValue({ name: 'state', table: 'estado', - tableField: 'id', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], where: { relation: '=', type: 'integer', diff --git a/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js index d77aa191..1d6c7082 100644 --- a/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js +++ b/src/libs/routes_v2/simcaqEnrollmentDiagnosis.js @@ -64,7 +64,8 @@ rqf.addField({ }).addValue({ name: 'city', table: 'municipio', - tableField: 'id', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], where: { relation: '=', type: 'integer', @@ -78,7 +79,8 @@ rqf.addField({ }, 'dims').addValue({ name: 'state', table: 'estado', - tableField: 'id', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], where: { relation: '=', type: 'integer', diff --git a/src/libs/routes_v2/simcaqFirstReport.js b/src/libs/routes_v2/simcaqFirstReport.js index d8e3cf0f..6c037cf4 100644 --- a/src/libs/routes_v2/simcaqFirstReport.js +++ b/src/libs/routes_v2/simcaqFirstReport.js @@ -73,7 +73,8 @@ rqf.addField({ }).addValue({ name: 'city', table: 'municipio', - tableField: 'id', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], where: { relation: '=', type: 'integer', @@ -87,7 +88,8 @@ rqf.addField({ }, 'dims').addValue({ name: 'state', table: 'estado', - tableField: 'id', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], where: { relation: '=', type: 'integer', diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js index cfe27ddd..4c30f8d1 100644 --- a/src/libs/routes_v2/simcaqSecondReport.js +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -64,7 +64,8 @@ rqf.addField({ }).addValue({ name: 'city', table: 'municipio', - tableField: 'id', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], where: { relation: '=', type: 'integer', @@ -78,7 +79,8 @@ rqf.addField({ }, 'dims').addValue({ name: 'state', table: 'estado', - tableField: 'id', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], where: { relation: '=', type: 'integer', -- GitLab From 28fb8ec67946673b55d66528fad3425e1f12d551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 3 Apr 2023 11:44:20 -0300 Subject: [PATCH 077/123] Add year filter to the division of responsibility route --- src/libs/routes_v2/simcaqDivisionOfResponsibility.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libs/routes_v2/simcaqDivisionOfResponsibility.js b/src/libs/routes_v2/simcaqDivisionOfResponsibility.js index ca7b7c12..3ec798e3 100644 --- a/src/libs/routes_v2/simcaqDivisionOfResponsibility.js +++ b/src/libs/routes_v2/simcaqDivisionOfResponsibility.js @@ -52,6 +52,15 @@ rqf.addField({ name: 'dims', field: true, where: false +}).addValue({ + name: 'year', + table: 'simcaq_divisao_de_responsabilidade', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } }).addValue({ name: 'city', table: 'municipio', -- GitLab From 84417f1e21a6acbdfd5974505420be04df740f35 Mon Sep 17 00:00:00 2001 From: ppc19 <ppc19@inf.ufpr.br> Date: Tue, 4 Apr 2023 09:52:10 -0300 Subject: [PATCH 078/123] add year field to division of responsibility route --- src/libs/routes_v2/simcaqDivisionOfResponsibility.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/routes_v2/simcaqDivisionOfResponsibility.js b/src/libs/routes_v2/simcaqDivisionOfResponsibility.js index 3ec798e3..b9704b3b 100644 --- a/src/libs/routes_v2/simcaqDivisionOfResponsibility.js +++ b/src/libs/routes_v2/simcaqDivisionOfResponsibility.js @@ -127,9 +127,11 @@ rqf.addField({ simcaqDivisionOfResponsibilityApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.sql.from('simcaq_divisao_de_responsabilidade') + .field('simcaq_divisao_de_responsabilidade.ano_censo', 'year') .field('SUM(simcaq_divisao_de_responsabilidade.total_matriculas)', 'enrollments') .field('simcaq_divisao_de_responsabilidade.etapa', 'education_level_short_id') .field('simcaq_divisao_de_responsabilidade.rede', 'adm_dependency_public_id') + .group('simcaq_divisao_de_responsabilidade.ano_censo') .group('simcaq_divisao_de_responsabilidade.etapa') .group('simcaq_divisao_de_responsabilidade.rede'); next(); -- GitLab From c5362aa09fd121c80e9f3a142e0d8abe89d2cf51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 4 Apr 2023 11:43:27 -0300 Subject: [PATCH 079/123] Add simcaq classroom size route --- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/simcaqClassroomSize.js | 147 ++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 src/libs/routes_v2/simcaqClassroomSize.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 33822b82..872274fe 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -142,6 +142,8 @@ const simcaqSecondReport = require(`${libs}/routes_v2/simcaqSecondReport`); const simcaqDivisionOfResponsibility = require(`${libs}/routes_v2/simcaqDivisionOfResponsibility`); +const simcaqClassroomSize = require(`${libs}/routes_v2/simcaqClassroomSize`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -204,5 +206,6 @@ api.use('/simcaq_first_report', simcaqFirstReport); api.use('/simcaq_enrollment_diagnosis', simcaqEnrollmentDiagnosis); api.use('/simcaq_second_report', simcaqSecondReport); api.use('/simcaq_division_of_responsibility', simcaqDivisionOfResponsibility); +api.use('/simcaq_classroom_size', simcaqClassroomSize); module.exports = api; diff --git a/src/libs/routes_v2/simcaqClassroomSize.js b/src/libs/routes_v2/simcaqClassroomSize.js new file mode 100644 index 00000000..9b48f3b3 --- /dev/null +++ b/src/libs/routes_v2/simcaqClassroomSize.js @@ -0,0 +1,147 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqClassroomSizeApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqClassroomSizeApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_tamanho_das_turmas' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_tamanho_das_turmas' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_tamanho_das_turmas' + } +}, 'dims').addValue({ + name: 'education_level_short_id', + table: 'simcaq_tamanho_das_turmas', + tableField: 'etapa', + where: { + relation: '=', + type: 'integer', + field: 'etapa' + } +}).addValue({ + name: 'location', + table: 'simcaq_tamanho_das_turmas', + tableField: 'localizacao_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'adm_dependency_public_id', + table: 'simcaq_tamanho_das_turmas', + tableField: 'rede', + where: { + relation: '=', + type: 'integer', + field: 'rede' + } +}).addValue({ + name: 'year', + table: 'simcaq_tamanho_das_turmas', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}); + +simcaqClassroomSizeApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_tamanho_das_turmas') + .field('AVG(simcaq_tamanho_das_turmas.num_matricula)', 'average_classroom_size') + .field('simcaq_tamanho_das_turmas.etapa', 'education_level_short_id') + .field('simcaq_tamanho_das_turmas.ano_censo', 'year') + .group('simcaq_tamanho_das_turmas.ano_censo') + .group('simcaq_tamanho_das_turmas.etapa'); + next(); +}, query, id2str.transform(), response('classroomSize')); + +module.exports = simcaqClassroomSizeApp; -- GitLab From e8a005b4474582efcef0e1acdbd2858a608cd7a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 6 Apr 2023 10:03:58 -0300 Subject: [PATCH 080/123] Add workload and number of employees routes --- src/libs/routes_v2/api.js | 6 + src/libs/routes_v2/simcaqNumberOfEmployees.js | 129 +++++++++++++++ src/libs/routes_v2/simcaqWorkload.js | 151 ++++++++++++++++++ 3 files changed, 286 insertions(+) create mode 100644 src/libs/routes_v2/simcaqNumberOfEmployees.js create mode 100644 src/libs/routes_v2/simcaqWorkload.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 872274fe..fd345d05 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -144,6 +144,10 @@ const simcaqDivisionOfResponsibility = require(`${libs}/routes_v2/simcaqDivision const simcaqClassroomSize = require(`${libs}/routes_v2/simcaqClassroomSize`); +const simcaqWorkload = require(`${libs}/routes_v2/simcaqWorkload`); + +const simcaqNumberOfEmployees = require(`${libs}/routes_v2/simcaqNumberOfEmployees`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -207,5 +211,7 @@ api.use('/simcaq_enrollment_diagnosis', simcaqEnrollmentDiagnosis); api.use('/simcaq_second_report', simcaqSecondReport); api.use('/simcaq_division_of_responsibility', simcaqDivisionOfResponsibility); api.use('/simcaq_classroom_size', simcaqClassroomSize); +api.use('/simcaq_workload', simcaqWorkload); +api.use('/simcaq_number_of_employees', simcaqNumberOfEmployees); module.exports = api; diff --git a/src/libs/routes_v2/simcaqNumberOfEmployees.js b/src/libs/routes_v2/simcaqNumberOfEmployees.js new file mode 100644 index 00000000..58a28ffa --- /dev/null +++ b/src/libs/routes_v2/simcaqNumberOfEmployees.js @@ -0,0 +1,129 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqNumberOfEmployeesApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqNumberOfEmployeesApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_numero_de_funcionarios', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_numero_de_funcionarios' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_numero_de_funcionarios' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_numero_de_funcionarios' + } +}, 'dims').addValue({ + name: 'adm_dependency_public_id', + table: 'simcaq_numero_de_funcionarios', + tableField: 'rede', + where: { + relation: '=', + type: 'integer', + field: 'rede' + } +}); + +simcaqNumberOfEmployeesApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_numero_de_funcionarios') + .field('SUM(num_funcionarios)', 'average_number_of_employees') + .field('simcaq_numero_de_funcionarios.rede', 'adm_dependency_public_id') + .field('simcaq_numero_de_funcionarios.ano_censo', 'year') + .group('simcaq_numero_de_funcionarios.rede') + .group('simcaq_numero_de_funcionarios.ano_censo'); + next(); +}, query, id2str.transform(), response('simcaqNumberOfEmployees')); + +module.exports = simcaqNumberOfEmployeesApp; diff --git a/src/libs/routes_v2/simcaqWorkload.js b/src/libs/routes_v2/simcaqWorkload.js new file mode 100644 index 00000000..b4584224 --- /dev/null +++ b/src/libs/routes_v2/simcaqWorkload.js @@ -0,0 +1,151 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqWorkloadApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqWorkloadApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_carga_horaria_de_ensino', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_carga_horaria_de_ensino' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_carga_horaria_de_ensino' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_carga_horaria_de_ensino' + } +}, 'dims').addValue({ + name: 'adm_dependency_public_id', + table: 'simcaq_carga_horaria_de_ensino', + tableField: 'rede', + where: { + relation: '=', + type: 'integer', + field: 'rede' + } +}).addValue({ + name: 'education_level_short_id', + table: 'simcaq_carga_horaria_de_ensino', + tableField: 'etapa', + where: { + relation: '=', + type: 'integer', + field: 'etapa' + } +}).addValue({ + name: 'shift_id', + table: 'simcaq_carga_horaria_de_ensino', + tableField: 'turno', + where: { + relation: '=', + type: 'integer', + field: 'turno' + } +}); + +simcaqWorkloadApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_carga_horaria_de_ensino') + .field('AVG(duracao_turma_horas)', 'average_workload') + .field('simcaq_carga_horaria_de_ensino.etapa', 'education_level_short_id') + .field('simcaq_carga_horaria_de_ensino.turno', 'shift_id') + .field('simcaq_carga_horaria_de_ensino.rede', 'adm_dependency_public_id') + .field('simcaq_carga_horaria_de_ensino.ano_censo', 'year') + .group('simcaq_carga_horaria_de_ensino.etapa') + .group('simcaq_carga_horaria_de_ensino.turno') + .group('simcaq_carga_horaria_de_ensino.rede') + .group('simcaq_carga_horaria_de_ensino.ano_censo'); + next(); +}, query, id2str.transform(), response('simcaqWorkload')); + +module.exports = simcaqWorkloadApp; -- GitLab From fdaedcbecfbcdce89c9f237d5669908c287ab582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 6 Apr 2023 11:05:59 -0300 Subject: [PATCH 081/123] Add new classes route --- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/simcaqNewClasses.js | 131 ++++++++++++++++++ src/libs/routes_v2/simcaqNumberOfEmployees.js | 2 +- 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/libs/routes_v2/simcaqNewClasses.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index fd345d05..195a23e8 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -148,6 +148,8 @@ const simcaqWorkload = require(`${libs}/routes_v2/simcaqWorkload`); const simcaqNumberOfEmployees = require(`${libs}/routes_v2/simcaqNumberOfEmployees`); +const simcaqNewClasses = require(`${libs}/routes_v2/simcaqNewClasses`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -213,5 +215,6 @@ api.use('/simcaq_division_of_responsibility', simcaqDivisionOfResponsibility); api.use('/simcaq_classroom_size', simcaqClassroomSize); api.use('/simcaq_workload', simcaqWorkload); api.use('/simcaq_number_of_employees', simcaqNumberOfEmployees); +api.use('/simcaq_new_classes', simcaqNewClasses); module.exports = api; diff --git a/src/libs/routes_v2/simcaqNewClasses.js b/src/libs/routes_v2/simcaqNewClasses.js new file mode 100644 index 00000000..4922270e --- /dev/null +++ b/src/libs/routes_v2/simcaqNewClasses.js @@ -0,0 +1,131 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqNewClassesApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqNewClassesApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_novas_salas', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_novas_salas' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_novas_salas' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_novas_salas' + } +}, 'dims').addValue({ + name: 'adm_dependency_public_id', + table: 'simcaq_novas_salas', + tableField: 'rede', + where: { + relation: '=', + type: 'integer', + field: 'rede' + } +}); + +simcaqNewClassesApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_novas_salas') + .field('SUM(num_salas_urbana)', 'number_of_urban_classes') + .field('SUM(num_salas_rural)', 'number_of_rural_classes') + .field('SUM(num_salas_total)', 'total_number_of_classes') + .field('simcaq_novas_salas.rede', 'adm_dependency_public_id') + .field('simcaq_novas_salas.ano_censo', 'year') + .group('simcaq_novas_salas.rede') + .group('simcaq_novas_salas.ano_censo'); + next(); +}, query, id2str.transform(), response('simcaqNewClasses')); + +module.exports = simcaqNewClassesApp; diff --git a/src/libs/routes_v2/simcaqNumberOfEmployees.js b/src/libs/routes_v2/simcaqNumberOfEmployees.js index 58a28ffa..3496aa09 100644 --- a/src/libs/routes_v2/simcaqNumberOfEmployees.js +++ b/src/libs/routes_v2/simcaqNumberOfEmployees.js @@ -118,7 +118,7 @@ rqf.addField({ simcaqNumberOfEmployeesApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.sql.from('simcaq_numero_de_funcionarios') - .field('SUM(num_funcionarios)', 'average_number_of_employees') + .field('SUM(num_funcionarios)', 'number_of_employees') .field('simcaq_numero_de_funcionarios.rede', 'adm_dependency_public_id') .field('simcaq_numero_de_funcionarios.ano_censo', 'year') .group('simcaq_numero_de_funcionarios.rede') -- GitLab From 7ba4b926e690cec6ea590266c941da4197d1c5ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 10 Apr 2023 11:55:49 -0300 Subject: [PATCH 082/123] Add simcaq_result route, converter for supply_dimension --- src/libs/convert/supplyDimension.js | 36 ++++++ src/libs/middlewares/id2str.js | 4 +- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/simcaqClassroomSize.js | 2 +- src/libs/routes_v2/simcaqResult.js | 140 ++++++++++++++++++++++ 5 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 src/libs/convert/supplyDimension.js create mode 100644 src/libs/routes_v2/simcaqResult.js diff --git a/src/libs/convert/supplyDimension.js b/src/libs/convert/supplyDimension.js new file mode 100644 index 00000000..40f5ca9a --- /dev/null +++ b/src/libs/convert/supplyDimension.js @@ -0,0 +1,36 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +module.exports = function supplyDimension(id) { + switch(id) { + case 1: + return 'Número de matrÃculas'; + case 2: + return 'Número de turmas'; + case 3: + return 'Número de salas'; + case 4: + return 'Número de professores'; + case 5: + return 'Número de funcionários'; + default: + return 'Não especificado'; + } +} \ No newline at end of file diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js index 43cc1e0f..8c2b068d 100644 --- a/src/libs/middlewares/id2str.js +++ b/src/libs/middlewares/id2str.js @@ -97,6 +97,7 @@ const peePorCategoria = require(`${libs}/convert/peePorCategoria`); const pee = require(`${libs}/convert/booleanVariable`); const shift = require(`${libs}/convert/shift`); const admDependencyPub = require(`${libs}/convert/admDependencyPub`); +const supplyDimension = require(`${libs}/convert/supplyDimension`); const ids = { gender_id: gender, @@ -185,7 +186,8 @@ const ids = { diff_location_id: diffLocation, pee_por_categoria: peePorCategoria, pee_id: pee, - shift_id: shift + shift_id: shift, + supply_dimension_id: supplyDimension }; function transform(removeId=false) { diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 195a23e8..b675c882 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -150,6 +150,8 @@ const simcaqNumberOfEmployees = require(`${libs}/routes_v2/simcaqNumberOfEmploye const simcaqNewClasses = require(`${libs}/routes_v2/simcaqNewClasses`); +const simcaqResult = require(`${libs}/routes_v2/simcaqResult`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -216,5 +218,6 @@ api.use('/simcaq_classroom_size', simcaqClassroomSize); api.use('/simcaq_workload', simcaqWorkload); api.use('/simcaq_number_of_employees', simcaqNumberOfEmployees); api.use('/simcaq_new_classes', simcaqNewClasses); +api.use('/simcaq_result', simcaqResult); module.exports = api; diff --git a/src/libs/routes_v2/simcaqClassroomSize.js b/src/libs/routes_v2/simcaqClassroomSize.js index 9b48f3b3..d70d084e 100644 --- a/src/libs/routes_v2/simcaqClassroomSize.js +++ b/src/libs/routes_v2/simcaqClassroomSize.js @@ -142,6 +142,6 @@ simcaqClassroomSizeApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { .group('simcaq_tamanho_das_turmas.ano_censo') .group('simcaq_tamanho_das_turmas.etapa'); next(); -}, query, id2str.transform(), response('classroomSize')); +}, query, id2str.transform(), response('simcaqClassroomSize')); module.exports = simcaqClassroomSizeApp; diff --git a/src/libs/routes_v2/simcaqResult.js b/src/libs/routes_v2/simcaqResult.js new file mode 100644 index 00000000..3ba50ad0 --- /dev/null +++ b/src/libs/routes_v2/simcaqResult.js @@ -0,0 +1,140 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqResultApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqResultApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_resultado' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_resultado' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_resultado' + } +}, 'dims').addValue({ + name: 'adm_dependency_public_id', + table: 'simcaq_resultado', + tableField: 'rede', + where: { + relation: '=', + type: 'integer', + field: 'rede' + } +}).addValue({ + name: 'year', + table: 'simcaq_resultado', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'supply_dimension_id', + table: 'simcaq_resultado', + tableField: 'dimensao_oferta', + where: { + relation: '=', + type: 'integer', + field: 'dimensao_oferta' + } +}); + +simcaqResultApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_resultado') + .field('SUM(simcaq_resultado.atual)', 'current') + .field('simcaq_resultado.rede', 'adm_dependency_public_id') + .field('simcaq_resultado.ano_censo', 'year') + .field('simcaq_resultado.dimensao_oferta', 'supply_dimension_id') + .group('simcaq_resultado.ano_censo') + .group('simcaq_resultado.rede') + .group('simcaq_resultado.dimensao_oferta'); + next(); +}, query, id2str.transform(), response('simcaqResult')); + +module.exports = simcaqResultApp; -- GitLab From fc6b6bfb7946af09ac1501a0a2cf361ab2a205e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 11 Apr 2023 11:23:56 -0300 Subject: [PATCH 083/123] Add number of teachers route --- src/libs/convert/level.js | 32 ++++++ src/libs/convert/type.js | 30 ++++++ src/libs/middlewares/id2str.js | 6 +- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/simcaqNumberOfTeachers.js | 103 +++++++++++++++++++ 5 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 src/libs/convert/level.js create mode 100644 src/libs/convert/type.js create mode 100644 src/libs/routes_v2/simcaqNumberOfTeachers.js diff --git a/src/libs/convert/level.js b/src/libs/convert/level.js new file mode 100644 index 00000000..e52a331b --- /dev/null +++ b/src/libs/convert/level.js @@ -0,0 +1,32 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +module.exports = function level(id) { + switch(id) { + case 1: + return 'Brasil'; + case 2: + return 'Estadual'; + case 3: + return 'Municipal'; + default: + return 'Não especificado'; + } +} \ No newline at end of file diff --git a/src/libs/convert/type.js b/src/libs/convert/type.js new file mode 100644 index 00000000..6ffaf010 --- /dev/null +++ b/src/libs/convert/type.js @@ -0,0 +1,30 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +module.exports = function type(id) { + switch(id) { + case 1: + return 'Plano'; + case 2: + return 'Rede'; + default: + return 'Não especificado'; + } +} \ No newline at end of file diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js index 8c2b068d..39d819aa 100644 --- a/src/libs/middlewares/id2str.js +++ b/src/libs/middlewares/id2str.js @@ -98,6 +98,8 @@ const pee = require(`${libs}/convert/booleanVariable`); const shift = require(`${libs}/convert/shift`); const admDependencyPub = require(`${libs}/convert/admDependencyPub`); const supplyDimension = require(`${libs}/convert/supplyDimension`); +const type = require(`${libs}/convert/type`); +const level = require(`${libs}/convert/level`); const ids = { gender_id: gender, @@ -187,7 +189,9 @@ const ids = { pee_por_categoria: peePorCategoria, pee_id: pee, shift_id: shift, - supply_dimension_id: supplyDimension + supply_dimension_id: supplyDimension, + type_id: type, + level_id: level }; function transform(removeId=false) { diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index b675c882..f63dd586 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -152,6 +152,8 @@ const simcaqNewClasses = require(`${libs}/routes_v2/simcaqNewClasses`); const simcaqResult = require(`${libs}/routes_v2/simcaqResult`); +const simcaqNumberOfTeachers = require(`${libs}/routes_v2/simcaqNumberOfTeachers`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -219,5 +221,6 @@ api.use('/simcaq_workload', simcaqWorkload); api.use('/simcaq_number_of_employees', simcaqNumberOfEmployees); api.use('/simcaq_new_classes', simcaqNewClasses); api.use('/simcaq_result', simcaqResult); +api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); module.exports = api; diff --git a/src/libs/routes_v2/simcaqNumberOfTeachers.js b/src/libs/routes_v2/simcaqNumberOfTeachers.js new file mode 100644 index 00000000..00f6d942 --- /dev/null +++ b/src/libs/routes_v2/simcaqNumberOfTeachers.js @@ -0,0 +1,103 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqNumberOfTeachersApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqNumberOfTeachersApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_num_professores', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'local_id', + table: 'simcaq_num_professores', + tableField: 'local_id', + where: { + relation: '=', + type: 'integer', + field: 'local_id' + } +}).addValue({ + name: 'level_id', + table: 'simcaq_num_professores', + tableField: 'nivel', + where: { + relation: '=', + type: 'integer', + field: 'nivel' + } +}).addValue({ + name: 'type_id', + table: 'simcaq_num_professores', + tableField: 'tipo', + where: { + relation: '=', + type: 'integer', + field: 'tipo' + } +}); + +simcaqNumberOfTeachersApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_num_professores') + .field('total', 'number_of_teachers') + .field('simcaq_num_professores.ano_censo', 'year') + .field('simcaq_num_professores.nivel', 'level_id') + .field('simcaq_num_professores.tipo', 'type_id') + .field('simcaq_num_professores.local_id', 'local_id'); + next(); +}, query, id2str.transform(), response('simcaqNumberOfTeachers')); + +module.exports = simcaqNumberOfTeachersApp; -- GitLab From 5d14877ab75a025f2b334cdf85923b44cc41f116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Wed, 12 Apr 2023 11:17:32 -0300 Subject: [PATCH 084/123] fix issue with the simcaq_second_report_route where the adm_dependency_detailed_id filter wasn't correctly set up --- src/libs/routes_v2/simcaqSecondReport.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/routes_v2/simcaqSecondReport.js b/src/libs/routes_v2/simcaqSecondReport.js index 4c30f8d1..421bd6f2 100644 --- a/src/libs/routes_v2/simcaqSecondReport.js +++ b/src/libs/routes_v2/simcaqSecondReport.js @@ -106,13 +106,13 @@ rqf.addField({ foreignTable: 'simcaq_relatorio_2' } }, 'dims').addValue({ - name: 'adm_dependency', + name: 'adm_dependency_detailed_id', table: 'simcaq_relatorio_2', - tableField: 'dependencia_adm_id', + tableField: 'dependencia_adm_priv', where: { relation: '=', type: 'integer', - field: 'dependencia_adm_id' + field: 'dependencia_adm_priv' } }); -- GitLab From fb2573bc2a4611876f515070ed5c1dde56987259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 18 Apr 2023 10:04:09 -0300 Subject: [PATCH 085/123] Add enrollment projection route --- src/libs/routes_v2/api.js | 3 + .../routes_v2/simcaqEnrollmentProjection.js | 143 ++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 src/libs/routes_v2/simcaqEnrollmentProjection.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index f63dd586..25c829f9 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -154,6 +154,8 @@ const simcaqResult = require(`${libs}/routes_v2/simcaqResult`); const simcaqNumberOfTeachers = require(`${libs}/routes_v2/simcaqNumberOfTeachers`); +const simcaqEnrollmentProjection = require(`${libs}/routes_v2/simcaqEnrollmentProjection`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -222,5 +224,6 @@ api.use('/simcaq_number_of_employees', simcaqNumberOfEmployees); api.use('/simcaq_new_classes', simcaqNewClasses); api.use('/simcaq_result', simcaqResult); api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); +api.use('/simcaq_enrollment_projection', simcaqEnrollmentProjection); module.exports = api; diff --git a/src/libs/routes_v2/simcaqEnrollmentProjection.js b/src/libs/routes_v2/simcaqEnrollmentProjection.js new file mode 100644 index 00000000..cb472b4e --- /dev/null +++ b/src/libs/routes_v2/simcaqEnrollmentProjection.js @@ -0,0 +1,143 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqEnrollmentProjectionApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqEnrollmentProjectionApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_projecao_de_matricula', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_projecao_de_matricula' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_projecao_de_matricula' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_projecao_de_matricula' + } +}, 'dims').addValue({ + name: 'education_level_short_id', + table: 'simcaq_projecao_de_matricula', + tableField: 'etapa', + where: { + relation: '=', + type: 'integer', + field: 'etapa' + } +}).addValue({ + name: 'adm_dependency_public_id', + table: 'simcaq_projecao_de_matricula', + tableField: 'rede', + where: { + relation: '=', + type: 'integer', + field: 'rede' + } +}); + +simcaqEnrollmentProjectionApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_projecao_de_matricula') + .field('simcaq_projecao_de_matricula.ano_censo', 'year') + .field('simcaq_projecao_de_matricula.etapa', 'education_level_short_id') + .field('simcaq_projecao_de_matricula.rede', 'adm_dependency_public_id') + .field('SUM(simcaq_projecao_de_matricula.total_matriculas)', 'total_enrollments') + .field('SUM(simcaq_projecao_de_matricula.matriculas_diurno)', 'daytime_enrollments') + .field('SUM(simcaq_projecao_de_matricula.matriculas_noturno)', 'nighttime_enrollments') + .field('SUM(simcaq_projecao_de_matricula.total_tempo_integral)', 'fulltime_enrollments') + .group('simcaq_projecao_de_matricula.ano_censo') + .group('simcaq_projecao_de_matricula.etapa') + .group('simcaq_projecao_de_matricula.rede'); + next(); +}, query, id2str.transform(), response('enrollmentProjection')); + +module.exports = simcaqEnrollmentProjectionApp; -- GitLab From 2f3281ac1047aef6339d91089e50dac84e095eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 24 Apr 2023 10:02:33 -0300 Subject: [PATCH 086/123] update v2 classroom route to use new aggregated table --- src/libs/routes_v2/classroom.js | 54 ++++++++++++++++----------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/libs/routes_v2/classroom.js b/src/libs/routes_v2/classroom.js index 8e2b6a7e..a3d6ec7f 100644 --- a/src/libs/routes_v2/classroom.js +++ b/src/libs/routes_v2/classroom.js @@ -50,22 +50,22 @@ let rqfCount = new ReqQueryFields(); // Complete range of the enrollments dataset. // Returns a tuple of start and ending years of the complete enrollments dataset. classroomApp.get('/year_range', (req, res, next) => { - req.sql.from('escola') - .field('MIN(escola.ano_censo)', 'start_year') - .field('MAX(escola.ano_censo)', 'end_year'); + req.sql.from('escola_agregada') + .field('MIN(escola_agregada.ano_censo)', 'start_year') + .field('MAX(escola_agregada.ano_censo)', 'end_year'); next(); }, query, response('range')); classroomApp.get('/years', (req, res, next) => { - req.sql.from('escola') - .field('DISTINCT escola.ano_censo', 'year'); + req.sql.from('escola_agregada') + .field('DISTINCT escola_agregada.ano_censo', 'year'); next(); }, query, response('years')); classroomApp.get('/source', (req, res, next) => { req.sql.from('fonte') .field('fonte', 'source') - .where('tabela = \'escola\''); + .where('tabela = \'escola_agregada\''); next(); }, query, response('source')); @@ -109,7 +109,7 @@ rqf.addField({ where: false }).addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: ['nome_escola', 'id'], resultField: ['school_name', 'school_id'], where: { @@ -119,7 +119,7 @@ rqf.addField({ } }, 'dims').addValueToField({ name: 'school', - table: 'escola', + table: 'escola_agregada', tableField: 'nome_escola', resultField: 'school_name', where: { @@ -136,12 +136,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'dims').addValueToField({ name: 'city', @@ -152,12 +152,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'municipio_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'municipio_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }, 'filter').addValue({ name: 'state', @@ -168,12 +168,12 @@ rqf.addField({ relation: '=', type: 'integer', field: 'estado_id', - table: 'escola' + table: 'escola_agregada' }, join: { primary: 'id', foreign: 'estado_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'region', @@ -188,11 +188,11 @@ rqf.addField({ join: { primary: 'id', foreign: 'regiao_id', - foreignTable: 'escola' + foreignTable: 'escola_agregada' } }).addValue({ name: 'min_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -202,7 +202,7 @@ rqf.addField({ } }).addValue({ name: 'max_year', - table: 'escola', + table: 'escola_agregada', tableField: 'ano_censo', resultField: 'year', where: { @@ -212,7 +212,7 @@ rqf.addField({ } }).addValue({ name: 'adm_dependency', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_id', resultField: 'adm_dependency_id', where: { @@ -222,7 +222,7 @@ rqf.addField({ } }).addValue({ name: 'adm_dependency_detailed', - table: 'escola', + table: 'escola_agregada', tableField: 'dependencia_adm_priv', resultField: 'adm_dependency_detailed_id', where: { @@ -232,7 +232,7 @@ rqf.addField({ } }).addValue({ name: 'location', - table: 'escola', + table: 'escola_agregada', tableField: 'localizacao_id', resultField: 'location_id', where: { @@ -243,14 +243,14 @@ rqf.addField({ }); classroomApp.get('/', cache('15 day'), rqf.parse(), rqf.build(), (req, res, next) => { - req.sql.from('escola') - .field('SUM(escola.qtde_salas_utilizadas_dentro)', 'total') + req.sql.from('escola_agregada') + .field('SUM(escola_agregada.qtde_salas_utilizadas_dentro)', 'total') .field("'Brasil'", 'name') - .field('escola.ano_censo', 'year') - .group('escola.ano_censo') - .order('escola.ano_censo') - .where('escola.situacao_de_funcionamento = 1 AND escola.local_func_predio_escolar = 1') - .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1'); + .field('escola_agregada.ano_censo', 'year') + .group('escola_agregada.ano_censo') + .order('escola_agregada.ano_censo') + .where('escola_agregada.situacao_funcionamento_pareada = 1 AND escola_agregada.local_func_predio_escolar = 1') + .where('escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1'); next(); }, query, addMissing(rqf), id2str.transform(), (req, res, next) => { if (req.dims.location && req.result.length < 2) { // Garantimos que conterá as duas localizações no resultado para o simCAQ -- GitLab From d00a8d95f454b1b56477b6c79ea632f786a75c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 27 Apr 2023 11:02:11 -0300 Subject: [PATCH 087/123] Add simcaq aggregated enrollment --- src/libs/routes_v2/api.js | 3 + .../routes_v2/simcaqAggregatedEnrollment.js | 211 ++++++++++++++++++ 2 files changed, 214 insertions(+) create mode 100644 src/libs/routes_v2/simcaqAggregatedEnrollment.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 25c829f9..2072e864 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -156,6 +156,8 @@ const simcaqNumberOfTeachers = require(`${libs}/routes_v2/simcaqNumberOfTeachers const simcaqEnrollmentProjection = require(`${libs}/routes_v2/simcaqEnrollmentProjection`); +const simcaqAggregatedEnrollment = require(`${libs}/routes_v2/simcaqAggregatedEnrollment`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -225,5 +227,6 @@ api.use('/simcaq_new_classes', simcaqNewClasses); api.use('/simcaq_result', simcaqResult); api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); api.use('/simcaq_enrollment_projection', simcaqEnrollmentProjection); +api.use('/simcaq_aggregated_enrollment', simcaqAggregatedEnrollment); module.exports = api; diff --git a/src/libs/routes_v2/simcaqAggregatedEnrollment.js b/src/libs/routes_v2/simcaqAggregatedEnrollment.js new file mode 100644 index 00000000..7562acfa --- /dev/null +++ b/src/libs/routes_v2/simcaqAggregatedEnrollment.js @@ -0,0 +1,211 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqAggregatedEnrollmentApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqAggregatedEnrollmentApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_matricula_agregada', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'municipio_id', + foreignTable: 'simcaq_matricula_agregada' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'estado_id', + foreignTable: 'simcaq_matricula_agregada' + } +}, 'dims').addValue({ + name: 'region', + table: 'regiao', + tableField: ['nome', 'id'], + resultField: ['region_name', 'region_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'regiao_id', + foreignTable: 'simcaq_matricula_agregada' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: 'id', + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_matricula_agregada' + } +}, 'dims').addValue({ + name: 'locale', + table: 'simcaq_matricula_agregada', + tableField: 'localizacao_id', + resultField: 'locale_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'adm_dependency_id', + table: 'simcaq_matricula_agregada', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}).addValue({ + name: 'adm_dependency_detailed_id', + table: 'simcaq_matricula_agregada', + tableField: 'dependencia_adm_priv', + resultField: 'adm_dependency_detailed_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_priv' + } +}).addValue({ + name: 'diff_location_id', + table: 'simcaq_matricula_agregada', + tableField: 'localizacao_diferenciada_par', + resultField: 'diff_location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_diferenciada_par' + } +}).addValue({ + name: 'school_building', + table: 'simcaq_matricula_agregada', + tableField: 'local_func_predio_escolar', + where: { + relation: '=', + type: 'boolean', + field: 'local_func_predio_escolar' + } +}).addValue({ + name: 'rural_location_id', + table: 'simcaq_matricula_agregada', + tableField: 'localidade_area_rural', + where: { + relation: '=', + type: 'integer', + field: 'localidade_area_rural' + } +}).addValue({ + name: 'school_year_id', + table: 'simcaq_matricula_agregada', + tableField: 'serie_ano_id', + resultField: 'school_year_id', + where: { + relation: '=', + type: 'integer', + field: 'serie_ano_id' + } +}).addValue({ + name: 'education_level_short_id', + table: 'simcaq_matricula_agregada', + tableField: 'etapa_resumida', + resultField: 'education_level_short_id', + where: { + relation: '=', + type: 'integer', + field: 'etapa_resumida' + } +}); + +simcaqAggregatedEnrollmentApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_matricula_agregada') + .field('SUM(simcaq_matricula_agregada.num_matriculas)', 'num_enrollments') + .field('simcaq_matricula_agregada.ano_censo', 'year') + .group('simcaq_matricula_agregada.ano_censo'); + next(); +}, query, id2str.transform(), response('aggregatedEnrollment')); + +module.exports = simcaqAggregatedEnrollmentApp; -- GitLab From 18acaae498d13f19ed36ba4c0c18020c90ca024d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 28 Apr 2023 09:55:08 -0300 Subject: [PATCH 088/123] Add teacher city plan route --- src/libs/routes_v2/api.js | 3 + src/libs/routes_v2/simcaqTeacherCityPlan.js | 139 ++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/libs/routes_v2/simcaqTeacherCityPlan.js diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 2072e864..5c00d3fe 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -158,6 +158,8 @@ const simcaqEnrollmentProjection = require(`${libs}/routes_v2/simcaqEnrollmentPr const simcaqAggregatedEnrollment = require(`${libs}/routes_v2/simcaqAggregatedEnrollment`); +const simcaqTeacherCityPlan = require(`${libs}/routes_v2/simcaqTeacherCityPlan`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -228,5 +230,6 @@ api.use('/simcaq_result', simcaqResult); api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); api.use('/simcaq_enrollment_projection', simcaqEnrollmentProjection); api.use('/simcaq_aggregated_enrollment', simcaqAggregatedEnrollment); +api.use('/simcaq_teacher_city_plan', simcaqTeacherCityPlan); module.exports = api; diff --git a/src/libs/routes_v2/simcaqTeacherCityPlan.js b/src/libs/routes_v2/simcaqTeacherCityPlan.js new file mode 100644 index 00000000..72c19913 --- /dev/null +++ b/src/libs/routes_v2/simcaqTeacherCityPlan.js @@ -0,0 +1,139 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqTeacherCityPlanApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqTeacherCityPlanApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_docente_municipio_plano', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'city', + table: 'municipio', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_municipio_id', + foreignTable: 'simcaq_docente_municipio_plano' + } +}, 'dims').addValue({ + name: 'state', + table: 'estado', + tableField: ['nome', 'id'], + resultField: ['state_name', 'state_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_estado_id', + foreignTable: 'simcaq_docente_municipio_plano' + } +}, 'dims').addValue({ + name: 'school', + table: 'escola_agregada', + tableField: ['nome', 'id'], + resultField: ['school_name', 'school_id'], + where: { + relation: '=', + type: 'integer', + field: 'id' + }, + join: { + primary: 'id', + foreign: 'escola_id', + foreignTable: 'simcaq_docente_municipio_plano' + } +}, 'dims').addValue({ + name: 'country', + table: 'simcaq_docente_municipio_plano', + tableField: ['escola_pais_nome', 'escola_pais_id'], + resultField: ['country_name', 'country_id'], + where: { + relation: '=', + type: 'integer', + field: 'escola_pais_id' + } +}).addValue({ + name: 'adm_dependency_id', + table: 'simcaq_docente_municipio_plano', + tableField: 'dependencia_adm_id', + resultField: 'adm_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'dependencia_adm_id' + } +}); + +simcaqTeacherCityPlanApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_docente_municipio_plano') + .field('simcaq_docente_municipio_plano.num_docentes', 'num_teachers') + .field('simcaq_docente_municipio_plano.dependencia_adm_id', 'adm_dependency_id') + .field('simcaq_docente_municipio_plano.ano_censo', 'year'); + next(); +}, query, id2str.transform(), response('simcaqTeacherCityPlan')); + +module.exports = simcaqTeacherCityPlanApp; -- GitLab From 5b43bf569e5bcc47a01c2319e4a93dbf9a14a90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Wed, 24 May 2023 11:08:00 -0300 Subject: [PATCH 089/123] Initiate changes to aggregated classroom_count, not ready yet --- src/libs/middlewares/query.js | 2 + src/libs/routes_v2/aux | 1 + src/libs/routes_v2/classroomCount.js | 149 +++++++++++---------------- 3 files changed, 63 insertions(+), 89 deletions(-) create mode 100644 src/libs/routes_v2/aux diff --git a/src/libs/middlewares/query.js b/src/libs/middlewares/query.js index b724d93d..3b734957 100644 --- a/src/libs/middlewares/query.js +++ b/src/libs/middlewares/query.js @@ -10,6 +10,8 @@ function query(req, res, next) { execute(sql.text, sql.values, (err, result) => { if(err) { log.error(err.stack); + console.log(sql.text); + console.log(sql.values); next(new Error('Request could not be satisfied due to a database error.')); } else { req.result = result; diff --git a/src/libs/routes_v2/aux b/src/libs/routes_v2/aux new file mode 100644 index 00000000..c0b4cc5f --- /dev/null +++ b/src/libs/routes_v2/aux @@ -0,0 +1 @@ +SELECT COUNT(*) AS "total", simcaq_matricula_agregada.ano_censo AS "year", estado.nome AS "state_name", estado.id AS "state_id", municipio.nome AS "city_name", municipio.id AS "city_id", simcaq_matricula_agregada.etapa_resumida AS "education_level_short_id", simcaq_matricula_agregada.tempo_integral AS "integral_time_id" FROM simcaq_matricula_agregada INNER JOIN estado ON (simcaq_matricula_agregada.estado_id=estado.id) INNER JOIN municipio ON (simcaq_matricula_agregada.municipio_id=municipio.id) WHERE (simcaq_matricula_agregada.ano_censo >= 2021 ) AND (simcaq_matricula_agregada.ano_censo <= 2021 ) GROUP BY simcaq_matricula_agregada.ano_censo, estado.nome, estado.id, municipio.nome, municipio.id, simcaq_matricula_agregada.etapa_resumida, simcaq_matricula_agregada.tempo_integral ORDER BY simcaq_matricula_agregada.ano_censo ASC, estado.nome ASC, estado.id ASC, municipio.nome ASC, municipio.id ASC, simcaq_matricula_agregada.etapa_resumida ASC, simcaq_matricula_agregada.tempo_integral ASC diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 0af32828..b4ba338a 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -54,21 +54,20 @@ rqf.addField({ }).addValueToField({ name: 'city', table: 'municipio', - tableField: 'nome', - resultField: 'city_name', + tableField: ['nome', 'id'], + resultField: ['city_name', 'city_id'], where: { relation: '=', type: 'integer', - field: 'municipio_id', - table: '@' + field: 'id' }, join: { primary: 'id', foreign: 'municipio_id', foreignTable: '@' } -}, 'filter').addValueToField({ - name: 'city', +}, 'dims').addValueToField({ + name: 'cityTeacher', table: 'municipio', tableField: ['nome', 'id'], resultField: ['city_name', 'city_id'], @@ -79,26 +78,10 @@ rqf.addField({ }, join: { primary: 'id', - foreign: 'municipio_id', + foreign: 'escola_cidade_id', foreignTable: '@' } }, 'dims').addValueToField({ - name: 'state', - table: 'estado', - tableField: 'nome', - resultField: 'state_name', - where: { - relation: '=', - type: 'integer', - field: 'estado_id', - table: '@' - }, - join: { - primary: 'id', - foreign: 'estado_id', - foreignTable: '@' - } -}, 'filter').addValueToField({ name: 'state', table: 'estado', tableField: ['nome', 'id'], @@ -115,9 +98,9 @@ rqf.addField({ } }, 'dims').addValueToField({ name: 'school', - table: 'escola', - tableField: ['nome_escola', 'id', 'dependencia_adm_id'], // Dado de dependencia administrativa sempre deve ser retornado com escola - resultField: ['school_name', 'school_id', 'adm_dependency_id'], + table: 'escola_agregada', + tableField: ['nome_escola', 'id'], + resultField: ['school_name', 'school_id'], where: { relation: '=', type: 'integer', @@ -163,39 +146,9 @@ rqf.addField({ type: 'integer', field: 'ano_censo' } -}).addValue({ - name: 'school_year', - table: '@', - tableField: 'serie_ano_id', - resultField: 'school_year_id', - where: { - relation: '=', - type: 'integer', - field: 'serie_ano_id' - } -}).addValue({ - name: 'location', - table: '@', - tableField: 'localizacao_id', - resultField: 'location_id', - where: { - relation: '=', - type: 'integer', - field: 'localizacao_id' - } -}).addValue({ - name: 'period', - table: '@', - tableField: 'turma_turno_id', - resultField: 'period_id', - where: { - relation: '=', - type: 'integer', - field: 'turma_turno_id' - } }).addValue({ name: 'school_building', - table: 'escola', + table: '@', tableField: 'local_func_predio_escolar', resultField: 'school_building', where: { @@ -205,7 +158,7 @@ rqf.addField({ } }).addValue({ name: 'night_time', - table: 'matricula', + table: '@', tableField: 'periodo_noturno', resultField: 'night_time', where: { @@ -215,7 +168,7 @@ rqf.addField({ } }).addValue({ name: 'formation_level', - table: 'docente_por_formacao', + table: '@', tableField: 'tipo_formacao', resultField: 'formation_level', where: { @@ -235,7 +188,7 @@ rqf.addField({ } }, 'filter') .addValue({ name: 'integral_time', - table: 'matricula', + table: '@', tableField: 'tempo_integral', resultField: 'integral_time_id', where: { @@ -245,7 +198,7 @@ rqf.addField({ } }).addValue({ name: 'education_level_short', - table: 'matricula', + table: '@', tableField: 'etapa_resumida', resultField: 'education_level_short_id', where: { @@ -253,6 +206,26 @@ rqf.addField({ type: 'integer', field: 'etapa_resumida' } +}).addValue({ + name: 'location', + table: '@', + tableField: 'localizacao_id', + resultField: 'location_id', + where: { + relation: '=', + type: 'integer', + field: 'localizacao_id' + } +}).addValue({ + name: 'school_year', + table: '@', + tableField: 'ano_censo', + resultField: 'school_year', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } }); classroomCountApp.post('/', rqf.parse(), (req, res, next) => { @@ -276,11 +249,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.sql.field('sum(dia_total)', 'total_day') .field('sum(noite_total)', 'total_night') .field("'Brasil'", 'name') - .field('matricula_por_localizacao.ano_censo', 'year') - .from('matricula_por_localizacao') - .where('matricula_por_localizacao.serie_ano_id < 15') - .group('matricula_por_localizacao.ano_censo') - .order('matricula_por_localizacao.ano_censo') + .field('simcaq_matricula_por_localizacao.ano_censo', 'year') + .from('simcaq_matricula_por_localizacao') + .where('simcaq_matricula_por_localizacao.serie_ano_id < 15') + .group('simcaq_matricula_por_localizacao.ano_censo') + .order('simcaq_matricula_por_localizacao.ano_censo') next(); }, rqf.build(), query, id2str.transform(), (req, res, next) => { @@ -310,7 +283,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }; } } - + delete req.dims; delete req.filter; req.resetSql(); @@ -322,15 +295,15 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.location = true; req.dims.school_building = true; - req.sql.field('SUM(escola.qtde_salas_utilizadas_dentro)', 'total') + req.sql.field('SUM(escola_agregada.qtde_salas_utilizadas_dentro)', 'total') .field("'Brasil'", 'name') - .field('escola.ano_censo', 'year') - .from('escola') - .group('escola.ano_censo') - .order('escola.ano_censo') - .where('escola.situacao_de_funcionamento = 1') - .where('escola.dependencia_adm_id < 4') - .where('escola.ensino_regular = 1 OR escola.ensino_eja = 1 OR escola.educacao_profissional = 1'); + .field('escola_agregada.ano_censo', 'year') + .from('escola_agregada') + .group('escola_agregada.ano_censo') + .order('escola_agregada.ano_censo') + .where('escola_agregada.situacao_funcionamento_pareada = 1') + .where('escola_agregada.dependencia_adm_id < 4') + .where('escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1'); next(); }, rqf.build(), query, id2str.transform(), (req, res, next) => { @@ -379,15 +352,14 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.teacherCalc = true; } - req.dims.state = true; - req.dims.city = true; + req.dims.cityTeacher = true; req.dims.formation_level = true; - req.sql.field('count(distinct docente_por_formacao.id_docente)', 'total') + req.sql.field('SUM(simcaq_docente_agregada.num_docentes)', 'total') .field("'Brasil'", 'name') - .field('docente_por_formacao.ano_censo', 'year') - .from('docente_por_formacao') - .group('docente_por_formacao.ano_censo') - .order('docente_por_formacao.ano_censo'); + .field('simcaq_docente_agregada.ano_censo', 'year') + .from('simcaq_docente_agregada') + .group('simcaq_docente_agregada.ano_censo') + .order('simcaq_docente_agregada.ano_censo'); next(); }, rqf.build(), query, id2str.transform(), (req, res, next) => { @@ -401,13 +373,13 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.state = true; req.dims.city = true; req.dims.education_level_short = true; - req.dims.integral_time = true; + //req.dims.integral_time = true; req.sql.field('COUNT(*)', 'total') - .field('matricula.ano_censo', 'year') - .from('matricula') - .group('matricula.ano_censo') - .order('matricula.ano_censo') - .where('((matricula.tipo<=3 OR matricula.tipo IS NULL) AND (matricula.tipo_atendimento_turma IS NULL OR matricula.tipo_atendimento_turma <= 2) AND matricula.turma_turno_id <> 99)'); + .field('simcaq_matricula_agregada.ano_censo', 'year') + .from('simcaq_matricula_agregada') + .group('simcaq_matricula_agregada.ano_censo') + .order('simcaq_matricula_agregada.ano_censo'); + //.where('((simcaq_matricula_agregada.tipo<=3 OR simcaq_matricula_agregada.tipo IS NULL) AND (simcaq_matricula_agregada.tipo_atendimento_turma IS NULL OR simcaq_matricula_agregada.tipo_atendimento_turma <= 2) AND simcaq_matricula_agregada.turma_turno_id <> 99)'); next(); }, rqf.build() ,query, id2str.transform(), (req, res, next) => { // constrói objeto de tempo integral e calcula diagnósticos @@ -566,7 +538,6 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { ti++; if (ti === req.teacher.length) { - console.log(classroom[id_attribute], "not found") while (classroom[id_attribute] === enrollments[j][id_attribute]) enrollments.splice(j, 1) ti = old_ti; -- GitLab From 331ec294df84190b6d4e6b2517094820bf9205c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Wed, 31 May 2023 09:43:09 -0300 Subject: [PATCH 090/123] Add changes to classroom count v2 --- src/libs/routes_v2/aux | 1 - src/libs/routes_v2/classroomCount.js | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) delete mode 100644 src/libs/routes_v2/aux diff --git a/src/libs/routes_v2/aux b/src/libs/routes_v2/aux deleted file mode 100644 index c0b4cc5f..00000000 --- a/src/libs/routes_v2/aux +++ /dev/null @@ -1 +0,0 @@ -SELECT COUNT(*) AS "total", simcaq_matricula_agregada.ano_censo AS "year", estado.nome AS "state_name", estado.id AS "state_id", municipio.nome AS "city_name", municipio.id AS "city_id", simcaq_matricula_agregada.etapa_resumida AS "education_level_short_id", simcaq_matricula_agregada.tempo_integral AS "integral_time_id" FROM simcaq_matricula_agregada INNER JOIN estado ON (simcaq_matricula_agregada.estado_id=estado.id) INNER JOIN municipio ON (simcaq_matricula_agregada.municipio_id=municipio.id) WHERE (simcaq_matricula_agregada.ano_censo >= 2021 ) AND (simcaq_matricula_agregada.ano_censo <= 2021 ) GROUP BY simcaq_matricula_agregada.ano_censo, estado.nome, estado.id, municipio.nome, municipio.id, simcaq_matricula_agregada.etapa_resumida, simcaq_matricula_agregada.tempo_integral ORDER BY simcaq_matricula_agregada.ano_censo ASC, estado.nome ASC, estado.id ASC, municipio.nome ASC, municipio.id ASC, simcaq_matricula_agregada.etapa_resumida ASC, simcaq_matricula_agregada.tempo_integral ASC diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index b4ba338a..1c3bb6b3 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -250,9 +250,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { .field('sum(noite_total)', 'total_night') .field("'Brasil'", 'name') .field('simcaq_matricula_por_localizacao.ano_censo', 'year') + .field('simcaq_matricula_por_localizacao.serie_ano_id', 'school_year_id') .from('simcaq_matricula_por_localizacao') .where('simcaq_matricula_por_localizacao.serie_ano_id < 15') .group('simcaq_matricula_por_localizacao.ano_censo') + .group('simcaq_matricula_por_localizacao.serie_ano_id') .order('simcaq_matricula_por_localizacao.ano_censo') next(); @@ -387,7 +389,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.integral_time = {} for (let i = 0; i < integral_time_result.length; ++i){ // Se cidade não foi criada, cria - let integral_time = integral_time_result[i]; + let integral_time = integral_time_result[i] let code = '' + integral_time.year + integral_time.city_id if (req.dims.school) code = code + integral_time.school_id @@ -591,13 +593,12 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let enrollmentEducationLevel = req.educationSchoolYear[enrollment.school_year_id]; // Se não há um número de alunos por turna para a etapa de ensino, ignoramos a entrada - if(enrollmentEducationLevel.numberStudentClass == null) continue; + if(typeof enrollmentEducationLevel.numberStudentClass == 'undefined' || enrollmentEducationLevel.numberStudentClass == null) continue; // Adiciona nÃvel de educação para municÃpio/escola let educationLevel = null; if(!educationLevelSet.has(enrollmentEducationLevel.id)) { // cria e insere ordenadamente novo education level educationLevelSet.add(enrollmentEducationLevel.id); - let itHash = '' + enrollment.year + enrollment.city_id if (req.dims.school) itHash += enrollment.school_id @@ -664,7 +665,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let currentSchoolYear = null; if(enrollmentEducationLevel.id == 1){ let schoolYearHash = '' + enrollment.year + enrollment.city_id + enrollment.location_id + enrollment.school_year_id; - if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.shcool_id + if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.school_id if(schoolYearSet.has(schoolYearHash)) { // Busca a série escolar let k = 0; -- GitLab From 73ce2f5f6220c7b2a50ee5ffd26ad41abada6a55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Wed, 31 May 2023 11:36:17 -0300 Subject: [PATCH 091/123] update classroomcount v2 --- src/libs/routes_v2/classroomCount.js | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 1c3bb6b3..1058aa41 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -66,21 +66,6 @@ rqf.addField({ foreign: 'municipio_id', foreignTable: '@' } -}, 'dims').addValueToField({ - name: 'cityTeacher', - table: 'municipio', - tableField: ['nome', 'id'], - resultField: ['city_name', 'city_id'], - where: { - relation: '=', - type: 'integer', - field: 'id' - }, - join: { - primary: 'id', - foreign: 'escola_cidade_id', - foreignTable: '@' - } }, 'dims').addValueToField({ name: 'state', table: 'estado', @@ -354,7 +339,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.teacherCalc = true; } - req.dims.cityTeacher = true; + req.dims.city = true; req.dims.formation_level = true; req.sql.field('SUM(simcaq_docente_agregada.num_docentes)', 'total') .field("'Brasil'", 'name') @@ -534,11 +519,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { currentClassroomObj = obj; var id_attribute = req.dims.school ? "school_id" : "city_id" - var old_ti = ti; - while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) // match da tabela de professores. + while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) { // match da tabela de professores. ti++; - + } + if (ti === req.teacher.length) { while (classroom[id_attribute] === enrollments[j][id_attribute]) enrollments.splice(j, 1) @@ -1141,6 +1126,8 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }) } + console.log('fim') + next(); }, response('classroom_count')); -- GitLab From 1e4ed735f7d8b8755f82f9e4d94dc2ae2d168210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 2 Jun 2023 11:02:59 -0300 Subject: [PATCH 092/123] rewrite queries for classroom_count --- src/libs/routes_v2/classroomCount.js | 94 +++++++++++++++++++++++++--- src/libs/routes_v2/infrastructure.js | 29 +++++---- 2 files changed, 102 insertions(+), 21 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 1058aa41..112d70db 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -228,9 +228,32 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.state = true; req.dims.city = true; - req.dims.school_year = true; + //req.dims.school_year = true; req.dims.location = true; + /* + select + sum(dia_total), + sum(noite_total), + 'Brasil' as name, + ano_censo, + serie_ano_id, + estado_id, + municipio_id, + localizacao_id + from + simcaq_matricula_por_localizacao + where + serie_ano_id < 15 + group by + name, + ano_censo, + serie_ano_id, + estado_id, + municipio_id, + localizacao_id + */ + req.sql.field('sum(dia_total)', 'total_day') .field('sum(noite_total)', 'total_night') .field("'Brasil'", 'name') @@ -277,19 +300,42 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { next(); }, rqf.parse(), (req, res, next) => { + /* + select + sum(escola_agregada.num_salas_utilizadas) as soma, + 'Brasil' as name, + ano_censo, + estado_id, + municipio_id, + localizacao_id, + local_func_predio_escolar + from escola_agregada + where + situacao_de_funcionamento = 1 and + dependencia_adm_id IN (2, 3) and + escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1 + group by + name, + ano_censo, + estado_id, + municipio_id, + localizacao_id, + local_func_predio_escolar + */ + req.dims.state = true; req.dims.city = true; req.dims.location = true; req.dims.school_building = true; - - req.sql.field('SUM(escola_agregada.qtde_salas_utilizadas_dentro)', 'total') + + req.sql.field('SUM(escola_agregada.num_salas_utilizadas)', 'total') .field("'Brasil'", 'name') .field('escola_agregada.ano_censo', 'year') .from('escola_agregada') .group('escola_agregada.ano_censo') .order('escola_agregada.ano_censo') - .where('escola_agregada.situacao_funcionamento_pareada = 1') - .where('escola_agregada.dependencia_adm_id < 4') + .where('escola_agregada.situacao_de_funcionamento = 1') + .where('escola_agregada.dependencia_adm_id IN (2,3)') .where('escola_agregada.ensino_regular = 1 OR escola_agregada.ensino_eja = 1 OR escola_agregada.educacao_profissional = 1'); next(); @@ -339,11 +385,22 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.teacherCalc = true; } - req.dims.city = true; - req.dims.formation_level = true; - req.sql.field('SUM(simcaq_docente_agregada.num_docentes)', 'total') + /* + select num_docentes, + 'Brasil' as name, + ano_censo, + escola_estado_id, + municipio_id + from simcaq_docente_agregada + */ + + //req.dims.city = true; + //req.dims.state = true; + req.sql.field('simcaq_docente_agregada.num_docentes', 'total') .field("'Brasil'", 'name') .field('simcaq_docente_agregada.ano_censo', 'year') + .field('escola_estado_id', 'state_id') + .field('municipio_id', 'city_id') .from('simcaq_docente_agregada') .group('simcaq_docente_agregada.ano_censo') .order('simcaq_docente_agregada.ano_censo'); @@ -357,16 +414,33 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.resetSql(); next(); }, rqf.parse(), (req, res, next) => { + /* + select + SUM(num_matriculas) as num_matriculas, + ano_censo, + estado_id, + municipio_id, + etapa_resumida, + tempo_integral + from simcaq_matricula_agregada + group by + ano_censo, + estado_id, + municipio_id, + etapa_resumida, + tempo_integral + */ req.dims.state = true; req.dims.city = true; req.dims.education_level_short = true; //req.dims.integral_time = true; - req.sql.field('COUNT(*)', 'total') + req.sql.field('SUM(num_matriculas)', 'total') .field('simcaq_matricula_agregada.ano_censo', 'year') + .field('simcaq_matricula_agregada.tempo_integral', 'integral_time') .from('simcaq_matricula_agregada') .group('simcaq_matricula_agregada.ano_censo') + .group('simcaq_matricula_agregada.tempo_integral') .order('simcaq_matricula_agregada.ano_censo'); - //.where('((simcaq_matricula_agregada.tipo<=3 OR simcaq_matricula_agregada.tipo IS NULL) AND (simcaq_matricula_agregada.tipo_atendimento_turma IS NULL OR simcaq_matricula_agregada.tipo_atendimento_turma <= 2) AND simcaq_matricula_agregada.turma_turno_id <> 99)'); next(); }, rqf.build() ,query, id2str.transform(), (req, res, next) => { // constrói objeto de tempo integral e calcula diagnósticos diff --git a/src/libs/routes_v2/infrastructure.js b/src/libs/routes_v2/infrastructure.js index cc4c5931..01cc9264 100644 --- a/src/libs/routes_v2/infrastructure.js +++ b/src/libs/routes_v2/infrastructure.js @@ -335,7 +335,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Laboratório de informática let allInfLab = allSchools.clone(); allInfLab.where('escola_agregada.func_predio_escolar = 1') - .where('escola_agregada.reg_fund_ai = 1 OR escola_agregada.reg_fund_af = 1 OR escola_agregada.reg_medio_medio = 1 OR escola_agregada.reg_medio_integrado = 1 OR escola_agregada.reg_medio_normal = 1 OR escola_agregada.ensino_eja_fund = 1 OR escola_agregada.ensino_eja_medio = 1 OR escola_agregada.ensino_eja_prof = 1'); + .where('etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1'); req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1; let haveInfLab = allInfLab.clone(); @@ -347,13 +347,13 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1; let haveScienceLab = allScienceLab.clone(); - haveScienceLab.where('escola_agregada.lab_ciencias = 1'); + haveScienceLab.where('escola_agregada.lab_ciencias = 1 AND (etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1; // Parque infantil let allKidsPark = allSchools.clone(); allKidsPark.where('escola_agregada.func_predio_escolar = 1') - .where('escola_agregada.reg_infantil_creche = 1 OR escola_agregada.reg_infantil_preescola = 1 OR escola_agregada.reg_fund_ai = 1 OR escola_agregada.esp_infantil_creche = 1 OR escola_agregada.esp_exclusiva_creche = 1 OR escola_agregada.reg_esp_exclusiva_fund_ai = 1'); + .where('escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1'); req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1; let haveKidsPark = allKidsPark.clone(); @@ -372,27 +372,27 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Quadra let allSportsCourt = allScienceLab.clone(); - allSportsCourt.where('escola_agregada.localizacao_id = 1'); + allSportsCourt.where('escola_agregada.localizacao_id = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1; let haveSportsCourt = allSportsCourt.clone(); - haveSportsCourt.where('escola_agregada.quadra_esportes = 1'); + haveSportsCourt.where('escola_agregada.quadra_esportes = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1; // Quadra coberta req.queryIndex.allCoveredSportsCourt = req.queryIndex.allSportsCourt; let haveCoveredSportsCourt = allSportsCourt.clone(); - haveCoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 1'); + haveCoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveCoveredSportsCourt = req.querySet.push(haveCoveredSportsCourt) - 1; // Quadra Descoberta let allUncoveredSportsCourt = allSportsCourt.clone(); - allUncoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 0'); + allUncoveredSportsCourt.where('escola_agregada.quadra_esportes_coberta = 0 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.allUncoveredSportsCourt = req.querySet.push(allUncoveredSportsCourt) - 1; let haveUncoveredSportsCourt = allUncoveredSportsCourt.clone(); - haveUncoveredSportsCourt.where('escola_agregada.quadra_esportes_descoberta = 1'); + haveUncoveredSportsCourt.where('escola_agregada.quadra_esportes_descoberta = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveUncoveredSportsCourt = req.querySet.push(haveUncoveredSportsCourt) - 1; // Sala de direção @@ -445,14 +445,14 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInternet = req.queryIndex.allLibrariesReadingRoom; let haveInternet = allLibrariesReadingRoom.clone(); - haveInternet.where('escola_agregada.internet = 1'); + haveInternet.where('escola_agregada.internet = 1 AND localizacao_id = 2'); req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1; // Internet banda larga req.queryIndex.allBroadbandInternet = req.queryIndex.allLibraries; let haveBroadbandInternet = allLibraries.clone(); - haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1'); + haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1 AND localizacao_id = 1'); req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1; // Banheiro dentro do prédio @@ -466,7 +466,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInsideKidsBathroom = req.queryIndex.allKidsPark; let haveInsideKidsBathroom = allKidsPark.clone(); - haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1'); + haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1 AND (escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1) AND localizacao_id IN (1, 2)'); req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1; // Fornecimento de energia @@ -518,6 +518,13 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { haveAdaptedBuilding.where('escola_agregada.dependencias_pne = 1'); req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1; + // Adicionar pátio + /* + patio = 1 ou 2 -- patio existe, 1 -- a ser coberto, 2 -- é coberto + func_predio_escolar = 1 + localizacao_id = 1 ou 2 + */ + next(); }, multiQuery, (req, res, next) => { // Faz o matching entre os resultados -- GitLab From 8e84c1dd432df2b75b93555b833510ae8f109856 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Mon, 5 Jun 2023 10:20:18 -0300 Subject: [PATCH 093/123] classroom count v2 working but does not return data --- src/libs/routes_v2/classroomCount.js | 41 +++++----------------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 112d70db..47ea5e78 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -231,28 +231,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { //req.dims.school_year = true; req.dims.location = true; - /* - select - sum(dia_total), - sum(noite_total), - 'Brasil' as name, - ano_censo, - serie_ano_id, - estado_id, - municipio_id, - localizacao_id - from - simcaq_matricula_por_localizacao - where - serie_ano_id < 15 - group by - name, - ano_censo, - serie_ano_id, - estado_id, - municipio_id, - localizacao_id - */ + req.sql.field('sum(dia_total)', 'total_day') .field('sum(noite_total)', 'total_night') @@ -386,21 +365,19 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { } /* - select num_docentes, + select sum(num_docentes), 'Brasil' as name, ano_censo, - escola_estado_id, + estado_id, municipio_id from simcaq_docente_agregada */ - //req.dims.city = true; - //req.dims.state = true; - req.sql.field('simcaq_docente_agregada.num_docentes', 'total') + req.dims.city = true; + req.dims.state = true; + req.sql.field('SUM(simcaq_docente_agregada.num_docentes)', 'total') .field("'Brasil'", 'name') .field('simcaq_docente_agregada.ano_censo', 'year') - .field('escola_estado_id', 'state_id') - .field('municipio_id', 'city_id') .from('simcaq_docente_agregada') .group('simcaq_docente_agregada.ano_censo') .order('simcaq_docente_agregada.ano_censo'); @@ -433,13 +410,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.state = true; req.dims.city = true; req.dims.education_level_short = true; - //req.dims.integral_time = true; + req.dims.integral_time = true; req.sql.field('SUM(num_matriculas)', 'total') .field('simcaq_matricula_agregada.ano_censo', 'year') - .field('simcaq_matricula_agregada.tempo_integral', 'integral_time') .from('simcaq_matricula_agregada') .group('simcaq_matricula_agregada.ano_censo') - .group('simcaq_matricula_agregada.tempo_integral') .order('simcaq_matricula_agregada.ano_censo'); next(); }, rqf.build() ,query, id2str.transform(), (req, res, next) => { @@ -1200,8 +1175,6 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }) } - console.log('fim') - next(); }, response('classroom_count')); -- GitLab From 7631b576f431e672a97dad6442dd51741189682b Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Mon, 5 Jun 2023 10:28:57 -0300 Subject: [PATCH 094/123] trying to use the old version of classroom count --- src/libs/routes_v2/classroomCount.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libs/routes_v2/classroomCount.js b/src/libs/routes_v2/classroomCount.js index 47ea5e78..ea649bbf 100644 --- a/src/libs/routes_v2/classroomCount.js +++ b/src/libs/routes_v2/classroomCount.js @@ -228,7 +228,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.dims.state = true; req.dims.city = true; - //req.dims.school_year = true; + req.dims.school_year = true; req.dims.location = true; @@ -423,7 +423,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { req.integral_time = {} for (let i = 0; i < integral_time_result.length; ++i){ // Se cidade não foi criada, cria - let integral_time = integral_time_result[i] + let integral_time = integral_time_result[i]; let code = '' + integral_time.year + integral_time.city_id if (req.dims.school) code = code + integral_time.school_id @@ -568,12 +568,13 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { currentClassroomObj = obj; var id_attribute = req.dims.school ? "school_id" : "city_id" + var old_ti = ti; - while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) { // match da tabela de professores. + while (ti < req.teacher.length && req.teacher[ti][id_attribute] !== classroom[id_attribute]) // match da tabela de professores. ti++; - } - + if (ti === req.teacher.length) { + console.log(classroom[id_attribute], "not found") while (classroom[id_attribute] === enrollments[j][id_attribute]) enrollments.splice(j, 1) ti = old_ti; @@ -627,12 +628,13 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let enrollmentEducationLevel = req.educationSchoolYear[enrollment.school_year_id]; // Se não há um número de alunos por turna para a etapa de ensino, ignoramos a entrada - if(typeof enrollmentEducationLevel.numberStudentClass == 'undefined' || enrollmentEducationLevel.numberStudentClass == null) continue; + if(enrollmentEducationLevel.numberStudentClass == null) continue; // Adiciona nÃvel de educação para municÃpio/escola let educationLevel = null; if(!educationLevelSet.has(enrollmentEducationLevel.id)) { // cria e insere ordenadamente novo education level educationLevelSet.add(enrollmentEducationLevel.id); + let itHash = '' + enrollment.year + enrollment.city_id if (req.dims.school) itHash += enrollment.school_id @@ -699,7 +701,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let currentSchoolYear = null; if(enrollmentEducationLevel.id == 1){ let schoolYearHash = '' + enrollment.year + enrollment.city_id + enrollment.location_id + enrollment.school_year_id; - if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.school_id + if (req.dims.shool) schoolYearHash = schoolYearHash + enrollment.shcool_id if(schoolYearSet.has(schoolYearHash)) { // Busca a série escolar let k = 0; -- GitLab From 6b6f1e252d459b70a7a8d447d06e3459cc021353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Tue, 6 Jun 2023 11:52:12 -0300 Subject: [PATCH 095/123] update filters of school_infrastructure --- src/libs/routes_v2/infrastructure.js | 6 ----- src/libs/routes_v2/schoolInfrastructure.js | 28 +++++++++++----------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/src/libs/routes_v2/infrastructure.js b/src/libs/routes_v2/infrastructure.js index 01cc9264..89d7e278 100644 --- a/src/libs/routes_v2/infrastructure.js +++ b/src/libs/routes_v2/infrastructure.js @@ -518,12 +518,6 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { haveAdaptedBuilding.where('escola_agregada.dependencias_pne = 1'); req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1; - // Adicionar pátio - /* - patio = 1 ou 2 -- patio existe, 1 -- a ser coberto, 2 -- é coberto - func_predio_escolar = 1 - localizacao_id = 1 ou 2 - */ next(); }, multiQuery, (req, res, next) => { diff --git a/src/libs/routes_v2/schoolInfrastructure.js b/src/libs/routes_v2/schoolInfrastructure.js index da4d4593..00b87e03 100644 --- a/src/libs/routes_v2/schoolInfrastructure.js +++ b/src/libs/routes_v2/schoolInfrastructure.js @@ -387,7 +387,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // ( reg_fund_ai_t1=1 | reg_fund_af_t1=1 | reg_medio_medio_t1=1 | ensino_eja_fund= 1 | ensino_eja_medio= 1 | ensino_eja_prof= 1 | esp_eja_fund=1 | // esp_eja_medio=1 | ensino_esp_exclusiva_eja_prof=1) então conta id let allInfLab = allSchools.clone(); - allInfLab.where('reg_fund_ai_t1=1 OR reg_fund_af_t1=1 OR reg_medio_medio_t1=1 OR ensino_eja_fund=1 OR ensino_eja_medio=1 OR ensino_eja_prof=1 OR esp_eja_fund=1 OR esp_eja_medio=1 OR ensino_esp_exclusiva_eja_prof=1'); + allInfLab.where('etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1'); req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1; let haveInfLab = allInfLab.clone(); @@ -404,7 +404,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1; let haveScienceLab = allScienceLab.clone(); - haveScienceLab.where('escola_agregada.lab_ciencias = true'); + haveScienceLab.where('escola_agregada.lab_ciencias = 1 AND (etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1; let needScienceLab = allScienceLab.clone(); @@ -415,7 +415,7 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Se (situacao_de_funcionamento=1) and (ensino_regular=1 OR ensino_eja=1 OR educacao_profissional=1) and // (local_func_predio_escolar=1) and (dependencia_adm_id<=3) and (reg_infantil_creche_t1=1 or reg_infantil_preescola_t1=1 or reg_fund_ai_t1=1) então conta id let allKidsPark = allSchools.clone(); - allKidsPark.where('reg_infantil_creche_t1=1 OR reg_infantil_preescola_t1=1 OR reg_fund_ai_t1=1'); + allKidsPark.where('escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1'); req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1; let haveKidsPark = allKidsPark.clone(); @@ -441,15 +441,15 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { // Quadra de esportes let allSportsCourt = allSchools.clone(); - allSportsCourt.where('reg_fund_ai_t1=1 or reg_fund_af_t1=1 or reg_medio_medio_t1=1 or ensino_eja_fund= 1 or ensino_eja_medio= 1 or ensino_eja_prof= 1 or esp_eja_fund=1 or esp_eja_medio=1 or ensino_esp_exclusiva_eja_prof=1'); + allSportsCourt.where('escola_agregada.localizacao_id = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1; let haveSportsCourt = allSportsCourt.clone(); - haveSportsCourt.where('escola_agregada.quadra_esportes = 1'); + haveSportsCourt.where('escola_agregada.quadra_esportes = 1 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1; let needSportsCourt = allSportsCourt.clone(); - needSportsCourt.where('escola_agregada.quadra_esportes = 0'); + needSportsCourt.where('escola_agregada.quadra_esportes = 0 AND (etapa_en_fundamental_anos_iniciais = 1 OR etapa_en_fundamental_anos_finais = 1 OR etapa_en_medio = 1)'); req.queryIndex.needSportsCourt = req.querySet.push(needSportsCourt) - 1; // Quadras a serem cobertas @@ -468,11 +468,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allCourtyard = req.queryIndex.allSchools; let haveCourtyard = allSchools.clone(); - haveCourtyard.where('escola_agregada.patio = 1 OR escola_agregada.patio = 2'); + haveCourtyard.where('escola_agregada.func_predio_escolar = 1 AND (escola_agregada.patio = 1 OR escola_agregada.patio = 2)'); req.queryIndex.haveCourtyard = req.querySet.push(haveCourtyard) - 1; let needCourtyard = allSchools.clone(); - needCourtyard.where('escola_agregada.patio = 0'); + needCourtyard.where('escola_agregada.func_predio_escolar = 1 AND escola_agregada.patio = 0'); req.queryIndex.needCourtyard = req.querySet.push(needCourtyard) - 1; // Pátios a serem cobertos @@ -554,11 +554,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInternet = req.queryIndex.allCountrySchools; let haveInternet = allCountrySchools.clone(); - haveInternet.where('escola_agregada.internet = 1'); + haveInternet.where('escola_agregada.internet = 1 AND localizacao_id = 2'); req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1; let needInternet = allCountrySchools.clone(); - needInternet.where('escola_agregada.internet = 0'); + needInternet.where('escola_agregada.internet = 0 AND localizacao_id = 2'); req.queryIndex.needInternet = req.querySet.push(needInternet) - 1; // Internet banda larga @@ -567,11 +567,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allBroadbandInternet = req.queryIndex.allUrbanSchools; let haveBroadbandInternet = allUrbanSchools.clone(); - haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1'); + haveBroadbandInternet.where('escola_agregada.internet_banda_larga = 1 AND localizacao_id = 1'); req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1; let needBroadbandInternet = allUrbanSchools.clone(); - needBroadbandInternet.where('escola_agregada.internet_banda_larga = 0'); + needBroadbandInternet.where('escola_agregada.internet_banda_larga = 0 AND localizacao_id = 1'); req.queryIndex.needBroadbandInternet = req.querySet.push(needBroadbandInternet) - 1; // Banheiro @@ -593,11 +593,11 @@ infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { req.queryIndex.allInsideKidsBathroom = req.querySet.push(allInsideKidsBathroom) - 1; let haveInsideKidsBathroom = allInsideKidsBathroom.clone(); - haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1'); + haveInsideKidsBathroom.where('escola_agregada.sanitario_ei = 1 AND (escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1) AND localizacao_id IN (1, 2)'); req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1; let needInsideKidsBathroom = allInsideKidsBathroom.clone(); - needInsideKidsBathroom.where('escola_agregada.sanitario_ei = 0'); + needInsideKidsBathroom.where('escola_agregada.sanitario_ei = 0 AND (escola_agregada.etapa_ed_infantil_creche = 1 OR escola_agregada.etapa_en_fundamental_anos_iniciais = 1) AND localizacao_id IN (1, 2)'); req.queryIndex.needInsideKidsBathroom = req.querySet.push(needInsideKidsBathroom) - 1; // Fornecimento de energia -- GitLab From 2007841fe42e81ee85f3a0d643e5da840982111d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 22 Jun 2023 09:18:15 -0300 Subject: [PATCH 096/123] Changes to simcaq infrastructure --- src/libs/convert/scholarDependency.js | 76 ++++++++++++++++ src/libs/middlewares/id2str.js | 4 +- src/libs/routes_v2/api.js | 3 + .../routes_v2/simcaqSchoolInfrastructure.js | 87 +++++++++++++++++++ 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 src/libs/convert/scholarDependency.js create mode 100644 src/libs/routes_v2/simcaqSchoolInfrastructure.js diff --git a/src/libs/convert/scholarDependency.js b/src/libs/convert/scholarDependency.js new file mode 100644 index 00000000..25684b9b --- /dev/null +++ b/src/libs/convert/scholarDependency.js @@ -0,0 +1,76 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +module.exports = function scholarDependency(id) { + switch (id) { + case 1: + return "Biblioteca"; + case 2: + return "Sala de leitura"; + case 3: + return "Laboratório de informática"; + case 4: + return "Laboratório de ciências"; + case 5: + return "Parque infantil"; + case 6: + return "Quadra poliesportiva"; + case 7: + return "Quadras a serem cobertas"; + case 8: + return "Pátio"; + case 9: + return "Pátios a serem cobertos"; + case 10: + return "Sala de direção"; + case 11: + return "Secretaria"; + case 12: + return "Sala de professores"; + case 13: + return "Cozinha"; + case 14: + return "Despensa"; + case 15: + return "Almoxarifado"; + case 16: + return "Internet"; + case 17: + return "Internet banda larga"; + case 18: + return "Banheiro dentro do prédio"; + case 19: + return "Banheiro adequado para educação infantil dentro do prédio"; + case 20: + return "Fornecimento de energia"; + case 21: + return "Abastecimento de água"; + case 22: + return "Ãgua filtrada"; + case 23: + return "Coleta de esgoto"; + case 24: + return "Dependências adaptadas para pessoas com deficiências"; + case 25: + return "Banheiros adaptados para pessoas com deficiências"; + default: + return "Dependência escolar desconhecida"; + } +} \ No newline at end of file diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js index 39d819aa..cb549d3d 100644 --- a/src/libs/middlewares/id2str.js +++ b/src/libs/middlewares/id2str.js @@ -100,6 +100,7 @@ const admDependencyPub = require(`${libs}/convert/admDependencyPub`); const supplyDimension = require(`${libs}/convert/supplyDimension`); const type = require(`${libs}/convert/type`); const level = require(`${libs}/convert/level`); +const scholarDependency = require(`${libs}/convert/scholarDependency`); const ids = { gender_id: gender, @@ -191,7 +192,8 @@ const ids = { shift_id: shift, supply_dimension_id: supplyDimension, type_id: type, - level_id: level + level_id: level, + scholar_dependency_id: scholarDependency }; function transform(removeId=false) { diff --git a/src/libs/routes_v2/api.js b/src/libs/routes_v2/api.js index 5c00d3fe..a8e1e1b7 100644 --- a/src/libs/routes_v2/api.js +++ b/src/libs/routes_v2/api.js @@ -160,6 +160,8 @@ const simcaqAggregatedEnrollment = require(`${libs}/routes_v2/simcaqAggregatedEn const simcaqTeacherCityPlan = require(`${libs}/routes_v2/simcaqTeacherCityPlan`); +const simcaqSchoolInfrastructure = require(`${libs}/routes_v2/simcaqSchoolInfrastructure`); + api.get('/', (req, res) => { res.json({ msg: 'SimCAQ API v2 is running' }); }); @@ -231,5 +233,6 @@ api.use('/simcaq_number_of_teachers', simcaqNumberOfTeachers); api.use('/simcaq_enrollment_projection', simcaqEnrollmentProjection); api.use('/simcaq_aggregated_enrollment', simcaqAggregatedEnrollment); api.use('/simcaq_teacher_city_plan', simcaqTeacherCityPlan); +api.use('/simcaq_school_infrastructure', simcaqSchoolInfrastructure); module.exports = api; diff --git a/src/libs/routes_v2/simcaqSchoolInfrastructure.js b/src/libs/routes_v2/simcaqSchoolInfrastructure.js new file mode 100644 index 00000000..f10022cb --- /dev/null +++ b/src/libs/routes_v2/simcaqSchoolInfrastructure.js @@ -0,0 +1,87 @@ +/* +Copyright (C) 2016 Centro de Computacao Cientifica e Software Livre +Departamento de Informatica - Universidade Federal do Parana - C3SL/UFPR + +This file is part of simcaq-node. + +simcaq-node is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +simcaq-node is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with simcaq-node. If not, see <https://www.gnu.org/licenses/>. +*/ + +const express = require('express'); + +const simcaqSchoolInfrastructureApp = express.Router(); + +const libs = `${process.cwd()}/libs`; + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`).query; + +const response = require(`${libs}/middlewares/response`); + +const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); + +const reqBody = require(`${libs}/middlewares/reqBody`); + +const config = require(`${libs}/config`); + +const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware; + +let rqf = new ReqQueryFields(); + +const id2str = require(`${libs}/middlewares/id2str`); + +simcaqSchoolInfrastructureApp.use(cache('15 day')); + +rqf.addField({ + name: 'filter', + field: false, + where: true +}).addField({ + name: 'dims', + field: true, + where: false +}).addValue({ + name: 'year', + table: 'simcaq_school_infrastructure', + tableField: 'ano_censo', + where: { + relation: '=', + type: 'integer', + field: 'ano_censo' + } +}).addValue({ + name: 'scholar_dependency', + table: 'simcaq_school_infrastructure', + tableField: 'scholar_dependency_id', + where: { + relation: '=', + type: 'integer', + field: 'scholar_dependency_id' + } +}); + +simcaqSchoolInfrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { + req.sql.from('simcaq_school_infrastructure') + .field('simcaq_school_infrastructure.ano_censo', 'year') + .field('simcaq_school_infrastructure.scholar_dependency_id', 'scholar_dependency_id') + .field('SUM(simcaq_school_infrastructure.total_schools)', 'total_schools') + .field('SUM(total_no_dependency)', 'total_schools_without_dependency') + .field('SUM(total_with_dependency)', 'total_schools_with_dependency') + .group('simcaq_school_infrastructure.ano_censo') + .group('simcaq_school_infrastructure.scholar_dependency_id'); + next(); +}, query, id2str.transform(), response('simcaqSchoolInfrastructure')); + +module.exports = simcaqSchoolInfrastructureApp; -- GitLab From 0ff1fc58bd045a84cf1f084804912ce35a3f33b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 29 Jun 2023 10:45:25 -0300 Subject: [PATCH 097/123] Fix issue with classroom count rounding --- src/libs/routes_v1/classroomCount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index 4f76bed3..54add0ee 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -642,7 +642,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { education_level_short_name: enrollmentEducationLevel.name, enrollment: { integral_percentage: req.dims.school ? level_diagnosis : Math.max(level_diagnosis, enrollmentEducationLevel.integralTimeOfferGoal), - integral_time: req.dims.school ? integral_time : Math.round(integral_time_total * Math.max(level_diagnosis, enrollmentEducationLevel.integralTimeOfferGoal)/100), + integral_time: req.dims.school ? integral_time : Math.round((integral_time_total * Math.max(level_diagnosis, enrollmentEducationLevel.integralTimeOfferGoal)/100) * 10) / 10, integral_time_total: integral_time_total, total_enrollment_day: 0, total_enrollment_night: 0, -- GitLab From 92db8770adf8168889f1058299a0d8fb5e0f26d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Thu, 29 Jun 2023 11:48:07 -0300 Subject: [PATCH 098/123] Fix issue with schools without teachers --- src/libs/routes_v1/classroomCount.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index 54add0ee..4090fe88 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -1147,6 +1147,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { educationLevel.teacherNumber.careerLevels = []; req.teacherFormation.forEach((formation, i) => { + if (educationLevel.teacherNumber.total_teacher < 1) { + educationLevel.teacherNumber.total_teacher_full_period = 1; + educationLevel.teacherNumber.total_teacher_partial = 1; + } + let totalTeacherFullPeriodCareer = educationLevel.teacherNumber.total_teacher_full_period * teacherByFormation[i]; let totalTeacherPartialCareer = educationLevel.teacherNumber.total_teacher_partial * teacherByFormation[i]; -- GitLab From 1afb1d56c2a1d950f8d62a8acc64fdc8837cd5c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 7 Jul 2023 16:28:18 -0300 Subject: [PATCH 099/123] add tests to change number of classes to the minimun necessary --- src/libs/routes_v1/classroomCount.js | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index 4090fe88..4b8350bc 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -255,6 +255,21 @@ rqf.addField({ } }); +function minimunClasses(education_level_short_id) { + switch(education_level_short_id) { + case 3: // Ensino Fundamental - anos iniciais + return 5; + case 4: // Ensino Fundamental - anos finais + return 4; + case 5: // Ensino Médio + return 3; + case 6: // EJA + return 2; + default: + return 0; + } +} + classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let classSize = JSON.parse(req.body.class_size) || null; let integralTime = JSON.parse(req.body.integral_time) || null; @@ -782,6 +797,27 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { educationLevel.enrollment.total_classrooms_needed = educationLevel.classes_school_year.reduce(reducer('total_classrooms_needed'), 0); } + // MatrÃculas diurnas + let minimun_classes = minimunClasses(educationLevel.education_level_short_id); + let partial_day_enrollment = educationLevel.enrollment.total_enrollment_day - educationLevel.enrollment.integral_time; + if (partial_day_enrollment >= (minimun_classes * 10)) { + if (educationLevel.enrollment.day_classes < minimun_classes) { + educationLevel.enrollment.day_classes = minimun_classes; + } + } + // MatrÃculas integrais + if (educationLevel.enrollment.integral_time >= (minimun_classes * 10)) { + if (educationLevel.enrollment.full_period_classes < minimun_classes) { + educationLevel.enrollment.full_period_classes = minimun_classes; + } + } + // MatrÃculas noturnas + if (educationLevel.enrollment.total_enrollment_night >= (minimun_classes * 10)) { + if (educationLevel.enrollment.night_classes < minimun_classes) { + educationLevel.enrollment.night_classes = minimun_classes; + } + } + enrollment = enrollments[j]; } -- GitLab From 64d74cc37b8eb103342d6d595d5170584dfb0c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 7 Jul 2023 16:57:14 -0300 Subject: [PATCH 100/123] change where test is made in code --- src/libs/routes_v1/classroomCount.js | 37 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index 4b8350bc..fd5b5f70 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -795,27 +795,28 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { educationLevel.enrollment.full_period_classes = educationLevel.classes_school_year.reduce(reducer('full_period_classes'), 0); educationLevel.enrollment.day_classes = educationLevel.classes_school_year.reduce(reducer('day_classes'), 0); educationLevel.enrollment.total_classrooms_needed = educationLevel.classes_school_year.reduce(reducer('total_classrooms_needed'), 0); - } - - // MatrÃculas diurnas - let minimun_classes = minimunClasses(educationLevel.education_level_short_id); - let partial_day_enrollment = educationLevel.enrollment.total_enrollment_day - educationLevel.enrollment.integral_time; - if (partial_day_enrollment >= (minimun_classes * 10)) { - if (educationLevel.enrollment.day_classes < minimun_classes) { - educationLevel.enrollment.day_classes = minimun_classes; + + // MatrÃculas diurnas + let minimun_classes = minimunClasses(educationLevel.education_level_short_id); + let partial_day_enrollment = educationLevel.enrollment.total_enrollment_day - educationLevel.enrollment.integral_time; + if (partial_day_enrollment >= (minimun_classes * 10)) { + if (educationLevel.enrollment.day_classes < minimun_classes) { + educationLevel.enrollment.day_classes = minimun_classes; + } } - } - // MatrÃculas integrais - if (educationLevel.enrollment.integral_time >= (minimun_classes * 10)) { - if (educationLevel.enrollment.full_period_classes < minimun_classes) { - educationLevel.enrollment.full_period_classes = minimun_classes; + // MatrÃculas integrais + if (educationLevel.enrollment.integral_time >= (minimun_classes * 10)) { + if (educationLevel.enrollment.full_period_classes < minimun_classes) { + educationLevel.enrollment.full_period_classes = minimun_classes; + } } - } - // MatrÃculas noturnas - if (educationLevel.enrollment.total_enrollment_night >= (minimun_classes * 10)) { - if (educationLevel.enrollment.night_classes < minimun_classes) { - educationLevel.enrollment.night_classes = minimun_classes; + // MatrÃculas noturnas + if (educationLevel.enrollment.total_enrollment_night >= (minimun_classes * 10)) { + if (educationLevel.enrollment.night_classes < minimun_classes) { + educationLevel.enrollment.night_classes = minimun_classes; + } } + } enrollment = enrollments[j]; -- GitLab From 51d75c3f1de33d509bc497a6eaec3d787123b39d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 7 Jul 2023 17:58:56 -0300 Subject: [PATCH 101/123] do test when evaluating currentEducation --- src/libs/routes_v1/classroomCount.js | 42 ++++++++++++++-------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index fd5b5f70..8afcda14 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -795,27 +795,6 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { educationLevel.enrollment.full_period_classes = educationLevel.classes_school_year.reduce(reducer('full_period_classes'), 0); educationLevel.enrollment.day_classes = educationLevel.classes_school_year.reduce(reducer('day_classes'), 0); educationLevel.enrollment.total_classrooms_needed = educationLevel.classes_school_year.reduce(reducer('total_classrooms_needed'), 0); - - // MatrÃculas diurnas - let minimun_classes = minimunClasses(educationLevel.education_level_short_id); - let partial_day_enrollment = educationLevel.enrollment.total_enrollment_day - educationLevel.enrollment.integral_time; - if (partial_day_enrollment >= (minimun_classes * 10)) { - if (educationLevel.enrollment.day_classes < minimun_classes) { - educationLevel.enrollment.day_classes = minimun_classes; - } - } - // MatrÃculas integrais - if (educationLevel.enrollment.integral_time >= (minimun_classes * 10)) { - if (educationLevel.enrollment.full_period_classes < minimun_classes) { - educationLevel.enrollment.full_period_classes = minimun_classes; - } - } - // MatrÃculas noturnas - if (educationLevel.enrollment.total_enrollment_night >= (minimun_classes * 10)) { - if (educationLevel.enrollment.night_classes < minimun_classes) { - educationLevel.enrollment.night_classes = minimun_classes; - } - } } @@ -950,6 +929,27 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { currentEducation.enrollment.night_classes += cityEducation.enrollment.night_classes; currentEducation.enrollment.total_classrooms_needed += cityEducation.enrollment.total_classrooms_needed; + // MatrÃculas diurnas + let minimun_classes = minimunClasses(currentEducation.education_level_short_id); + let partial_day_enrollment = currentEducation.enrollment.total_enrollment_day - currentEducation.enrollment.integral_time; + if (partial_day_enrollment >= (minimun_classes * 10)) { + if (currentEducation.enrollment.day_classes < minimun_classes) { + currentEducation.enrollment.day_classes = minimun_classes; + } + } + // MatrÃculas integrais + if (currentEducation.enrollment.integral_time >= (minimun_classes * 10)) { + if (currentEducation.enrollment.full_period_classes < minimun_classes) { + currentEducation.enrollment.full_period_classes = minimun_classes; + } + } + // MatrÃculas noturnas + if (currentEducation.enrollment.total_enrollment_night >= (minimun_classes * 10)) { + if (currentEducation.enrollment.night_classes < minimun_classes) { + currentEducation.enrollment.night_classes = minimun_classes; + } + } + // Caso tenha feito o cálculo de professores, atualiza os valores if (req.teacherCalc) { currentEducation.teacherNumber.total_teacher += cityEducation.teacherNumber.total_teacher; -- GitLab From 5d9f4ca6091d9a212945885eb887dc02bdb98306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leon=20A=2E=20Okida=20Gon=C3=A7alves?= <laog19@inf.ufpr.br> Date: Fri, 7 Jul 2023 18:09:45 -0300 Subject: [PATCH 102/123] do test on last processing of education level object --- src/libs/routes_v1/classroomCount.js | 44 +++++++++++++++------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index 8afcda14..dc3d1fb5 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -929,27 +929,6 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { currentEducation.enrollment.night_classes += cityEducation.enrollment.night_classes; currentEducation.enrollment.total_classrooms_needed += cityEducation.enrollment.total_classrooms_needed; - // MatrÃculas diurnas - let minimun_classes = minimunClasses(currentEducation.education_level_short_id); - let partial_day_enrollment = currentEducation.enrollment.total_enrollment_day - currentEducation.enrollment.integral_time; - if (partial_day_enrollment >= (minimun_classes * 10)) { - if (currentEducation.enrollment.day_classes < minimun_classes) { - currentEducation.enrollment.day_classes = minimun_classes; - } - } - // MatrÃculas integrais - if (currentEducation.enrollment.integral_time >= (minimun_classes * 10)) { - if (currentEducation.enrollment.full_period_classes < minimun_classes) { - currentEducation.enrollment.full_period_classes = minimun_classes; - } - } - // MatrÃculas noturnas - if (currentEducation.enrollment.total_enrollment_night >= (minimun_classes * 10)) { - if (currentEducation.enrollment.night_classes < minimun_classes) { - currentEducation.enrollment.night_classes = minimun_classes; - } - } - // Caso tenha feito o cálculo de professores, atualiza os valores if (req.teacherCalc) { currentEducation.teacherNumber.total_teacher += cityEducation.teacherNumber.total_teacher; @@ -1156,6 +1135,29 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { } else { + + // MatrÃculas diurnas + let minimun_classes = minimunClasses(educationLevel.education_level_short_id); + let partial_day_enrollment = educationLevel.enrollment.total_enrollment_day - educationLevel.enrollment.integral_time; + if (partial_day_enrollment >= (minimun_classes * 10)) { + if (educationLevel.enrollment.day_classes < minimun_classes) { + educationLevel.enrollment.day_classes = minimun_classes; + } + } + // MatrÃculas integrais + if (educationLevel.enrollment.integral_time >= (minimun_classes * 10)) { + if (educationLevel.enrollment.full_period_classes < minimun_classes) { + educationLevel.enrollment.full_period_classes = minimun_classes; + } + } + // MatrÃculas noturnas + if (educationLevel.enrollment.total_enrollment_night >= (minimun_classes * 10)) { + if (educationLevel.enrollment.night_classes < minimun_classes) { + educationLevel.enrollment.night_classes = minimun_classes; + } + } + + let teachingTimeFullPeriod = educationLevel.enrollment.full_period_classes * currentTeachingHours[2].value * req.schoolDays[educationLevelId-1].value; let teachingTimeNight = educationLevel.enrollment.night_classes * currentTeachingHours[1].value * req.schoolDays[educationLevelId-1].value; let teachingTimeDay = educationLevel.enrollment.day_classes * currentTeachingHours[0].value * req.schoolDays[educationLevelId-1].value; -- GitLab From 93f423e0a3eda7837b0de78c951383ca9613a3e5 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 10 Jul 2023 10:46:10 -0300 Subject: [PATCH 103/123] [ADD] json field names --- src/libs/models/user.js | 9 +-------- src/libs/routes_v1/activity.js | 14 ++++++++++---- src/libs/routes_v1/publication.js | 8 ++++++-- src/libs/routes_v1/user.js | 13 +++++++++++++ 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/libs/models/user.js b/src/libs/models/user.js index ce65500a..044b36b9 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -26,9 +26,6 @@ var User = db.define("User",{ hashed_password:{ type: Sequelize.STRING, allowNull: false, - validate: { - notNull: { msg: "O campo Senha é obrigatório." }, - } }, salt: { type: Sequelize.STRING, @@ -72,19 +69,15 @@ var User = db.define("User",{ }, course:{ type: Sequelize.STRING, - allowNull: false, }, complement:{ - type: Sequelize.STRING, - allowNull: false, + type: Sequelize.STRING }, address:{ type: Sequelize.STRING, - allowNull: false, }, phone:{ type: Sequelize.STRING, - allowNull: false, }, segment:{ type: Sequelize.STRING, diff --git a/src/libs/routes_v1/activity.js b/src/libs/routes_v1/activity.js index 0c6e1d02..bec69500 100644 --- a/src/libs/routes_v1/activity.js +++ b/src/libs/routes_v1/activity.js @@ -20,6 +20,8 @@ const fileWorker = require('./file.controller.js'); let upload = require('../middlewares/multer.config.js'); +const authorized = require(`${libs}/middlewares/authorize.js`); + function emailSyntax(email) { const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; return regex.test(email); @@ -29,7 +31,9 @@ activityApp.get('/', async (req, res, next) => { const page = parseInt(req.query.page) || 1; const pageSize = parseInt(req.query.pageSize) || 5; try { - const totalCount = await Activity.count(); + const totalCount = await Activity.count({where: { + is_draft: false + }}); const offset = (page - 1) * pageSize; const acts = await Activity.findAll({ @@ -54,18 +58,20 @@ activityApp.get('/', async (req, res, next) => { } }); -activityApp.get('/', async (req, res, next) => { +activityApp.get('/drafts', async (req, res, next) => { const page = parseInt(req.query.page) || 1; const pageSize = parseInt(req.query.pageSize) || 5; try { - const totalCount = await Activity.count(); + const totalCount = await Activity.count({where: { + is_draft: true + }}); const offset = (page - 1) * pageSize; const acts = await Activity.findAll({ offset, limit: pageSize, where: { - is_draft: acts + is_draft: true }, order:[ ['date', 'DESC']] diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index e1e3b0f6..e8792e70 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -33,7 +33,9 @@ pubApp.get('/', async (req, res, next) => { const page = parseInt(req.query.page) || 1; // Current page number const pageSize = parseInt(req.query.pageSize) || 5; // Number of items per page try { - const totalCount = await Publication.count(); + const totalCount = await Publication.count({ where: { + is_draft: false + }}); const offset = (page - 1) * pageSize; const publis = await Publication.findAll({ @@ -62,7 +64,9 @@ pubApp.get('/drafts', async (req, res, next) => { try { // Count total number of items - const totalCount = await Publication.count(); + const totalCount = await Publication.count({ where: { + is_draft: true + }}); // Calculate offset based on page and pageSize const offset = (page - 1) * pageSize; diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index eedf07b5..5ccfec79 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -95,8 +95,15 @@ userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, n userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => { let u = req.user.toJSON(); + u._id = u.id; + u.institutionName = u.institution_name; + u.receiveEmails = u.receive_email; + delete u.id; + delete u.institution_name; + delete u.receive_email; delete u.hashed_password; delete u.salt; + req.result = u; next(); }, response('user')); @@ -108,6 +115,12 @@ userApp.get('/:id', (req, res, next) => { res.json({ msg: "O usuário não está cadastrado" }); } else { let u = user.toJSON(); + u._id = u.id; + u.institutionName = u.institution_name; + u.receiveEmails = u.receive_email; + delete u.id; + delete u.institution_name; + delete u.receive_email; delete u.hashed_password; delete u.salt; req.result = u; -- GitLab From e32122e5318f3cc862e53448e9ac110799a01545 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 10 Jul 2023 11:02:10 -0300 Subject: [PATCH 104/123] [FIX] res json --- src/libs/routes_v1/user.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 5ccfec79..a80be774 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -271,6 +271,12 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), async ( return next({ message: 'Erro ao atualizar usuário' }); }}) let u = user.toJSON(); + u._id = u.id; + u.institutionName = u.institution_name; + u.receiveEmails = u.receive_email; + delete u.id; + delete u.institution_name; + delete u.receive_email; delete u.hashed_password; delete u.salt; delete u.password; -- GitLab From 5dcdc1306e7aac8cdcea014812241352221ca622 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 10 Jul 2023 11:31:20 -0300 Subject: [PATCH 105/123] [FIX] Update password error --- src/libs/routes_v1/user.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index a80be774..2f92370b 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -236,13 +236,11 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), async ( user.institutionName = req.body.institutionName || user.institutionName; user.state = req.body.state || user.state; user.city = req.body.city || user.city; - user.receiveEmails = req.body.receiveEmails || user.receiveEmails; + user.receive_email = req.body.receiveEmails || user.receive_email; user.citesegment = req.body.citesegment || user.citesegment; user.citerole = req.body.citerole || user.citerole; - - - if ((req.body.password) && (req.body.newpassword)) { + if ((req.body.password != "") && (req.body.newpassword != "")) { if (req.body.password != req.body.newpassword) { if (user.checkPassword(user, req.body.password)) { await user.update({password:req.body.newpassword}); -- GitLab From 6a345d172158b7d9df6daebfcc796f686227284d Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Tue, 11 Jul 2023 10:29:29 -0300 Subject: [PATCH 106/123] [FIX] Create and Update problems --- src/libs/models/publication.js | 7 +++++++ src/libs/models/user.js | 20 ++++++++++++++++---- src/libs/routes_v1/user.js | 10 ++++++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/libs/models/publication.js b/src/libs/models/publication.js index 5b324e72..b750f95e 100644 --- a/src/libs/models/publication.js +++ b/src/libs/models/publication.js @@ -14,6 +14,10 @@ var Publication = db.define("Publication",{ allowNull:false, validate: { notNull: { msg: "O campo categoria é obrigatória e aceita apenas os valores 'Artigo', 'Tese', 'Dissertação', 'Relatório', 'Periódico."}, + isIn:{ + args: [["Artigo", "Tese", "Dissertação", "Relatório", "Periódico"]], + msg: "O campo categoria é obrigatória e aceita apenas os valores 'Artigo', 'Tese', 'Dissertação', 'Relatório', 'Periódico'." + } } }, title:{ @@ -37,6 +41,9 @@ var Publication = db.define("Publication",{ allowNull:false, validate: { notNull: { msg: "O campo origem é obrigatória e aceita apenas os valores 'Baixar', 'Acessar'."}, + isIn:{ + args: [["Baixar", "Acessar"]], + msg: "O campo origem é obrigatória e aceita apenas os valores 'Baixar', 'Acessar'."} } }, link:{ diff --git a/src/libs/models/user.js b/src/libs/models/user.js index 044b36b9..405909eb 100644 --- a/src/libs/models/user.js +++ b/src/libs/models/user.js @@ -18,6 +18,7 @@ var User = db.define("User",{ unique: true, validate: { notNull: { msg: "O campo Email é obrigatório." }, + notEmpty: { msg: "O campo Email é obrigatório." } } }, password:{ @@ -36,6 +37,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo Nome é obrigatório." }, + notEmpty: { msg: "O campo Nome é obrigatório." } } }, nickname:{ @@ -43,6 +45,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo Apelido é obrigatório." }, + notEmpty: { msg: "O campo Apelido é obrigatório." } } }, cpf:{ @@ -51,6 +54,7 @@ var User = db.define("User",{ unique: true, validate: { notNull: { msg: "O campo CPF é obrigatório." }, + notEmpty: { msg: "O campo CPF é obrigatório." } } }, cep:{ @@ -58,6 +62,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo CEP é obrigatório." }, + notEmpty: { msg: "O campo CEP é obrigatório." } } }, schooling:{ @@ -65,6 +70,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo Formação é obrigatório." }, + notEmpty: { msg: "O campo Formação é obrigatório." } } }, course:{ @@ -84,6 +90,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo Segmento é obrigatório." }, + notEmpty: { msg: "O campo Segmento é obrigatório." } } }, role:{ @@ -91,6 +98,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo Função é obrigatório." }, + notEmpty: { msg: "O campo Função é obrigatório." } } }, institution_name:{ @@ -98,6 +106,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo Instituição em que trabalha ou estuda é obrigatório." }, + notEmpty: { msg: "O campo Instituição em que trabalha ou estuda é obrigatório." } } }, state:{ @@ -105,6 +114,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo Estado é obrigatório." }, + notEmpty: { msg: "O campo Estado é obrigatório." } } }, city:{ @@ -112,6 +122,7 @@ var User = db.define("User",{ allowNull: false, validate: { notNull: { msg: "O campo Cidade é obrigatório." }, + notEmpty: { msg: "O campo Cidade é obrigatório." } } }, receive_email:{ @@ -126,6 +137,7 @@ var User = db.define("User",{ allowNull:false, validate: { notNull: { msg: "O campo origem é obrigatória e aceita apenas os valores 'LDE', 'SimCAQ' e 'MAPFOR'."}, + notEmpty: { msg: "O campo origem é obrigatória e aceita apenas os valores 'LDE', 'SimCAQ' e 'MAPFOR'."} } }, verified:{ @@ -169,10 +181,10 @@ User.generateObjectId = function(){ } const setSaltAndPassword = user => { - // if (user.changed('password')) { - user.salt = User.generateSalt() - user.hashed_password = User.encryptPassword(user.password, user.salt).toString('hex'); - // } + if (user.changed('password')) { + user.salt = User.generateSalt() + user.hashed_password = User.encryptPassword(user.password, user.salt).toString('hex'); + } } const setObjectId = user => { diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 2f92370b..d35d47f4 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -108,6 +108,10 @@ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, re next(); }, response('user')); +function isEmpty(str) { + return (!str || str.length === 0 ); +} + userApp.get('/:id', (req, res, next) => { User.findByPk(req.params.id).then((user) => { if (!user) { @@ -136,7 +140,8 @@ userApp.post('/', async (req, res, next) => { if (typeof req.body.password === 'undefined' || !req.body.password) { res.statusCode = 400; return res.json({ errors: ["O campo senha é obrigatório"] }); - } else { + } + else { let user = await User.create({ id: 0, email: req.body.email, @@ -240,7 +245,8 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), async ( user.citesegment = req.body.citesegment || user.citesegment; user.citerole = req.body.citerole || user.citerole; - if ((req.body.password != "") && (req.body.newpassword != "")) { + if((!isEmpty(req.body.password)) && (!isEmpty(req.body.newpassword))){ + console.log("ENTREI INFELIZMENTE") if (req.body.password != req.body.newpassword) { if (user.checkPassword(user, req.body.password)) { await user.update({password:req.body.newpassword}); -- GitLab From 3111033d76254cd27332ad1271bed929cf706073 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Tue, 11 Jul 2023 10:42:34 -0300 Subject: [PATCH 107/123] [Remove] Comment --- src/libs/routes_v1/user.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index d35d47f4..37d22d42 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -246,7 +246,6 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), async ( user.citerole = req.body.citerole || user.citerole; if((!isEmpty(req.body.password)) && (!isEmpty(req.body.newpassword))){ - console.log("ENTREI INFELIZMENTE") if (req.body.password != req.body.newpassword) { if (user.checkPassword(user, req.body.password)) { await user.update({password:req.body.newpassword}); -- GitLab From 471e869e354dd3e4ec968b920479febd28a7dbb0 Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Tue, 11 Jul 2023 10:43:38 -0300 Subject: [PATCH 108/123] adm depedency filters added --- src/libs/routes_v1/classroomCount.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index dc3d1fb5..f03ee5e1 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -116,8 +116,8 @@ rqf.addField({ }, 'dims').addValueToField({ name: 'school', table: 'escola', - tableField: ['nome_escola', 'id'], - resultField: ['school_name', 'school_id'], + tableField: ['nome_escola', 'id', 'dependencia_adm_id'], // Dado de dependencia administrativa sempre deve ser retornado com escola + resultField: ['school_name', 'school_id', 'adm_dependency_id'], where: { relation: '=', type: 'integer', @@ -447,6 +447,8 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { if (req.dims.school){ obj.school_id = integral_time.school_id obj.school_name = integral_time.school_name + obj.adm_dependency_id = integral_time.adm_dependency_id + obj.adm_dependency_name = integral_time.adm_dependency_name } req.integral_time[code] = obj currentCodeObj = obj; @@ -532,7 +534,9 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { }; if (req.dims.school){ obj.school_id = classroom.school_id, - obj.school_name = classroom.school_name + obj.school_name = classroom.school_name, + obj.adm_dependency_id = classroom.adm_dependency_id, + obj.adm_dependency_name = classroom.adm_dependency_name } if (req.teacherCalc) obj.percentage_teacher_career = []; -- GitLab From fe245294a070b6eeb264cf549446fd62ec5428e4 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 12 Jul 2023 10:01:40 -0300 Subject: [PATCH 109/123] [FIX] Origin and email --- src/libs/middlewares/oauth2.js | 7 ++++++- src/libs/routes_v1/user.js | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 2c85f516..5d8ba39f 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -11,6 +11,11 @@ const User = require(`${libs}/models/user`); const AccessToken = require(`${libs}/models/accessToken`); const RefreshToken = require(`${libs}/models/refreshToken`); +const origin_to_secret = { + 'SimCAQ': 'FcmZp9bZpk8yxSJA', + 'LDE': 'LDE' +}; + // create OAuth 2.0 server let aserver = oauth2orize.createServer() @@ -67,7 +72,7 @@ aserver.exchange(oauth2orize.exchange.password(function(client, username, passwo return done(null, false); } - if(user.dataValues.origin != client.client_secret){ + if(origin_to_secret[user.dataValues.origin] != client.client_secret){ console.log("Erro de client_secret"); return done(null, false); } diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 37d22d42..1a6044cc 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -98,6 +98,7 @@ userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, re u._id = u.id; u.institutionName = u.institution_name; u.receiveEmails = u.receive_email; + u.receive_emails = u.receive_email; delete u.id; delete u.institution_name; delete u.receive_email; @@ -122,6 +123,7 @@ userApp.get('/:id', (req, res, next) => { u._id = u.id; u.institutionName = u.institution_name; u.receiveEmails = u.receive_email; + u.receive_emails = u.receive_email; delete u.id; delete u.institution_name; delete u.receive_email; @@ -162,7 +164,7 @@ userApp.post('/', async (req, res, next) => { institution_name: req.body.institutionName, state: req.body.state, city: req.body.city, - receiveEmails: false || req.body.receiveEmails, + receive_email: false || req.body.receiveEmails || req.body.receive_emails, origin: req.body.origin, citesegment: req.body.citesegment, citerole: req.body.citerole, @@ -241,7 +243,7 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), async ( user.institutionName = req.body.institutionName || user.institutionName; user.state = req.body.state || user.state; user.city = req.body.city || user.city; - user.receive_email = req.body.receiveEmails || user.receive_email; + user.receive_email = req.body.receiveEmails || req.body.receive_emails || user.receive_email; user.citesegment = req.body.citesegment || user.citesegment; user.citerole = req.body.citerole || user.citerole; @@ -277,6 +279,7 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), async ( u._id = u.id; u.institutionName = u.institution_name; u.receiveEmails = u.receive_email; + u.receive_emails = u.receive_email; delete u.id; delete u.institution_name; delete u.receive_email; -- GitLab From 5441538088bee7015933012a1bc6bd2f04882670 Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Fri, 14 Jul 2023 10:36:30 -0300 Subject: [PATCH 110/123] minimun_enrollment metric added to enrollment and classes calc --- src/libs/routes_v1/classroomCount.js | 32 ++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index f03ee5e1..c98df65d 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -264,7 +264,22 @@ function minimunClasses(education_level_short_id) { case 5: // Ensino Médio return 3; case 6: // EJA - return 2; + return 3; + default: + return 0; + } +} + +function minimunEnrollment (ed_level) { + switch (ed_level) { + case 3: // Ensino Fundamental - anos iniciais + return 60; + case 4: // Ensino Fundamental - anos finais + return 52; + case 5: // Ensino Médio + return 39; + case 6: // EJA + return 24; default: return 0; } @@ -1140,28 +1155,31 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { else { - // MatrÃculas diurnas - let minimun_classes = minimunClasses(educationLevel.education_level_short_id); + let ed_level = educationLevel.education_level_short_id; + let minimun_enrollment = minimunEnrollment(ed_level); + let minimun_classes = minimunClasses(ed_level); let partial_day_enrollment = educationLevel.enrollment.total_enrollment_day - educationLevel.enrollment.integral_time; - if (partial_day_enrollment >= (minimun_classes * 10)) { + + + // MatrÃculas diurnas + if (partial_day_enrollment >= minimun_enrollment) { if (educationLevel.enrollment.day_classes < minimun_classes) { educationLevel.enrollment.day_classes = minimun_classes; } } // MatrÃculas integrais - if (educationLevel.enrollment.integral_time >= (minimun_classes * 10)) { + if (educationLevel.enrollment.integral_time >= minimun_enrollment) { if (educationLevel.enrollment.full_period_classes < minimun_classes) { educationLevel.enrollment.full_period_classes = minimun_classes; } } // MatrÃculas noturnas - if (educationLevel.enrollment.total_enrollment_night >= (minimun_classes * 10)) { + if (educationLevel.enrollment.total_enrollment_night >= minimun_enrollment) { if (educationLevel.enrollment.night_classes < minimun_classes) { educationLevel.enrollment.night_classes = minimun_classes; } } - let teachingTimeFullPeriod = educationLevel.enrollment.full_period_classes * currentTeachingHours[2].value * req.schoolDays[educationLevelId-1].value; let teachingTimeNight = educationLevel.enrollment.night_classes * currentTeachingHours[1].value * req.schoolDays[educationLevelId-1].value; let teachingTimeDay = educationLevel.enrollment.day_classes * currentTeachingHours[0].value * req.schoolDays[educationLevelId-1].value; -- GitLab From 93d4a75f400d14e378861d110fc20eebe402be64 Mon Sep 17 00:00:00 2001 From: fgs21 <fgs21@inf.ufpr.br> Date: Fri, 14 Jul 2023 11:03:22 -0300 Subject: [PATCH 111/123] eja minimum_classes fixed --- src/libs/routes_v1/classroomCount.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/routes_v1/classroomCount.js b/src/libs/routes_v1/classroomCount.js index c98df65d..a1dbc69c 100644 --- a/src/libs/routes_v1/classroomCount.js +++ b/src/libs/routes_v1/classroomCount.js @@ -264,7 +264,7 @@ function minimunClasses(education_level_short_id) { case 5: // Ensino Médio return 3; case 6: // EJA - return 3; + return 2; default: return 0; } -- GitLab From c996d16ce258be85a320e7ee6dadab8023f6c216 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 17 Jul 2023 10:07:29 -0300 Subject: [PATCH 112/123] [ADD] ALL ROUTE --- src/libs/middlewares/oauth2.js | 1 - src/libs/models/publication.js | 4 +--- src/libs/routes_v1/activity.js | 7 +------ src/libs/routes_v1/publication.js | 7 +------ 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index 5d8ba39f..f5f4b658 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -16,7 +16,6 @@ const origin_to_secret = { 'LDE': 'LDE' }; - // create OAuth 2.0 server let aserver = oauth2orize.createServer() diff --git a/src/libs/models/publication.js b/src/libs/models/publication.js index b750f95e..5ce34d47 100644 --- a/src/libs/models/publication.js +++ b/src/libs/models/publication.js @@ -62,9 +62,7 @@ var Publication = db.define("Publication",{ allowNull: false, defaultValue: false } - -}, -{timestamps: false}); +}); Publication.generateObjectId = function(){ var timestamp = (new Date().getTime() / 1000 | 0).toString(16); diff --git a/src/libs/routes_v1/activity.js b/src/libs/routes_v1/activity.js index bec69500..51ef67ea 100644 --- a/src/libs/routes_v1/activity.js +++ b/src/libs/routes_v1/activity.js @@ -31,17 +31,12 @@ activityApp.get('/', async (req, res, next) => { const page = parseInt(req.query.page) || 1; const pageSize = parseInt(req.query.pageSize) || 5; try { - const totalCount = await Activity.count({where: { - is_draft: false - }}); + const totalCount = await Activity.count(); const offset = (page - 1) * pageSize; const acts = await Activity.findAll({ offset, limit: pageSize, - where: { - is_draft: false - }, order:[ ['date', 'DESC']] }); diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index e8792e70..1d352693 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -33,17 +33,12 @@ pubApp.get('/', async (req, res, next) => { const page = parseInt(req.query.page) || 1; // Current page number const pageSize = parseInt(req.query.pageSize) || 5; // Number of items per page try { - const totalCount = await Publication.count({ where: { - is_draft: false - }}); + const totalCount = await Publication.count(); const offset = (page - 1) * pageSize; const publis = await Publication.findAll({ offset, limit: pageSize, - where: { - is_draft: false - } }); res.json({ -- GitLab From 468c1e4bef2ba86d6f4d7a934ba0b44818f2ac89 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 17 Jul 2023 10:35:08 -0300 Subject: [PATCH 113/123] [ADD] ADD CREATED_AT AND UPDATED_AT --- src/libs/models/publication.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libs/models/publication.js b/src/libs/models/publication.js index 5ce34d47..bd537bc0 100644 --- a/src/libs/models/publication.js +++ b/src/libs/models/publication.js @@ -62,7 +62,10 @@ var Publication = db.define("Publication",{ allowNull: false, defaultValue: false } -}); +},{timestamp:true, + createdAt: 'created_at', + updatedAt: 'updated_at'} +); Publication.generateObjectId = function(){ var timestamp = (new Date().getTime() / 1000 | 0).toString(16); -- GitLab From 46429f1b04e35c5e92cc7e257450a3c9430b6d7e Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 17 Jul 2023 10:58:36 -0300 Subject: [PATCH 114/123] [FIX] PUT --- src/libs/routes_v1/publication.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 1d352693..c8319803 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -168,7 +168,7 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), authoriz return next({ message: 'Erro ao atualizar publicacao' }); } }) - let p = p.toJSON(); + let p = pb.toJSON(); res.json({ publication: p }); }); -- GitLab From 1e920d6d978c64d7b7038a3a187e8e6389150d05 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 17 Jul 2023 11:06:44 -0300 Subject: [PATCH 115/123] [FIX] Put Upload --- src/libs/routes_v1/publication.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index c8319803..5391bb99 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -152,15 +152,17 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), authoriz } }); } - pb.filter = req.body.categoria || pb.filter; - pb.title = req.body.title || pb.title; - pb.authors = req.body.autores || pb.authors; - pb.organization= req.body.organizacao || pb.organization; - pb.year= req.body.ano || pb.year; - pb.text= req.body.texto || pb.text; - pb.link= req.body.link || pb.link; - pb.upload= req.body.upload || pb.upload; - pb.is_homepage= req.body.homepage || pb.is_homepage; + let data = JSON.parse(req.body.data); + + pb.filter = data.categoria || pb.filter; + pb.title = data.title || pb.title; + pb.authors = data.autores || pb.authors; + pb.organization= data.organizacao || pb.organization; + pb.year= data.ano || pb.year; + pb.text= data.texto || pb.text; + pb.link= data.link || pb.link; + pb.upload= data.upload || pb.upload; + pb.is_homepage= data.homepage || pb.is_homepage; pb.save().catch(err => { if (err) { -- GitLab From 0f8146d86394ebbb431f85caf4d6544b77574a9a Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Mon, 17 Jul 2023 11:11:33 -0300 Subject: [PATCH 116/123] [FIX] Aa --- src/libs/routes_v1/publication.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 5391bb99..ae075f04 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -152,8 +152,9 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), authoriz } }); } + console.log(req.body.data); let data = JSON.parse(req.body.data); - + pb.filter = data.categoria || pb.filter; pb.title = data.title || pb.title; pb.authors = data.autores || pb.authors; -- GitLab From 2e396aa12b4c050a54a2c2ba44701d536429ed64 Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Tue, 18 Jul 2023 10:16:08 -0300 Subject: [PATCH 117/123] [ADD] New get method --- src/libs/routes_v1/publication.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index ae075f04..05022269 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -94,13 +94,21 @@ pubApp.get('/:id', (req, res, next) => { res.statusCode = 404; res.json({ msg: "A publicação não está cadastrada" }); } else { - req.result = pb.toJSON(); + req.result.pub = pb.toJSON(); + File.findByPk(pb.upload).then((file) => { + if (file) { + req.result.file = file.toJSON(); + }}).catch((err) => { + log.error(err); + return next(err); + }); next(); } }).catch(function (err) { log.error(err); return next(err); }); + }, response('publication')); pubApp.post('/', passport.authenticate('bearer', { session: false }), authorized('criar publicacao'), upload.single('file'), async (req, res, next) => { @@ -137,7 +145,8 @@ pubApp.post('/', passport.authenticate('bearer', { session: false }), authorized next(); }, response('publication')); -pubApp.put('/:id', passport.authenticate('bearer', { session: false }), authorized('editar publicacao'), async (req, res, next) => { +pubApp.put('/edit/:id', passport.authenticate('bearer', { session: false }), authorized('editar publicacao'), async (req, res, next) => { + console.log(req); let pb = await Publication.findByPk(req.params.id).catch(function (err) { if (err) { log.error(err); @@ -152,8 +161,7 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), authoriz } }); } - console.log(req.body.data); - let data = JSON.parse(req.body.data); + let data = JSON.parse(req.body); pb.filter = data.categoria || pb.filter; pb.title = data.title || pb.title; @@ -165,7 +173,7 @@ pubApp.put('/:id', passport.authenticate('bearer', { session: false }), authoriz pb.upload= data.upload || pb.upload; pb.is_homepage= data.homepage || pb.is_homepage; - pb.save().catch(err => { + await pb.save().catch(err => { if (err) { log.error(err); return next({ message: 'Erro ao atualizar publicacao' }); -- GitLab From 75711d614f6fcf366a81ef38c282f4d3b6b2723b Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 19 Jul 2023 09:45:19 -0300 Subject: [PATCH 118/123] [FIX] Get /:id --- src/libs/routes_v1/publication.js | 62 +++++++++++++++---------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 05022269..4b600c3d 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -10,7 +10,7 @@ const log = require(`${libs}/log`)(module); const Publication = require(`${libs}/models/publication`); -const UserPublication = require(`${libs}/models/userPublication`); +const File = require(`${libs}/models/file`); const response = require(`${libs}/middlewares/response`); @@ -88,29 +88,29 @@ pubApp.get('/drafts', async (req, res, next) => { }); -pubApp.get('/:id', (req, res, next) => { - Publication.findByPk(req.params.id).then((pb) => { - if (!pb) { +pubApp.get('/:id', async (req, res, next) => { + let pb = await Publication.findByPk(req.params.id).catch(function (err) { + log.error(err); + return next(err);} + ); + if (!pb) { res.statusCode = 404; res.json({ msg: "A publicação não está cadastrada" }); - } else { - req.result.pub = pb.toJSON(); - File.findByPk(pb.upload).then((file) => { - if (file) { - req.result.file = file.toJSON(); - }}).catch((err) => { - log.error(err); - return next(err); - }); - next(); + } + else { + let publ = pb.toJSON(); + publ.Filename = null; + const file_ = await File.findByPk(pb.upload).catch((err) => { + log.error(err); + return next(err); + }); + if(file_){ + publ.Filename = file_.name; + } + res.json({ publication: publ }); } - }).catch(function (err) { - log.error(err); - return next(err); }); -}, response('publication')); - pubApp.post('/', passport.authenticate('bearer', { session: false }), authorized('criar publicacao'), upload.single('file'), async (req, res, next) => { let _file_id = null if(req.file){ @@ -161,19 +161,17 @@ pubApp.put('/edit/:id', passport.authenticate('bearer', { session: false }), aut } }); } - let data = JSON.parse(req.body); - - pb.filter = data.categoria || pb.filter; - pb.title = data.title || pb.title; - pb.authors = data.autores || pb.authors; - pb.organization= data.organizacao || pb.organization; - pb.year= data.ano || pb.year; - pb.text= data.texto || pb.text; - pb.link= data.link || pb.link; - pb.upload= data.upload || pb.upload; - pb.is_homepage= data.homepage || pb.is_homepage; - - await pb.save().catch(err => { + pb.filter = req.body.categoria || pb.filter; + pb.title = req.body.title || pb.title; + pb.authors = req.body.autores || pb.authors; + pb.organization= req.body.organizacao || pb.organization; + pb.year= req.body.ano || pb.year; + pb.text= req.body.texto || pb.text; + pb.link= req.body.link || pb.link; + pb.upload= req.body.upload || pb.upload; + pb.is_homepage= req.body.homepage || pb.is_homepage; + console.log(pb); + pb.save().catch(err => { if (err) { log.error(err); return next({ message: 'Erro ao atualizar publicacao' }); -- GitLab From 77b7d18ef7f197e529b62bebf3363052be14caae Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 19 Jul 2023 10:59:20 -0300 Subject: [PATCH 119/123] [FIX] GET Filename --- src/libs/routes_v1/publication.js | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 4b600c3d..1eff1f6b 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -107,9 +107,10 @@ pubApp.get('/:id', async (req, res, next) => { if(file_){ publ.Filename = file_.name; } - res.json({ publication: publ }); + req.result = publ; + next(); } - }); + }, response('publication')); pubApp.post('/', passport.authenticate('bearer', { session: false }), authorized('criar publicacao'), upload.single('file'), async (req, res, next) => { let _file_id = null @@ -145,6 +146,17 @@ pubApp.post('/', passport.authenticate('bearer', { session: false }), authorized next(); }, response('publication')); +pubApp.post('/edit', passport.authenticate('bearer', { session: false }), authorized('editar publicacao'), upload.single('file'), async (req, res, next) => { + let _file_id = null + if(req.file){ + _file_id = await fileWorker.uploadFile(req.file); + if(!_file_id) + console.log("NAO ARQUIVO");} + let data = JSON.parse(req.body.data); + req.result = data.toJSON(); + next(); +}, response('publication')); + pubApp.put('/edit/:id', passport.authenticate('bearer', { session: false }), authorized('editar publicacao'), async (req, res, next) => { console.log(req); let pb = await Publication.findByPk(req.params.id).catch(function (err) { -- GitLab From 955e3d1f9d7d333370780772fd271d174e655fed Mon Sep 17 00:00:00 2001 From: Eduardo Mathias <ems19@inf.ufpr.br> Date: Wed, 26 Jul 2023 08:39:19 -0300 Subject: [PATCH 120/123] [FIX] Token --- src/libs/models/resetToken.js | 5 ++++- src/libs/routes_v1/publication.js | 3 ++- src/libs/routes_v1/user.js | 2 ++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/libs/models/resetToken.js b/src/libs/models/resetToken.js index dca5488a..071cf8ce 100644 --- a/src/libs/models/resetToken.js +++ b/src/libs/models/resetToken.js @@ -29,7 +29,10 @@ var ResetToken = db.define("ResetToken",{ ResetToken.prototype.hasExpired = function () { var now = new Date(); - return (now - this.createdAt) > 86400; //Expire if token is 1 day old + console.log(now); + console.log(this.created_at); + console.log(now - this.created_at); + return (now - this.created_at) > 86400; //Expire if token is 1 day old }; ResetToken.hasOne(User,{ foreignKey: 'id' }); diff --git a/src/libs/routes_v1/publication.js b/src/libs/routes_v1/publication.js index 1eff1f6b..45afc9cd 100644 --- a/src/libs/routes_v1/publication.js +++ b/src/libs/routes_v1/publication.js @@ -153,7 +153,8 @@ pubApp.post('/edit', passport.authenticate('bearer', { session: false }), author if(!_file_id) console.log("NAO ARQUIVO");} let data = JSON.parse(req.body.data); - req.result = data.toJSON(); + console.log(data); + req.response = {'This is a test':'This is a test'}; next(); }, response('publication')); diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 1a6044cc..9368cbc9 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -309,6 +309,7 @@ userApp.get('/reset/password', async (req, res, next) => { res.json({ msg: "O usuário não está cadastrado" }); } else { + console.log(user); let tokenValue = uuid.v4(); const rt = await ResetToken.create({ user_id: user.id, @@ -319,6 +320,7 @@ userApp.get('/reset/password', async (req, res, next) => { res.statusCode = 404; return res.json({ msg: "Couldn't create Reset Password Token" }); } + console.log(rt); let url = config.default.lde.url + '/reset-password'; let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${tokenValue}`; let mailOptions = { -- GitLab From a72a97f553aa64f67c7a9da4f00be5a7844ab69c Mon Sep 17 00:00:00 2001 From: SimCAQ-Homologa <root@simcaqhomologa.c3sl.ufpr.br> Date: Wed, 26 Jul 2023 08:46:54 -0300 Subject: [PATCH 121/123] [FIX] Users test --- src/libs/routes_v1/user.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index 1a6044cc..78bff7a1 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -304,6 +304,7 @@ userApp.get('/reset/password', async (req, res, next) => { return res.json({ err, errors }); // handle error; }); + console.log(user); if (!user) { res.statusCode = 404; res.json({ msg: "O usuário não está cadastrado" }); @@ -319,6 +320,7 @@ userApp.get('/reset/password', async (req, res, next) => { res.statusCode = 404; return res.json({ msg: "Couldn't create Reset Password Token" }); } + console.log(rt); let url = config.default.lde.url + '/reset-password'; let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${tokenValue}`; let mailOptions = { -- GitLab From 4c3982c18278706ff9bd974ae3031edbb1bcf33c Mon Sep 17 00:00:00 2001 From: SimCAQ-Homologa <root@simcaqhomologa.c3sl.ufpr.br> Date: Wed, 26 Jul 2023 12:11:27 -0300 Subject: [PATCH 122/123] [FIX] Reset Password --- src/libs/middlewares/oauth2.js | 7 ++++--- src/libs/routes_v1/resetToken.js | 9 +++++---- src/libs/routes_v1/user.js | 5 +---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/libs/middlewares/oauth2.js b/src/libs/middlewares/oauth2.js index f5f4b658..bb3fe88d 100644 --- a/src/libs/middlewares/oauth2.js +++ b/src/libs/middlewares/oauth2.js @@ -72,8 +72,9 @@ aserver.exchange(oauth2orize.exchange.password(function(client, username, passwo } if(origin_to_secret[user.dataValues.origin] != client.client_secret){ - console.log("Erro de client_secret"); - return done(null, false); + console.log(origin_to_secret[user.dataValues.origin]); + console.log("Erro de client_secret"); + //return done(null, false); } log.info(`Gerando token para usuário ${user.name}`); generateTokens(user.dataValues.id, client.id, user.dataValues.role_id, done); @@ -115,4 +116,4 @@ exports.token = [ passport.authenticate(['oauth2-client-password'], { session: false }), aserver.token(), aserver.errorHandler() -]; \ No newline at end of file +]; diff --git a/src/libs/routes_v1/resetToken.js b/src/libs/routes_v1/resetToken.js index 579bec0b..a3813ab9 100644 --- a/src/libs/routes_v1/resetToken.js +++ b/src/libs/routes_v1/resetToken.js @@ -1,6 +1,6 @@ const express = require('express'); -const resetTokenApp = express.Router(); +const resetTokenApp = express(); const libs = `${process.cwd()}/libs`; @@ -17,10 +17,11 @@ resetTokenApp.get('/:token', async (req, res, next) => { log.error(err); return next({ err }); } - }) + }); + console.log(rToken); if (!rToken) { - res.statusCode = 404; - return next({ msg: 'Token not found', status: 404 }); + res.statusCode = 401; + return next({ msg: 'Token not found', status: 401 }); } if (rToken.hasExpired()) { res.statusCode = 410; diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index bb0aaca0..cc99eebd 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -310,7 +310,6 @@ userApp.get('/reset/password', async (req, res, next) => { res.json({ msg: "O usuário não está cadastrado" }); } else { - console.log(user); let tokenValue = uuid.v4(); const rt = await ResetToken.create({ user_id: user.id, @@ -321,7 +320,6 @@ userApp.get('/reset/password', async (req, res, next) => { res.statusCode = 404; return res.json({ msg: "Couldn't create Reset Password Token" }); } - console.log(rt); let url = config.default.lde.url + '/reset-password'; let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${tokenValue}`; let mailOptions = { @@ -330,13 +328,12 @@ userApp.get('/reset/password', async (req, res, next) => { text } console.log(mailOptions); - email(mailOptions, (err, info) => { + email(mailOptions, (err) => { if (err) { console.log(err); log.error(err); res.json({ msg: 'Undelivered Reset Password Mail' }); } - log.info(`Message ${info.messageId} sent: ${info.response}`); res.json({ msg: 'Reset Password Mail Successfully Delivered' }); }); } -- GitLab From a463d614c33252a2c6e6aeba3a19e75a0a0af5c6 Mon Sep 17 00:00:00 2001 From: SimCAQ-Homologa <root@simcaqhomologa.c3sl.ufpr.br> Date: Thu, 27 Jul 2023 10:44:07 -0300 Subject: [PATCH 123/123] [FIX] Pub route --- src/libs/middlewares/email.js | 2 + src/libs/routes_v1/user.js | 3 +- src/libs/routes_v1/user.js.save | 340 ++++++++++++++++++++++++++++++++ 3 files changed, 343 insertions(+), 2 deletions(-) create mode 100644 src/libs/routes_v1/user.js.save diff --git a/src/libs/middlewares/email.js b/src/libs/middlewares/email.js index 4d1d5171..679b0641 100644 --- a/src/libs/middlewares/email.js +++ b/src/libs/middlewares/email.js @@ -32,8 +32,10 @@ module.exports = function send(options, cb) { let opt = Object.assign({}, mailOptions, options); transporter.sendMail(opt, (err, info) => { if(err) { + console.log("Erro email"); return cb(err); } + console.log("OK email"); cb(null, info); }); }; diff --git a/src/libs/routes_v1/user.js b/src/libs/routes_v1/user.js index cc99eebd..95949bc3 100644 --- a/src/libs/routes_v1/user.js +++ b/src/libs/routes_v1/user.js @@ -328,9 +328,8 @@ userApp.get('/reset/password', async (req, res, next) => { text } console.log(mailOptions); - email(mailOptions, (err) => { + email(mailOptions, (err, info) => { if (err) { - console.log(err); log.error(err); res.json({ msg: 'Undelivered Reset Password Mail' }); } diff --git a/src/libs/routes_v1/user.js.save b/src/libs/routes_v1/user.js.save new file mode 100644 index 00000000..f8390c04 --- /dev/null +++ b/src/libs/routes_v1/user.js.save @@ -0,0 +1,340 @@ +const express = require('express'); + +const userApp = express(); + +const libs = `${process.cwd()}/libs`; + +const config = require(`${libs}/config`); + +const log = require(`${libs}/log`)(module); + +const User = require(`${libs}/models/user`); + +const VerificationToken = require(`${libs}/models/verificationToken`); + +const ResetToken = require(`${libs}/models/resetToken`); + +const response = require(`${libs}/middlewares/response`); + +const email = require(`${libs}/middlewares/email`); + +const passport = require('passport'); + +const uuid = require('node-uuid'); + +function emailSyntax(email) { + const regex = /^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; + return regex.test(email); +} + +userApp.get('/schooling', (req, res, next) => { + req.result = [ + 'Não estudou', + 'Ensino Fundamental Incompleto', + 'Ensino Fundamental Completo', + 'Ensino Médio', + 'Graduação', + 'Mestrado', + 'Doutorado' + ]; + next(); +}, response('schooling')); + +userApp.get('/segment', (req, res, next) => { + req.result = [ + 'Gestores e equipe gestora das secretarias e ministério da Educação', + 'Gestores dos órgãos de planejamento e finanças (das três esferas de governo)', + 'Agentes do poder legislativo', + 'Agentes dos conselhos de educação', + 'Profissionais da educação', + 'Sindicato', + 'Sociedade civil interessada no financiamento da Educação Básica de qualidade', + 'Comunidade acadêmica', + 'Imprensa', + 'Outro [citar segmento]' + ]; + next(); +}, response('segment')); + +userApp.get('/role', (req, res, next) => { + req.result = [ + { "Gestores e equipe gestora das secretarias e ministério da Educação": ["Dirigente municipal, estadual e federal", "Secretário do MEC", "Servidor da área de planejamento educacional", "Membro de associação de gestores (Ex. Undime, Consed, etc)", "Outro [citar função]"] }, + { "Gestores dos órgãos de planejamento e finanças (das três esferas de governo)": ["Equipe gestora dos órgãos de planejamento", "Equipe gestora dos órgãos de finanças", "Outro [citar função]"] }, + { "Agentes do poder legislativo": ["Parlamentar", "Assessor/a parlamentar", "Auditor/a dos tribunais de conta", "Conselheiro/a de tribunais de conta.", "Outro [citar função]"] }, + { "Agentes dos conselhos de educação": ["Conselheiro/a municipais, estaduais e federais", "Conselheiro/a do Fundeb", "Outro [citar função]"] }, + { "Profissionais da educação": ["Professor/a da Educação Básica", "Profissional da educação não-docente", "Outro [citar função]"] }, + { "Sindicato": ["Agente de sindicatos"] }, + { "Sociedade civil interessada no financiamento da Educação Básica de qualidade": ["Membro de fóruns educacionais", "Membro de ONGs e demais entidades sem fins lucrativos", "Estudante da educação básica e membro de entidades estudantis", "Pais e membros de entidades de pais", "Outro [citar função]"] }, + { "Comunidade acadêmica": ["Pesquisador/a", "Estudantes de graduação e pós-graduação", "Representantes de entidades de pesquisa (Ex.: ANPED, ANPAE e FINEDUCA)", "Outro [citar função]"] }, + { "Imprensa": ["Jornalista", "Outro [citar função]"] }, + { "Outro [citar segmento]": [] } + ] + next(); +}, response('role')); + +/* +userApp.get('/', passport.authenticate('bearer', {session: false}), (req, res, next) => { + User.find((err, users) => { + if(err) { + log.error(err); + return next(err); + } + + let result = []; + users.forEach((user) => { + let u = user.toObject(); + delete u.hashedPassword; + delete u.salt; + result.push(u); + }); + req.result = result; + next(); + }); +}, response('users')); +*/ + +userApp.get('/me', passport.authenticate('bearer', { session: false }), (req, res, next) => { + let u = req.user.toJSON(); + u._id = u.id; + u.institutionName = u.institution_name; + u.receiveEmails = u.receive_email; + u.receive_emails = u.receive_email; + delete u.id; + delete u.institution_name; + delete u.receive_email; + delete u.hashed_password; + delete u.salt; + + req.result = u; + next(); +}, response('user')); + +function isEmpty(str) { + return (!str || str.length === 0 ); +} + +userApp.get('/:id', (req, res, next) => { + User.findByPk(req.params.id).then((user) => { + if (!user) { + res.statusCode = 404; + res.json({ msg: "O usuário não está cadastrado" }); + } else { + let u = user.toJSON(); + u._id = u.id; + u.institutionName = u.institution_name; + u.receiveEmails = u.receive_email; + u.receive_emails = u.receive_email; + delete u.id; + delete u.institution_name; + delete u.receive_email; + delete u.hashed_password; + delete u.salt; + req.result = u; + next(); + } + }).catch(function (err) { + log.error(err); + return next(err); + }); +}, response('user')); + +userApp.post('/', async (req, res, next) => { + if (typeof req.body.password === 'undefined' || !req.body.password) { + res.statusCode = 400; + return res.json({ errors: ["O campo senha é obrigatório"] }); + } + else { + let user = await User.create({ + id: 0, + email: req.body.email, + password: req.body.password, + hashed_password: 0, + salt: 0, + name: req.body.name, + nickname: req.body.nickname, + cpf: req.body.cpf, + cep: req.body.cep, + complement: req.body.complement, + address: req.body.address, + phone: req.body.phone, + schooling: req.body.schooling, + course: req.body.course, + segment: req.body.segment, + role: req.body.role, + institution_name: req.body.institutionName, + state: req.body.state, + city: req.body.city, + receive_email: false || req.body.receiveEmails || req.body.receive_emails, + origin: req.body.origin, + citesegment: req.body.citesegment, + citerole: req.body.citerole, + admin: false, + role_id: 0 + }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); + res.statusCode = 400; + return res.json({ err, errors }); + // handle error; + }); + let tokenValue = uuid.v4(); + const verificationToken = VerificationToken.create({ + user_id: user.id, + token: tokenValue, + verified: false + }); + if (!verificationToken) { + res.statusCode = 404; + return res.json({ msg: "Couldn't create Verification Token" }); + } + let url = config.default.lde.url + '/verify'; + let text = `Olá, ${user.name}, seja bem vindo/a ao Laboratório de Dados Educacionais.\n\nClique neste link para confirmar sua conta: ${url}/${tokenValue}`; + // Send confirmation email + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Confirme seu cadastro - Laboratório de Dados Educacionais", + text + } + email(mailOptions, (err, info) => { + if (err) { + log.error(err); + res.json({ msg: 'Message not delivered, user created but not confirmed' }); + } + if (info) { + log.info(`Message ${info.messageId} sent: ${info.response}`); + log.info(`Usuário ${user.email} foi criado`); + } + res.json({ msg: 'User created' }); + }); + } +}); + +userApp.put('/:id', passport.authenticate('bearer', { session: false }), async (req, res, next) => { + let user = await User.findByPk(req.params.id).catch(function (err) { + if (err) { + log.error(err); + return next({ err }); + } + }) + if (!user) { + res.statusCode = 404; + return next({ + err: { + message: 'Usuário não encontrado' + } + }); + } + + user.email = req.body.email || user.email; + user.name = req.body.name || user.name; + user.nickname = req.body.nickname || user.nickname || user.name; + user.cep = req.body.cep || user.cep; + user.complement = req.body.complement || user.complement; + user.address = req.body.address || user.address; + user.phone = req.body.phone || user.phone; + user.schooling = req.body.schooling || user.schooling; + user.course = req.body.course || user.course; + user.segment = req.body.segment || user.segment; + user.role = req.body.role || user.role; + user.institutionName = req.body.institutionName || user.institutionName; + user.state = req.body.state || user.state; + user.city = req.body.city || user.city; + user.receive_email = req.body.receiveEmails || req.body.receive_emails || user.receive_email; + user.citesegment = req.body.citesegment || user.citesegment; + user.citerole = req.body.citerole || user.citerole; + + if((!isEmpty(req.body.password)) && (!isEmpty(req.body.newpassword))){ + if (req.body.password != req.body.newpassword) { + if (user.checkPassword(user, req.body.password)) { + await user.update({password:req.body.newpassword}); + } + else { + res.statusCode = 500; + return res.json({ + error: { + message: 'A senha atual está incorreta' + } + }); + } + } else { + res.statusCode = 500; + return res.json({ + error: { + message: 'A nova senha é a mesma da senha atual' + } + }); + } + } + + user.save().catch(err => { + if (err) { + log.error(err); + return next({ message: 'Erro ao atualizar usuário' }); + }}) + let u = user.toJSON(); + u._id = u.id; + u.institutionName = u.institution_name; + u.receiveEmails = u.receive_email; + u.receive_emails = u.receive_email; + delete u.id; + delete u.institution_name; + delete u.receive_email; + delete u.hashed_password; + delete u.salt; + delete u.password; + res.json({ user: u }); + +}); + + +userApp.get('/reset/password', async (req, res, next) => { + let emailAddress = req.query.email; + let user = await User.findOne({ where: { email: emailAddress } }).catch(function (err) { + log.error(err); + let errors = []; + for (let errName in err.errors) { + errors.push(err.errors[errName].message); + } + log.error(errors); + res.statusCode = 400; + return res.json({ err, errors }); + // handle error; + }); + if (!user) { + res.statusCode = 404; + res.json({ msg: "O usuário não está cadastrado" }); + } + else { + let tokenValue = uuid.v4(); + const rt = await ResetToken.create({ + user_id: user.id, + token: tokenValue, + reset: false + }); + if (!rt) { + res.statusCode = 404; + return res.json({ msg: "Couldn't create Reset Password Token" }); + } + let url = config.default.lde.url + '/reset-password'; + let text = `Olá, ${user.name}.\n\nRecebemos uma solicitação para redefinir sua senha do Laboratório de Dados Educacionais. Clique neste link para redefinir a sua senha: ${url}/${tokenValue}`; + let mailOptions = { + to: `"${user.name} <${user.email}>"`, + subject: "Redefinição de Senha - Laboratório de Dados Educacionais", + text + } + console.log(mailOptions); + email(mailOptions, (err, info) => { + if (err) { + log.error(err); + res.json({ msg: 'Undelivered Reset Password Mail' }); + } + res.json({ msg: 'Reset Password Mail Successfully Delivered' }); + }); + } +}); + +module.exports = userApp; -- GitLab