diff --git a/.gitignore b/.gitignore
index 99a279fb87ba4d97734e25ed4d26cfef532ea04e..dcf0f82ad5528491b97e4e768a248dceeb491ffc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,5 @@ docs/
 .vscode/
 
 package-lock.json
+
+Dockerfile
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index 356b1c4bb62a490f2043bcaf264a4cd660bf03e1..0000000000000000000000000000000000000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,43 +0,0 @@
-image: node:9.2.1
-
-stages:
-  - test
-
-services:
-  - mongo:latest
-
-variables:
-  MONGO_URI: 'mongodb://mongo/app_name'
-  NODE_ENV: 'test'
-
-#run_tests:
-#  stage: test
-#  before_script:
-#    - node -v
-#    - npm install --global gulp gulp-cli babel babel-cli babel-core babel-register mocha gulp-mocha #gulp-eslint
-#    - npm install
-#  script:
-#    - ping -W1 -c1 mongo
-#    - sed -i -e 's/false/true/g' config.json
-#    - gulp build
-#    - gulp test
-#  tags:
-#    - node
-
-regression_tests:
-  stage: test
-  before_script:
-    - npm install --global gulp gulp-cli babel babel-cli babel-core babel-register mocha gulp-mocha gulp-eslint
-    - npm install
-    - gulp build && gulp &
-    - curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
-    - python get-pip.py
-    - sleep 60
-  script:
-    
-    - git clone https://gitlab.c3sl.ufpr.br/simcaq/lde-api-regression-test.git
-    - cd lde-api-regression-test
-    - pip install -r requirements.txt
-    - python manage.py compare --verbose
-  tags:
-    - node
diff --git a/config.json.example b/config.json.example
index e3d309200d160d47b17dbe57f23dee11cdbccd23..1fa157c1e562f3843ef2f44bf60e1793fbf9c1e7 100644
--- a/config.json.example
+++ b/config.json.example
@@ -7,7 +7,7 @@
         "monetdb": {
             "host": "simcaqdb3.c3sl.ufpr.br",
             "port": 50000,
-            "dbname": "simcaq_dev4",
+            "dbname": "simcaq",
             "user": "monetdb",
             "password":"monetdb",
             "nrConnections": "4"
@@ -34,11 +34,17 @@
             }
         },
         "email": {
-            "port": 25,
-            "host": "mx.c3sl.ufpr.br",
-            "secure": false,
-            "ignoreTLS": true,
-            "from": "\"Laboratório de Dados Educacionais\" <lde@c3sl.ufpr.br>"
+            "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
@@ -46,13 +52,13 @@
     },
     "test":
     {
-        "port": 4000,
+        "port": 3000,
         "ip": "127.0.0.1",
         "debug" : true,
         "monetdb": {
             "host": "simcaqdb3.c3sl.ufpr.br",
             "port": 50000,
-            "dbname": "simcaq_dev4",
+            "dbname": "simcaq",
             "user": "monetdb",
             "password":"monetdb",
             "nrConnections": "4"
@@ -80,11 +86,17 @@
             }
         },
         "email": {
-            "port": 25,
-            "host": "mx.c3sl.ufpr.br",
-            "secure": false,
-            "ignoreTLS": true,
-            "from": "\"Laboratório de Dados Educacionais\" <lde@c3sl.ufpr.br>"
+            "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
@@ -92,13 +104,13 @@
     },
     "production":
     {
-        "port": 6000,
+        "port": 3000,
         "ip": "127.0.0.1",
         "debug" : false,
         "monetdb": {
             "host": "simcaqdb3.c3sl.ufpr.br",
             "port": 50000,
-            "dbname": "simcaq_dev4",
+            "dbname": "simcaq",
             "user": "monetdb",
             "password":"monetdb",
             "nrConnections": "4"
@@ -126,11 +138,17 @@
             }
         },
         "email": {
-            "port": 25,
-            "host": "mx.c3sl.ufpr.br",
-            "secure": false,
-            "ignoreTLS": true,
-            "from": "\"Laboratório de Dados Educacionais\" <lde@c3sl.ufpr.br>"
+            "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/gulpfile.babel.js b/gulpfile.babel.js
index 11e9416f87c8528c84d0bbb64f5312c8455215b4..32500420095cccb6a792b14ebe739bbfa16d4abc 100644
--- a/gulpfile.babel.js
+++ b/gulpfile.babel.js
@@ -111,7 +111,7 @@ gulp.task('run', () => {
         tasks: ['watch'],
         ignore: ["test/test.js", "gulpfile.babel.js"],
         ext: 'js html json',
-        env: { 'NODE_ENV': 'development' }
+        env: { 'NODE_ENV': process.env.NODE_ENV }
     });
 });
 
diff --git a/src/libs/convert/academicLevel.js b/src/libs/convert/academicLevel.js
index 3f76bc115a7e7897ef7aea4967fa872d07409bf2..c2c81a93e6384b9b61fe1139f25a8c561af4d59e 100644
--- a/src/libs/convert/academicLevel.js
+++ b/src/libs/convert/academicLevel.js
@@ -26,6 +26,8 @@ module.exports = function academicLevel(id) {
         return 'Licenciatura';
         case 3:
         return 'Tecnológico';
+        case 4:
+        return 'Bacharelado e Licenciatura';
         default:
         return 'Não classificada';
     }
diff --git a/src/libs/convert/booleanVariable.js b/src/libs/convert/booleanVariable.js
index 64966010de42b0da4a9f8381f0811e081c734596..fac47d76e6f63150e12fa79c9d4a42b1792500e0 100644
--- a/src/libs/convert/booleanVariable.js
+++ b/src/libs/convert/booleanVariable.js
@@ -19,10 +19,16 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 module.exports = function booleanVariable(id) {
-  if (id == null)
-    return 'Não Declarado';
-  else if (id == false)
-    return 'Não';
-  else if (id == true)
-    return 'Sim';
+  switch(id){
+    case 1:
+      return 'Sim';
+    case true:
+      return 'Sim';
+    case 0:
+      return 'Não';
+    case false:
+      return 'Não';
+    default:
+      return 'Não Declarado';
+  }
 };
diff --git a/src/libs/convert/cineDetailed.js b/src/libs/convert/cineDetailed.js
index e12117040aef3946cb7f4ca72c934daec7cbf038..d95c745135848f8ed2cd551073b08505f43b93da 100644
--- a/src/libs/convert/cineDetailed.js
+++ b/src/libs/convert/cineDetailed.js
@@ -19,8 +19,8 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 */
 module.exports = function cineDetailed(id) {
 	switch (id) {
-		case 11: 
-        return 'Programas básicos';                                              
+        case 11:
+        return 'Programas Básicos';
         case 111: 
         return 'Ciência da educação';                                            
         case 112: 
diff --git a/src/libs/convert/cineGeral.js b/src/libs/convert/cineGeral.js
index 4f38e88a51ba2ea805c1359438922eb1b16505d9..ec274ce9a114af6f142e38404d180fd508dfa7d5 100644
--- a/src/libs/convert/cineGeral.js
+++ b/src/libs/convert/cineGeral.js
@@ -20,8 +20,6 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 
 module.exports = function cineGeral(id) {
     switch (id) {
-        case 0:
-        return 'Programas básicos';
         case 1:
         return 'Educação';
         case 2:
diff --git a/src/libs/convert/cineSpecific.js b/src/libs/convert/cineSpecific.js
index 8c900c350d49a4865b7df09e60e8933c4813e7c5..50ca1437f31cfa96fe6bfa60c454af5c78c77a2a 100644
--- a/src/libs/convert/cineSpecific.js
+++ b/src/libs/convert/cineSpecific.js
@@ -21,8 +21,6 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 
 module.exports = function cineSpecific(id) {
     switch (id) {
-        case 1:
-        return 'Programas básicos';                                            
         case 11:
         return 'Educação';                                                      
         case 18:
diff --git a/src/libs/convert/contractType.js b/src/libs/convert/contractType.js
index 98ffcb84e02f2894a888d78a2d9422b670f841b0..5a938a0bae73e15700d86ddbac7e9a00cbdb17e5 100644
--- a/src/libs/convert/contractType.js
+++ b/src/libs/convert/contractType.js
@@ -21,7 +21,7 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 module.exports = function contractType(id) {
     switch (id) {
         case 1:
-        return 'Concursado/Efetivo/Estável';
+        return 'Concursado/ Efetivo/ Estável';
         case 2:
         return 'Contrato temporário';
         case 3:
diff --git a/src/libs/convert/diffLocation.js b/src/libs/convert/diffLocation.js
new file mode 100644
index 0000000000000000000000000000000000000000..f239f0041cf4101cf646d980a859b87058261f1f
--- /dev/null
+++ b/src/libs/convert/diffLocation.js
@@ -0,0 +1,32 @@
+/*
+Copyright (C) 2022 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 location(id) {
+    switch (id) {
+        case 0:
+            return 'Não está em localidade diferenciada';
+        case 1:
+            return 'Área de assentamento';
+        case 2:
+            return 'Terra indígena';
+        case 3: 
+            return 'Área remanescente de quilombos';
+    }
+};
diff --git a/src/libs/convert/discipline.js b/src/libs/convert/discipline.js
index 6cf571548e51fe1d98f48e3f9c5684ad123b2976..3bf4aaf7a71b364ae7ac3346f98c778e219f932b 100644
--- a/src/libs/convert/discipline.js
+++ b/src/libs/convert/discipline.js
@@ -21,42 +21,42 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 module.exports = function discipline(id) {
     switch (id) {
         case 1:
-            return 'Química'
+            return 'Química';
         case 2:
-            return 'Física'
+            return 'Física';
         case 3:
-            return 'Matemática'
+            return 'Matemática';
         case 4:
-            return 'Biologia'
+            return 'Biologia';
         case 5:
-            return 'Ciências'
+            return 'Ciências';
         case 6:
-            return 'Língua Portuguesa'
+            return 'Língua Portuguesa';
         case 7:
-            return 'Língua Estrangeira – Inglês'
+            return 'Língua Estrangeira – Inglês';
         case 8:
-            return 'Língua Estrangeira - Espanhol'
+            return 'Língua Estrangeira - Espanhol';
         case 9:
-            return 'Língua Estrangeira - Francês'
+            return 'Língua Estrangeira - Francês';
         case 10:
-            return 'Língua Estrangeira - Outras'
+            return 'Língua Estrangeira - Outras';
         case 11:
-            return 'Língua Indígena'
+            return 'Língua Indígena';
         case 12:
-            return 'Arte'
+            return 'Arte';
         case 13:
-            return 'Educação Física'
+            return 'Educação Física';
         case 14:
-            return 'História'
+            return 'História';
         case 15:
-            return 'Geografia'
+            return 'Geografia';
         case 16:
-            return 'Filosofia'
+            return 'Filosofia';
         case 17:
-            return 'Ensino religioso'
+            return 'Ensino religioso';
         case 18:
-            return 'Estudos Sociais'
+            return 'Estudos Sociais';
         case 19:
-            return 'Sociologia'
+            return 'Sociologia';
     }
 };
diff --git a/src/libs/convert/educationLevelMod.js b/src/libs/convert/educationLevelMod.js
index 5add8f1e37bf539bdda0cc81878a4f60e8265eea..7c6f2cdf042e08e95dc91066956e20b67449c1ff 100644
--- a/src/libs/convert/educationLevelMod.js
+++ b/src/libs/convert/educationLevelMod.js
@@ -43,7 +43,7 @@ module.exports = function educationLevelMod(id) {
         case 11:
         return 'EJA - EF e EM Integrado - tecnico';
         case 12:
-        return 'Educacao Profissional - concomitante e subsequente'
+        return 'Educacao Profissional - concomitante e subsequente';
         default:
         return 'Não classificada';
     }
diff --git a/src/libs/convert/educationLevelSchoolYear.js b/src/libs/convert/educationLevelSchoolYear.js
index 07cc64f7f577d7984c1c1bfdee5cd55325d3d9be..1c17534e5589b902d91f82c91ef58487ad96667d 100644
--- a/src/libs/convert/educationLevelSchoolYear.js
+++ b/src/libs/convert/educationLevelSchoolYear.js
@@ -20,37 +20,69 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 
 module.exports = function educationLevelSchoolYear(id) {
     switch(id) {
-        case 1: return 'Creche';
-        case 11: return 'Creche - Menor de 1 ano';
-        case 12: return 'Creche - 1 ano';
-        case 13: return 'Creche - 2 anos';
-        case 14: return 'Creche - 3 anos';
-        case 2: return 'Pré-Escola';
-        case 21: return 'Pré-Escola - 4 anos';
-        case 22: return 'Pré-Escola - 5 anos';
-        case 3: return 'Ensino Fundamental - anos iniciais';
-        case 31: return 'Ens. Fundamental - 1º Ano';
-        case 32: return 'Ens. Fundamental - 1ª série/2º ano';
-        case 33: return 'Ens. Fundamental - 2ª série/3º ano';
-        case 34: return 'Ens. Fundamental - 3ª série/4º ano';
-        case 35: return 'Ens. Fundamental - 4ª série/5º Ano';
-        case 4: return 'Ensino Fundamental - anos finais';
-        case 41: return 'Ens. Fundamental - 5ª série/6º ano';
-        case 42: return 'Ens. Fundamental - 6ª série/7º ano';
-        case 43: return 'Ens. Fundamental - 7ª série/8º ano';
-        case 44: return 'Ens. Fundamental - 8ª serie/9º ano';
-        case 5: return 'Ensino Médio';
-        case 51: return 'Ens. Médio - 1ª série';
-        case 52: return 'Ens. Médio - 2ª série';
-        case 53: return 'Ens. Médio - 3ª série';
-        case 54: return 'Ens. Médio - 4ª série';
-        case 6: return 'EJA';
-        case 61: return 'EJA - anos iniciais do Ens. Fundamental';
-        case 62: return 'EJA - anos finais do Ens. Fundamental';
-        case 63: return 'EJA - Ensino Médio';
-        case 64: return 'EJA semi-presencial';
-        case 7: return 'EE exclusiva';
-        case 71: return 'Educação Profissional';
-        default: return 'Não classificada';
+        case 1: 
+        return 'Creche';
+        case 11: 
+        return 'Creche - Menor de 1 ano';
+        case 12: 
+        return 'Creche - 1 ano';
+        case 13: 
+        return 'Creche - 2 anos';
+        case 14: 
+        return 'Creche - 3 anos';
+        case 2: 
+        return 'Pré-Escola';
+        case 21: 
+        return 'Pré-Escola - 4 anos';
+        case 22: 
+        return 'Pré-Escola - 5 anos';
+        case 3: 
+        return 'Ensino Fundamental - anos iniciais';
+        case 31: 
+        return 'Ens. Fundamental - 1º Ano';
+        case 32: 
+        return 'Ens. Fundamental - 1ª série/2º ano';
+        case 33: 
+        return 'Ens. Fundamental - 2ª série/3º ano';
+        case 34: 
+        return 'Ens. Fundamental - 3ª série/4º ano';
+        case 35: 
+        return 'Ens. Fundamental - 4ª série/5º Ano';
+        case 4: 
+        return 'Ensino Fundamental - anos finais';
+        case 41: 
+        return 'Ens. Fundamental - 5ª série/6º ano';
+        case 42: 
+        return 'Ens. Fundamental - 6ª série/7º ano';
+        case 43: 
+        return 'Ens. Fundamental - 7ª série/8º ano';
+        case 44: 
+        return 'Ens. Fundamental - 8ª serie/9º ano';
+        case 5: 
+        return 'Ensino Médio';
+        case 51: 
+        return 'Ens. Médio - 1ª série';
+        case 52: 
+        return 'Ens. Médio - 2ª série';
+        case 53: 
+        return 'Ens. Médio - 3ª série';
+        case 54: 
+        return 'Ens. Médio - 4ª série';
+        case 6: 
+        return 'EJA';
+        case 61: 
+        return 'EJA - anos iniciais do Ens. Fundamental';
+        case 62: 
+        return 'EJA - anos finais do Ens. Fundamental';
+        case 63: 
+        return 'EJA - Ensino Médio';
+        case 64: 
+        return 'EJA semi-presencial';
+        case 7: 
+        return 'EE exclusiva';
+        case 71: 
+        return 'Educação Profissional';
+        default: 
+        return 'Não classificada';
     }
 }
\ No newline at end of file
diff --git a/src/libs/convert/enrolledVacanciesFreshmen.js b/src/libs/convert/enrolledVacanciesFreshmen.js
new file mode 100644
index 0000000000000000000000000000000000000000..890445cd0775c3728cea9192a183cb757bf256f5
--- /dev/null
+++ b/src/libs/convert/enrolledVacanciesFreshmen.js
@@ -0,0 +1,32 @@
+/*
+Copyright (C) 2022 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 enrolledVacanciesFreshmen(id) {
+  switch (id) {
+      case 1:
+      return 'Ingresso';
+      case 2:
+      return 'Vagas totais';
+      case 3:
+      return 'Inscritos';
+      default:
+      return 'Não definido';
+  }
+};
diff --git a/src/libs/convert/enrollmentSituation.js b/src/libs/convert/enrollmentSituation.js
new file mode 100644
index 0000000000000000000000000000000000000000..9b709ea2b8842e2f259ae518f753405746600910
--- /dev/null
+++ b/src/libs/convert/enrollmentSituation.js
@@ -0,0 +1,33 @@
+/*
+Copyright (C) 2022 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 enrollmentSituation(id) {
+    switch (id) {
+        case 1:
+        return 'Ingressante';
+        case 2:
+        return 'Cursando';
+        case 3:
+        return 'Concluintes';
+        default:
+        return 'Não definido';
+    }
+};
+  
diff --git a/src/libs/convert/enterSituation.js b/src/libs/convert/enterSituation.js
new file mode 100644
index 0000000000000000000000000000000000000000..1fe551d944e176d99fef590890acc836b05b4e14
--- /dev/null
+++ b/src/libs/convert/enterSituation.js
@@ -0,0 +1,35 @@
+/*
+Copyright (C) 2022 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 enterSituation(id) {
+    switch (id) {
+        case 1:
+        return 'Cursando';
+        case 2:
+        return 'Concluinte';
+        case 3:
+        return 'Evadido';
+        case 4:
+        return 'Trancado';
+        default:
+        return 'Não definido';
+    }
+};
+  
diff --git a/src/libs/convert/ethnicGroupIES.js b/src/libs/convert/ethnicGroupIES.js
index a57150fcc30d5e46df45ba9c1cd7d97761fc612f..0e6fbd207f4fc8614b15b0c497c3f38821c432ec 100644
--- a/src/libs/convert/ethnicGroupIES.js
+++ b/src/libs/convert/ethnicGroupIES.js
@@ -32,6 +32,7 @@ module.exports = function ethnicGroupIES(id) {
         return 'Amarela';
         case 5:
         return 'Indígena';
+        case 9:
         default:
         return 'Não dispõe da informação (Não resposta)';
     }
diff --git a/src/libs/convert/ethnicGroupTeacherIES.js b/src/libs/convert/ethnicGroupTeacherIES.js
index 7db2936ccc04200a58a7680f32c4a0d2c3122aaa..40ce39d6dba8cf1038a1ac08ff09cde84a325fa9 100644
--- a/src/libs/convert/ethnicGroupTeacherIES.js
+++ b/src/libs/convert/ethnicGroupTeacherIES.js
@@ -32,6 +32,7 @@ module.exports = function ethnicGroupTeacherIES(id) {
         return 'Amarela';
         case 5:
         return 'Indígena';
+        case 9:
         default:
         return 'Não dispõe da informação (Não resposta)';
     }
diff --git a/src/libs/convert/finishUniversity.js b/src/libs/convert/finishUniversity.js
index 389b8f205e7a2b4348c9c9ed734cea89a39f204f..55c6265abc04e62d714a0e69febaa5220515c44e 100644
--- a/src/libs/convert/finishUniversity.js
+++ b/src/libs/convert/finishUniversity.js
@@ -21,9 +21,9 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 module.exports = function finishUniversity(id) {
 	switch (id) {
 		case 0:
-			return 'Não';
+			return 'Não concluinte';
 		case 1:
-			return 'Sim';
+			return 'Concluinte';
 		default:
 			return 'Não declarado';
 	}
diff --git a/src/libs/convert/govermentAgreement.js b/src/libs/convert/governmentAgreement.js
similarity index 94%
rename from src/libs/convert/govermentAgreement.js
rename to src/libs/convert/governmentAgreement.js
index 106a3a72c3292cbdd83a01fa92517600ff765784..475760153b81b04d984437b7fe137b2dc29cabd8 100644
--- a/src/libs/convert/govermentAgreement.js
+++ b/src/libs/convert/governmentAgreement.js
@@ -18,7 +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/>.
 */
 
-module.exports = function govermentAgreement(id) {
+module.exports = function governmentAgreement(id) {
     switch (id) {
         case 1:
         return 'Convênio com rede Municipal';
@@ -32,6 +32,7 @@ module.exports = function govermentAgreement(id) {
         return 'Privada sem detalhamento';
         case 6:
         return 'Não se aplica (pública)';
+        case "null":
         default:
         return 'Não classificada';
     }
diff --git a/src/libs/convert/initialTraining.js b/src/libs/convert/initialTraining.js
index 3eff60f0021232d9203be255edb495e191d079c4..ef17c6e2381322e28e2f4e77f5b42d6d6ec5b71d 100644
--- a/src/libs/convert/initialTraining.js
+++ b/src/libs/convert/initialTraining.js
@@ -21,12 +21,14 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 module.exports = function initialTraining(id) {
     switch (id) {
     case 1:
-    return 'Sem formação mínima';
+        return 'Sem formação mínima';
     case 2:
-    return 'Ensino Médio na modalidade normal';
+        return 'Ensino Médio na modalidade normal';
     case 3:
-    return 'Superior bacharelado ou tecnólogo';
+        return 'Superior bacharelado ou tecnólogo';
     case 4:
-    return 'Superior com licenciatura ou complementação pedagógica';
+        return 'Superior com licenciatura ou complementação pedagógica';
+    case 5:
+        return 'Pós-gradução';
     }
 };
diff --git a/src/libs/convert/integralTime.js b/src/libs/convert/integralTime.js
index 1a1f8d307813b66bc9b862490cdeee7c56e43aa1..c780342b3e9482f1dddeaf3c17f5aa560d193093 100644
--- a/src/libs/convert/integralTime.js
+++ b/src/libs/convert/integralTime.js
@@ -25,6 +25,6 @@ module.exports = function integralTime(id) {
 		case 1:
 		return 'Sim';
 		case 2:
-		return 'Não se aplica (semi presencial e EaD)';
+		return 'Não se aplica - Semipresencial e EaD';
     }
 };
diff --git a/src/libs/convert/licentiateDegree.js b/src/libs/convert/licentiateDegree.js
new file mode 100644
index 0000000000000000000000000000000000000000..cc103374eae32b00bcf5ba92099eb08a4ca97068
--- /dev/null
+++ b/src/libs/convert/licentiateDegree.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 licentiateDegree(id) {
+    switch (id) {
+    case 1:
+        return 'Sem ensino superior';
+    case 2:
+        return 'Superior com bacharelado ou tecnólogo';
+    case 3:
+        return 'Superior com licenciatura ou complementação pedagógica';
+    }
+};
diff --git a/src/libs/convert/nightTime.js b/src/libs/convert/nightTime.js
index 1e84007145b7bf1af29d4f44dc057bd4860d5b6e..99b9f07818fe122b237fe0e0d32c603a08cb4cd2 100644
--- a/src/libs/convert/nightTime.js
+++ b/src/libs/convert/nightTime.js
@@ -26,7 +26,8 @@ module.exports = function nightTime(id) {
 			return 'Não';
 		case 1:
 			return 'Sim';
+		case 9:
 		default:
-			return 'Curso a distância';
+			return 'Curso à distância';
 	}
 };
\ No newline at end of file
diff --git a/src/libs/convert/peePorCategoria.js b/src/libs/convert/peePorCategoria.js
new file mode 100644
index 0000000000000000000000000000000000000000..f944fe4e9d8dabe8b0827a1c99ed5c6210f91184
--- /dev/null
+++ b/src/libs/convert/peePorCategoria.js
@@ -0,0 +1,52 @@
+/*
+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 peeCategory(id) {
+    switch (id) {
+        case 1:
+        return 'Cegueira';
+        case 2:
+        return 'Baixa visão';
+        case 3:
+        return 'Surdez';
+        case 4:
+        return 'Deficiência auditiva';
+        case 5:
+        return 'Surdocegueira';
+        case 6:
+        return 'Deficiência física';
+        case 7:
+        return 'Deficiência intelectual';
+        case 8:
+        return 'Deficiências múltiplas';
+        case 9:
+        return 'Autismo';
+        case 10:
+        return 'Síndrome de Asperger';
+        case 11:
+        return 'Síndrome de Rett';
+        case 12:
+        return 'Transtorno Desintegrativo da Infância';
+        case 13:
+        return 'Altas habilidades / Superdotação';
+        case 14:
+        return 'Transtorno do Espectro Austista (TEA)';
+    }
+};
diff --git a/src/libs/convert/pfe.js b/src/libs/convert/pfe.js
index c67a7141af9779bac92b145a06d084753bcf9c49..ca71b98b17c0a1258b2adc10894200dd09e046e2 100644
--- a/src/libs/convert/pfe.js
+++ b/src/libs/convert/pfe.js
@@ -20,18 +20,31 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 
 module.exports = function pfeName(id) {
     switch(id) {
-        case 1: return 'População fora da escola menor de 1 ano';
-        case 2: return 'População fora da escola 1 ano';
-        case 3: return 'População fora da escola 2 anos';
-        case 4: return 'População fora da escola 3 anos';
-        case 5: return 'População fora da escola 4 anos';
-        case 6: return 'População fora da escola 5 anos';
-        case 7: return 'População fora da escola 6 e 10 anos sem instrução ou com EF incompleto';
-        case 8: return 'População fora da escola 11 a 14 anos sem instrução';
-        case 9: return 'População fora da escola 11 a 14 anos com EF incompleto';
-        case 10: return 'População fora da escola 15 a 24 anos com e EF completo EM incompleto';
-        case 11: return 'População fora da escola 15 anos mais sem instrução';
-        case 12: return 'População fora da escola 15 anos mais com EF incompleto';
-        case 13: return 'População fora da escola 25 anos mais com EF completo e EM incompleto';
+        case 1: 
+        return 'População fora da escola menor de 1 ano';
+        case 2: 
+        return 'População fora da escola 1 ano';
+        case 3: 
+        return 'População fora da escola 2 anos';
+        case 4: 
+        return 'População fora da escola 3 anos';
+        case 5: 
+        return 'População fora da escola 4 anos';
+        case 6: 
+        return 'População fora da escola 5 anos';
+        case 7: 
+        return 'População fora da escola 6 e 10 anos sem instrução ou com EF incompleto';
+        case 8: 
+        return 'População fora da escola 11 a 14 anos sem instrução';
+        case 9: 
+        return 'População fora da escola 11 a 14 anos com EF incompleto';
+        case 10: 
+        return 'População fora da escola 15 a 24 anos com e EF completo EM incompleto';
+        case 11: 
+        return 'População fora da escola 15 anos mais sem instrução';
+        case 12: 
+        return 'População fora da escola 15 anos mais com EF incompleto';
+        case 13: 
+        return 'População fora da escola 25 anos mais com EF completo e EM incompleto';
     }
 };
diff --git a/src/libs/convert/schoolType.js b/src/libs/convert/schoolType.js
index f485ecb9fabf74e860e34d1d082b0de1eacce36d..665fc14c23b806ecc12875cd6e612de58a7a6738 100644
--- a/src/libs/convert/schoolType.js
+++ b/src/libs/convert/schoolType.js
@@ -18,12 +18,13 @@ 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 studentDeficiency(id) {
+module.exports = function schoolType(id) {
     switch (id) {
         case 1:
         return 'Pública';
         case 2:
         return 'Privada';
+        case 9:
         default:
         return 'Não classificado';
     }
diff --git a/src/libs/convert/stateName.js b/src/libs/convert/stateName.js
index 7b526379e670b80da5b5f8be6ca90ac997a446f9..092969fa961aceaf262db094c383a7362267eee8 100644
--- a/src/libs/convert/stateName.js
+++ b/src/libs/convert/stateName.js
@@ -37,7 +37,7 @@ module.exports = function stateName(id) {
         case 21:
         return 'Maranhão';
         case 22:
-        return'Piauí';
+        return 'Piauí';
         case 23:
         return 'Ceará';
         case 24:
diff --git a/src/libs/convert/studentDeficiency.js b/src/libs/convert/studentDeficiency.js
index c5ad0e0184de5f4eecf1ed889c7ea526f634ee0d..a9c648c86a9b3e9df5d3df5327c26962c342dc49 100644
--- a/src/libs/convert/studentDeficiency.js
+++ b/src/libs/convert/studentDeficiency.js
@@ -24,7 +24,8 @@ module.exports = function studentDeficiency(id) {
         return 'Não';
         case 1:
         return 'Sim';
+        case 9:
         default:
-        return 'Não declarado'
+        return 'Não declarado';
     }
 };
diff --git a/src/libs/convert/upperTurn.js b/src/libs/convert/upperTurn.js
index b5cac83f361bebe821ef9be7b4a442500bd43985..3a751dd4a0f315e445d91c1542fa29038625eaac 100644
--- a/src/libs/convert/upperTurn.js
+++ b/src/libs/convert/upperTurn.js
@@ -28,7 +28,9 @@ module.exports = function upperTurn(id) {
         return 'Noturno';
         case 4:
         return 'Integral';
-        default:
+        case "null":
         return 'Não aplicavel (Ead)';
+        default:
+        return 'Não classificada'; 
     }
 };
diff --git a/src/libs/convert/workRegime.js b/src/libs/convert/workRegime.js
index f03d97a8ec20ff4466b9024e16a38a425c3465b1..46f14afa41ba50a37da3263c75f51d57c9534d3d 100644
--- a/src/libs/convert/workRegime.js
+++ b/src/libs/convert/workRegime.js
@@ -28,7 +28,8 @@ module.exports = function workRegime(id) {
         return 'Tempo Parcial';
         case 4:
         return 'Horista';
+        case "null":
         default:
-        return 'Não declarado';
+        return 'Não Declarado';
     }
 };
diff --git a/src/libs/middlewares/email.js b/src/libs/middlewares/email.js
index 7e0403d423cebd1bd0a8c6c31f57eef5773860f4..4d1d51711566a586fc5d29c0bf8ba7953f7da0f1 100644
--- a/src/libs/middlewares/email.js
+++ b/src/libs/middlewares/email.js
@@ -7,8 +7,9 @@ const htmlToText = require('nodemailer-html-to-text').htmlToText;
 let transporter = nodemailer.createTransport({
     host: config.email.host,
     port: config.email.port,
-    secure: config.email.secure,
-    ignoreTLS: config.email.ignoreTLS
+    secureConnection: config.email.secureConnection,
+    auth: config.email.auth,
+    tls: config.email.tls,
 });
 
 transporter.use('compile', htmlToText());
@@ -23,7 +24,8 @@ transporter.verify(function(error, success) {
 });
 
 const mailOptions = {
-    from: config.email.from
+    from: config.email.from,
+    to: config.email.from
 };
 
 module.exports = function send(options, cb) {
@@ -34,4 +36,4 @@ module.exports = function send(options, cb) {
         }
         cb(null, info);
     });
-};
\ No newline at end of file
+};
diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js
index cb9a18d6303bf9226028ddbc246a76e01b1ec2b1..bd5c83c0d108d55d8e91b154f499f17b6221bfab 100644
--- a/src/libs/middlewares/id2str.js
+++ b/src/libs/middlewares/id2str.js
@@ -81,13 +81,20 @@ const teacherSchooling = require(`${libs}/convert/teacherSchooling`);
 const ethnicGroupTeacherIES = require(`${libs}/convert/ethnicGroupTeacherIES`);
 const genderIES = require(`${libs}/convert/genderIES`);
 const deficiency = require(`${libs}/convert/studentDeficiency`);
-const govermentAgreement = require(`${libs}/convert/govermentAgreement`);
+const governmentAgreement = require(`${libs}/convert/governmentAgreement`);
 const arrangement = require(`${libs}/convert/arrangement`);
 const nightTime = require(`${libs}/convert/nightTime`);
 const discipline = require(`${libs}/convert/discipline`);
 const finishUniversity = require(`${libs}/convert/finishUniversity`);
 const initialTraining = require(`${libs}/convert/initialTraining`);
 const posTraining = require(`${libs}/convert/posTraining`);
+const licentiateDegree = require(`${libs}/convert/licentiateDegree`);
+const enrolledVacanciesFreshmen = require(`${libs}/convert/enrolledVacanciesFreshmen`);
+const enterSituation = require(`${libs}/convert/enterSituation`);
+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 ids = {
     gender_id: gender,
@@ -105,7 +112,7 @@ const ids = {
     ethnic_group_id: ethnicGroup,
     agreement_id: agreement,
     integral_time_id: integralTime,
-    government_agreement_id: govermentAgreement,
+    government_agreement_id: governmentAgreement,
     education_day_care_child_id: booleanVariable,
     education_preschool_child_id: booleanVariable,
     education_begin_elementary_school_id: booleanVariable,
@@ -167,7 +174,14 @@ const ids = {
     discipline: discipline,
     finish_id: finishUniversity,
     initial_training_id: initialTraining,
-    pos_training_id: posTraining
+    pos_training_id: posTraining,
+    licentiate_degree_id: licentiateDegree,
+    enrolled_vacancies_freshmen: enrolledVacanciesFreshmen,
+    enter_situation: enterSituation,
+    enrollment_situation: enrollmentSituation,
+    diff_location_id: diffLocation,
+    pee_por_categoria: peePorCategoria,
+    pee_id: pee
 };
 
 function transform(removeId=false) {
@@ -268,11 +282,18 @@ module.exports = {
     genderIES,
     deficiency,
     transport,
-    govermentAgreement,
+    governmentAgreement,
     arrangement,
     nightTime,
     discipline,
     finishUniversity,
     initialTraining,
-    posTraining
+    posTraining,
+    licentiateDegree,
+    enrolledVacanciesFreshmen,
+    enterSituation,
+    enrollmentSituation,
+    diffLocation,
+    peePorCategoria,
+    pee
 };
diff --git a/src/libs/middlewares/reqQueryFields.js b/src/libs/middlewares/reqQueryFields.js
index 61f989630effb5bd5a03519641eb0ca94bf781b0..0891e1b895fa0f8075ebe5970f6cb5e4bcdc6938 100644
--- a/src/libs/middlewares/reqQueryFields.js
+++ b/src/libs/middlewares/reqQueryFields.js
@@ -2,23 +2,28 @@ const libs = `${process.cwd()}/libs`;
 
 const log = require(`${libs}/log`)(module);
 
+const id2str = require(`${libs}/middlewares/id2str`);
+
 const _ = require('lodash');
 
-function parseWhereValue(type, value) {
+
+function parseWhereValue(type, value, relation) {
+    if (value == null)
+        return null;
+    if (value.toString().toLowerCase() == "null")
+        return null;
+
     if(type === 'integer') return parseInt(value, 10);
     if(type === 'double') return parseFloat(value);
-    if(type === 'string') return '%'+value+'%';
+    if(type === 'string' && relation === 'LIKE') return '%'+value+'%';
+    if(type === 'string') return value;
     if(type === 'boolean') {
         if(value === null || typeof value === 'boolean') {
             return value;
         }
         if(typeof value === 'string') {
-            if(value.toLowerCase() === 'true' || value.toLowerCase() === '1') {
+            if(value.toLowerCase() === 'true' || value.toLowerCase() === '1') 
                 return true;
-            }
-            if(value.toLowerCase() === 'null') {
-                return null;
-            }
         }
         return false;
     }
@@ -167,6 +172,18 @@ class ReqQueryFields {
                         // No exemplo `{'state': 41}`
                     }
 
+                    let categorias = ['', 'blindness', 'low_vision', 'deafness', 'hearing_deficiency', 'deafblindness', 'physical_disability', 'intellectual_disability', 
+                    'multiple_disabilities', 'autism', 'asperger_syndrom', 'rett_syndrom', 'childhood_desintegrative_disorder', 'supergifted', 'autism_spectrum_disorder'];
+
+                    if(obj.pee_por_categoria !== undefined && queryField === 'filter'){
+                        for(var cat of obj.pee_por_categoria){
+                            cat = parseInt(cat);
+                            obj[categorias[cat]] = true;
+                        }
+                        delete obj.pee_por_categoria;
+                    }
+                        
+
                     // Se o array existe e não está vazio fazemos a interseção
                     if (typeof arrayOfParams !== 'undefined' && arrayOfParams.length > 0) {
                         // Fazemos a interseção das chaves de `obj` com o array `arrayOfParams`.
@@ -217,18 +234,20 @@ class ReqQueryFields {
                         if(value.join.foreignTable === '@') foreignTable = thisTable+'.';
                         // Fazemos o join
                         let onClause = '';
-                        if(Array.isArray(value.join.primary)) {
-                            // Se é um array, montamos a cláusula ON com mais de uma coluna
-                            value.join.primary.forEach((column, index, arr) => {
-                                onClause += foreignTable+value.join.foreign[index]+'='+value.table+'.'+column;
-                                if(index < arr.length-1) {
-                                    onClause+=' AND ';
-                                }
-                            });
-                        } else {
-                            onClause = foreignTable+value.join.foreign+'='+value.table+'.'+value.join.primary;
+                        if (foreignTable !== value.table+'.') { // Não é feito join de uma tabela com ela mesma
+                            if(Array.isArray(value.join.primary)) {
+                                // Se é um array, montamos a cláusula ON com mais de uma coluna
+                                value.join.primary.forEach((column, index, arr) => {
+                                    onClause += foreignTable+value.join.foreign[index]+'='+value.table+'.'+column;
+                                    if(index < arr.length-1) {
+                                        onClause+=' AND ';
+                                    }
+                                });
+                            } else {
+                                onClause = foreignTable+value.join.foreign+'='+value.table+'.'+value.join.primary;
+                            }
+                            sql.join(value.table, null, onClause);
                         }
-                        sql.join(value.table, null, onClause);
                         // Marcamos o join como feito para não ter problemas
                         hasJoined[value.table] = true;
                     }
@@ -281,14 +300,14 @@ class ReqQueryFields {
                                     let whereString = '(';
                                     for(let i = 0; i < whereValue.length; ++i) {
                                         whereString += whereField;
-                                        whereValues.push(parseWhereValue(value.where.type, whereValue[i]));
+                                        whereValues.push(parseWhereValue(value.where.type, whereValue[i], value.where.relation));
                                         if(i < whereValue.length-1) {
                                             whereString += ' OR ';
                                         }
                                     }
                                     whereString += ')';
                                 } else {
-                                    whereValues.push(parseWhereValue(value.where.type, whereValue));
+                                    whereValues.push(parseWhereValue(value.where.type, whereValue, value.where.relation));
                                 }
                             });
 
@@ -300,8 +319,13 @@ class ReqQueryFields {
                                 let whereString = '(';
                                 let arrayWhereValues = [];
                                 for(let i = 0; i < whereValue.length; ++i) {
-                                    whereString += whereField + ' ' + value.where.relation + lower;
-                                    arrayWhereValues.push(parseWhereValue(value.where.type, whereValue[i]));
+                                    let curRelation = value.where.relation;
+                                    let curValue = parseWhereValue(value.where.type, whereValue[i],value.where.relation)
+                                    if (curValue === null) 
+                                        curRelation = "is";
+
+                                    whereString += whereField + ' ' + curRelation + lower;
+                                    arrayWhereValues.push(curValue);
                                     if(i < whereValue.length-1) {
                                         whereString += ' OR ';
                                     }
@@ -309,7 +333,13 @@ class ReqQueryFields {
                                 whereString += ')';
                                 sql.where(whereString, ...arrayWhereValues);
                             } else {
-                                sql.where(whereField + ' ' + value.where.relation + lower, parseWhereValue(value.where.type, whereValue));
+                                let curValue = parseWhereValue(value.where.type, whereValue, value.where.relation)
+                                let curRelation = value.where.relation;
+                                
+                                if (curValue === null ) 
+                                    curRelation = "is";
+
+                                sql.where(whereField + ' ' + curRelation + lower, curValue);
                             }
                         }
                     }
diff --git a/src/libs/models/user.js b/src/libs/models/user.js
index 0d54e4175fbf3336c4386bcc252d235dc6b478ce..be62f4a5cf87074e2f84695f3d1e190c20b8c118 100644
--- a/src/libs/models/user.js
+++ b/src/libs/models/user.js
@@ -81,8 +81,8 @@ var UserSchema = new Schema({
     },
     origin: {
         type: String,
-        enum: ['LDE', 'SimCAQ'],
-        required: [true, 'O campo origem é obrigatória e aceita apenas os valores "LDE" ou "SimCAQ"']
+        enum: ['LDE', 'SimCAQ', 'MAPFOR'],
+        required: [true, 'O campo origem é obrigatória e aceita apenas os valores "LDE", "SimCAQ" e "MAPFOR"']
     },
     verified: {
         type: Boolean,
diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js
index c96266b09f260fb65813ea5c71ca0aeef4a9347c..f6715eaa36c611eb5632d801cf3546ccd528fa16 100644
--- a/src/libs/routes/api.js
+++ b/src/libs/routes/api.js
@@ -118,6 +118,8 @@ const educationalBudget = require(`${libs}/routes/educationalBudget`);
 
 const schoolLocation = require(`${libs}/routes/schoolLocation`);
 
+const studentsAee = require(`${libs}/routes/studentsAee`);
+
 const mesoregion = require(`${libs}/routes/mesoregion`);
 
 const microregion = require(`${libs}/routes/microregion`);
@@ -128,6 +130,10 @@ const disciplines = require(`${libs}/routes/disciplines`);
 
 const universityLocalOffer = require(`${libs}/routes/universityLocalOffer`);
 
+const message = require(`${libs}/routes/message`);
+
+const courseStudents = require(`${libs}/routes/courseStudents`);
+
 api.get('/', (req, res) => {
     res.json({ msg: 'SimCAQ API is running' });
 });
@@ -178,9 +184,13 @@ 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/auxiliar.js b/src/libs/routes/auxiliar.js
index 5a4198d32bb0bfb55d996bd7e6b363ec6dd69436..ef5389611ae2b53dce22d3c513034db5f9bf64d9 100644
--- a/src/libs/routes/auxiliar.js
+++ b/src/libs/routes/auxiliar.js
@@ -80,7 +80,7 @@ auxiliarApp.get('/education_type', (req, res, next) => {
 
 auxiliarApp.get('/adm_dependency_detailed', (req, res, next) => {
     req.result = [];
-    for(let i = 1; i <= 6; ++i) {
+    for(let i = 1; i <= 7; ++i) {
         req.result.push({
             id: i,
             name: id2str.admDependencyPriv(i)
@@ -101,31 +101,26 @@ auxiliarApp.get('/adm_dependency', (req, res, next) => {
 }, response('adm_dependency'));
 
 auxiliarApp.get('/location', (req, res, next) => {
-    req.result = [];
-    for(let i = 1; i <= 2; ++i) {
-        req.result.push({
-            id: i,
-            name: id2str.location(i)
-        });
-    };
+    req.result = [
+        {id: 1, name: 'Urbana'},
+        {id: 2, name: 'Rural'}
+    ];
     next();
 }, response('location'));
 
-auxiliarApp.get('/rural_location', (req, res, next) => {
+auxiliarApp.get('/diff_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"}
+        {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('rural_location'));
+}, response('diff_location'));
 
 auxiliarApp.get('/education_level_mod', (req, res, next) => {
     req.result = [];
-    for(let i = 1; i <= 11; ++i) {
+    for(let i = 1; i <= 12; ++i) {
         req.result.push({
             id: i,
             name: id2str.educationLevelMod(i)
@@ -316,6 +311,16 @@ rqf.addField({
         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',
@@ -370,7 +375,7 @@ auxiliarApp.get('/', rqf.parse(), (req, res, next) => {
   .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)');     // não devemos trazer SC em 2009.
+    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'));
 
diff --git a/src/libs/routes/city.js b/src/libs/routes/city.js
index ef28500f275b237c9be2d4ec3a860da7d9e960cf..fc697a9f5d146c48c5e87c49ec54572566b22f82 100644
--- a/src/libs/routes/city.js
+++ b/src/libs/routes/city.js
@@ -69,6 +69,22 @@ rqf.addField({
         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,
@@ -82,7 +98,41 @@ rqf.addField({
         type: 'string',
         field: 'nome'
     }
-}, 'search');;
+}, '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) => {
@@ -97,4 +147,5 @@ cityApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
     next();
 }, query, response('city'));
 
+
 module.exports = cityApp;
diff --git a/src/libs/routes/class.js b/src/libs/routes/class.js
index 4cf349fa06672f1fbe927ddd4f424a9d4edb0844..4eca8cc30f9af5cc0c084bc792d26e55d4b2968d 100644
--- a/src/libs/routes/class.js
+++ b/src/libs/routes/class.js
@@ -69,29 +69,22 @@ classApp.get('/source', (req, res, next) => {
 }, query, response('source'));
 
 classApp.get('/location', (req, res, next) => {
-    req.result = [];
-    for(let i = 1; i <= 2; ++i) {
-        req.result.push({
-            id: i,
-            name: id2str.location(i)
-        });
-    };
+    req.result = [
+        {id: 1, name: 'Urbana'},
+        {id: 2, name: 'Rural'}
+    ];
     next();
 }, response('location'));
 
-classApp.get('/rural_location', (req, res, next) => {
+classApp.get('/diff_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"},
-        {id: 7, name: "Unidade de uso sustentavel em terra indígena"},
-        {id: 8, name: "Unidade de uso sustentável em área remanescente de quilombos"}
+        {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('rural_location'));
+}, response('diff_location'));
 
 // Returns all adm dependencies
 classApp.get('/adm_dependency', (req, res, next) => {
@@ -125,23 +118,29 @@ classApp.get('/period', (req, res, next) => {
             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 = [
-        {id: null, name: 'Não Disponível'},
-        {id: 0, name: 'Não'},
-        {id: 1, name: 'Sim'}
-    ];
+    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 <=11; ++i) {
+    for(let i = 1; i <=12; ++i) {
         req.result.push({
             id: i,
             name: id2str.educationLevelMod(i)
@@ -275,6 +274,16 @@ rqfCount.addField({
         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',
@@ -365,6 +374,16 @@ rqfCount.addField({
         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');
 
 
diff --git a/src/libs/routes/classCount.js b/src/libs/routes/classCount.js
index 2713238305d705af7f5d8cc06ce10e09b64568c1..ffdbe34fb15ee4df7312a7d8b45fb2b286a04bab 100644
--- a/src/libs/routes/classCount.js
+++ b/src/libs/routes/classCount.js
@@ -367,7 +367,7 @@ classCountApp.get('/count', rqf.parse(), (req, res, next) => {
    .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)');
+   .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'));
 
diff --git a/src/libs/routes/classroomCount.js b/src/libs/routes/classroomCount.js
index e337e57b8e01b3f2afe00c42f6c949dbebb3bd34..038c6e4563f20b8348ff4244385eb202c9197f55 100644
--- a/src/libs/routes/classroomCount.js
+++ b/src/libs/routes/classroomCount.js
@@ -43,6 +43,8 @@ const cache = require('apicache').options({ debug: config.debug, statusCodes: {i
 
 let rqf = new ReqQueryFields();
 
+const fs = require('fs')
+
 rqf.addField({
     name: 'filter',
     field: false,
@@ -113,6 +115,21 @@ rqf.addField({
         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',
@@ -218,7 +235,27 @@ rqf.addField({
         type: 'integer',
         field: 'dependencia_adm_id'
     }
-}, 'filter');
+}, '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;
@@ -250,19 +287,20 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
     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] = {
@@ -274,6 +312,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
             };
         }
     }
+    
     delete req.dims;
     delete req.filter;
     req.resetSql();
@@ -292,56 +331,20 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
     .group('escola.ano_censo')
     .order('escola.ano_censo')
     .where('escola.situacao_de_funcionamento = 1')
-    .where('escola.dependencia_adm_id < 4')
+    .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 ("state" in req.filter) {
-        req.dims.state = true;
-        req.dims.city = true;
-        req.dims.school_year = true;
-        req.dims.location = true;
-        req.sql.field('sum(indice_distribuicao_matriculas.indice)', 'total')
-               .field("'Brasil'", 'name')
-               .field('indice_distribuicao_matriculas.ano_censo', 'year')
-               .from('indice_distribuicao_matriculas')
-               .where('indice_distribuicao_matriculas.nivel_simulacao = 2')
-               .where('indice_distribuicao_matriculas.serie_ano_id < 15')
-               .group('indice_distribuicao_matriculas.ano_censo')
-               .order('indice_distribuicao_matriculas.ano_censo')
-    }
-    else {
-        req.dims.state = true;
-        req.dims.city = true;
-        req.dims.school_year = true;
-        req.dims.location = true;
-        req.sql.field('sum(indice_distribuicao_matriculas.indice)', 'idm')
-               .field("'Brasil'", 'name')
-               .field('indice_distribuicao_matriculas.ano_censo', 'year')
-               .from('indice_distribuicao_matriculas')
-               .where('indice_distribuicao_matriculas.nivel_simulacao = 1')
-               .where('indice_distribuicao_matriculas.serie_ano_id < 15')
-               .group('indice_distribuicao_matriculas.ano_censo')
-               .order('indice_distribuicao_matriculas.ano_censo')
-    }
 
-    next();
-}, rqf.build(), query, id2str.transform(), (req, res, next) =>  {
-    req.idm = req.result; 
     delete req.dims;
     delete req.filter;
     req.resetSql();
     next();
-},rqf.parse(), (req, res, next) => {
+}, rqf.parse(), (req, res, next) => {
     if (req.body.teacher_journey !== undefined) {
-        req.teacherJourney = JSON.parse(req.body.teacher_journey) || null;
+        // 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;
@@ -365,6 +368,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
             schoolYear.shifts = shifts
             teachingHoursParsed.push(schoolYear)
         }
+
         req.schoolDays = schoolDaysParsed;
         req.teachingHours = teachingHoursParsed;
 
@@ -373,7 +377,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
             teacherFormationParsed.push(teacherFormation.find((el) => {return el.idFormationLevel === i}))
         }
         req.teacherFormation = teacherFormationParsed;
-
+        
         req.teacherCalc = true;
     }
 
@@ -390,16 +394,88 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
     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) => {
-    // req.classroom = req.result;
-    // req.idm = req.result; 
-    
-    // req.result = [{classroom: req.classroom, enrollment: req.enrollment}]; return next();
 
+    // Talvez dê para remover todos os req.projections.
     let enrollmentProjectionNight = [];
     let enrollmentProjectionDay = [];
     if (req.projections) {
@@ -413,28 +489,25 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
     }
     let qntYears = 1;
     if (req.projections) {
-        qntYears = enrollmentProjectionDay[0].stagesEnrollments[0].seriesEnrollments[0].enrollments.length;
+       qntYears = enrollmentProjectionDay[0].stagesEnrollments[0].seriesEnrollments[0].enrollments.length;
     }
     let result = [];
 
-    // Cria estrutura de resposta requisitada:
+    // 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 ei = 0;    // index for idm table
-        let eiCityStart = 0;
-
-        let verifySchoolYear;       // Matriz para verificar se o idm já foi inserido no school year.
-
         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;
+            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,
@@ -443,8 +516,14 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                 state_name: classroom.state_name,
                 city_id: classroom.city_id,
                 city_name: classroom.city_name,
-                locations: []
             };
+            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 = {
@@ -455,9 +534,11 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                 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) ) {
+            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) {
@@ -470,23 +551,29 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                         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_locations, ti);
+                    if (req.teacherCalc) executeTeacherCalc(last_city, ti);
                 }
                 hashSet.add(hash);
                 result.push(obj);
                 currentClassroomObj = obj;
 
-                eiCityStart = ei;
-
-                verifySchoolYear = Array.from(Array(2), () => new Array(15));
-
-                while (req.teacher[ti].city_id !== classroom.city_id) {       // match da tabela de professores.
+                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];
-                ei = eiCityStart;
             }
             currentClassroomObj.locations.push(location);
 
@@ -503,14 +590,19 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                     ++j;
                     continue;
                 }
-
-                if(classroom.city_id !== enrollment.city_id) { // Se as cidades não são iguais, já passamos do range
-                    enrollmentMatch = false;
-                    while (req.idm[ei].city_id !== enrollment.city_id) {
-                        ei++;
-                    }
-                    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;
@@ -518,7 +610,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                 }
 
 
-                // Temos uma matrícula com cidade, ano e localidades certos
+                // 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);
 
@@ -528,14 +620,32 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
 
                 if(enrollmentEducationLevel.numberStudentClass == null) continue;
                 
+                // Adiciona nível de educação para município/escola
                 let educationLevel = null;
-                if(!educationLevelSet.has(enrollmentEducationLevel.id)) {
+                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,
@@ -549,7 +659,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                         educationLevel.classes_school_year = [];
                     }
 
-                    // Para manter a ordem da etapa de ensino
+                    // Para manter a ordem da etapa de ensino (insertion sort)
                     if (location.education_level.length == 0) {
                         location.education_level.push(educationLevel);
                     } else {
@@ -564,7 +674,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                         k++;
                         location.education_level.splice(k, 0, educationLevel);
                     }
-                } else {
+                } else { // pega o objeto de education level já existente
                     let k = 0;
                     let el = location.education_level[k];
                     while(k < location.education_level.length) {
@@ -581,6 +691,8 @@ 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(schoolYearSet.has(schoolYearHash)) { // Busca a série escolar
                         let k = 0;
                         let el = educationLevel.classes_school_year[k];
@@ -616,22 +728,8 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                     }
                 }
 
-                // Faz match da tabela de idm com a de enrollment
-                if (educationLevel.education_level_short_id !== 1) {
-                    while (req.idm[ei].school_year_id < educationLevel.education_level_short_id) ei++;
-                    while (req.idm[ei].school_year_id > educationLevel.education_level_short_id) ei--;
-
-                    if (req.idm[ei].location_id < location.location_id) {
-                        ei++;
-                    }
-                    else if(req.idm[ei].location_id > location.location_id) {
-                        ei--;
-                    }
-                }
-                let enrollmentIdm = req.idm[ei];
-
-
-                let currentIntegralOfferGoal = enrollmentEducationLevel.integralTimeOfferGoal;
+                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
@@ -662,44 +760,12 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                     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];
                 }
-                if (!verifySchoolYear[location.location_id-1][educationLevel.education_level_short_id]) {     // Garantimos que será somado apenas uma vez por localização.
-                    verifySchoolYear[location.location_id-1][educationLevel.education_level_short_id] = 1;
-                    
-                    // Projeção de matricula multiplicada pelo indice de distribuição de matriculas da localização.
-                    if (req.projections && (currentEnrollmentOfferDay.enrollments !== undefined) ) {
-                        educationLevel.enrollment.total_enrollment_day += parseFloat(((currentEnrollmentOfferDay.enrollments[yearCount].quantity - currentEnrollmentOfferDay.currentOffer)*enrollmentIdm.idm).toFixed(2));
-                        if (educationLevel.enrollment.total_enrollment_day < 0) educationLevel.enrollment.total_enrollment_day = 0;
-                        educationLevel.enrollment.total_enrollment_night += (educationLevel.education_level_short_id > 2) ? parseFloat(((currentEnrollmentOfferNight.enrollments[yearCount].quantity - currentEnrollmentOfferNight.currentOffer)*enrollmentIdm.idm).toFixed(2)) : 0;
-                        if (educationLevel.enrollment.total_enrollment_night < 0) educationLevel.enrollment.total_enrollment_night = 0;
-                    }
-                }
 
                 // Faz os mesmos cálculos para a série escolar
                 if(currentSchoolYear) {
-                    // Faz match da enrollment com o idm, no caso de não usar o mod
-                    while (req.idm[ei].school_year_id < enrollment.school_year_id) ei++;
-                    while (req.idm[ei].school_year_id > enrollment.school_year_id) ei--;
-
-                    if (req.idm[ei].location_id < location.location_id) {
-                        ei++;
-                    }
-                    else if(req.idm[ei].location_id > location.location_id) {
-                        ei--;
-                    }
-                    enrollmentIdm = req.idm[ei];
-
-
                     // Totais de matrícula
                     currentSchoolYear.total_enrollment_day += enrollment.total_day;
 
-                    if (req.projections && !verifySchoolYear[location.location_id-1][currentSchoolYear.school_year_id]) {     // Garantimos que será somado apenas uma vez por localização.
-                        verifySchoolYear[location.location_id-1][currentSchoolYear.school_year_id] = 1;
-
-                        let currentEnrollmentSchoolYear = currentEnrollmentOfferDay.seriesEnrollments[Math.trunc(currentSchoolYear.school_year_id/10) - 1];
-                        currentSchoolYear.total_enrollment_day += (currentEnrollmentSchoolYear !== undefined) ? parseFloat(((currentEnrollmentSchoolYear.enrollments[yearCount].quantity - currentEnrollmentSchoolYear.currentOffer)*enrollmentIdm.idm).toFixed(2)) : 0;
-                        if (currentSchoolYear.total_enrollment_day < 0) currentSchoolYear.total_enrollment_day = 0;
-                    }
-                    
                     // Número de turmas parcial
                     currentSchoolYear.full_period_classes = parseFloat(((currentSchoolYear.total_enrollment_day * (currentIntegralOfferGoal/100)) / currentNumberStudentClass).toFixed(2));
 
@@ -730,6 +796,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
 
         // 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) {
@@ -742,13 +809,14 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                 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_locations, ti);
+            if (req.teacherCalc) executeTeacherCalc(last_city, ti);
         }
     }
 
     // Agregar por estado e brasil
     let reduction = null;
-    if(req.dims.state || !req.dims.city) { // Se um dos dois acontecer, sabemos que devemos agregar
+    
+    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();
@@ -756,16 +824,17 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
             let city = result[i];
             let obj = {
                 year: city.year,
-                name: city.name
+                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;
 
@@ -776,6 +845,16 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                 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
@@ -827,6 +906,8 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                             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;
@@ -908,6 +989,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                             ++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;
@@ -918,12 +1000,26 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
             }
             ++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(lastLocations, index) {
+    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;
         
@@ -938,25 +1034,31 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
             }
         }
 
-        // console.log(teacherByFormation, teacherTotal);
-
         // 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 for menor/maior que 100 soma/subtrai na P2 caso exista, se não na P1
+        
+        // Se soma de porcentagens for menor/maior que 100, faz correção
         if (Math.abs(diff) > 0.0001) {
-            if (teacherByFormation[1] > 0) {
-                teacherByFormation[1] += diff;
-            }
-            else {
-                teacherByFormation[0] += diff;
-            }
+            // Garante que a porcentagem corrigida não ficará negativa
+            let indDiff = 1;
+            while (teacherByFormation[indDiff] + diff < 0) indDiff++;
+            teacherByFormation[indDiff] += diff;
         }
 
-        // console.log(teacherByFormation)
+        // 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) => {
@@ -964,8 +1066,6 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
 
                 let currentTeachingHours = req.teachingHours[educationLevelId-1].shifts;
         
-                let journey = req.teacherJourney.journeyTotal * req.teacherJourney.journeyWithInteraction/100;
-
                 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;
@@ -974,62 +1074,25 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
 
                         let currentTeacherByClass = (location.location_id === 1) ? req.educationSchoolYear[schoolYear.school_year_id].teacherByClass.urban : req.educationSchoolYear[schoolYear.school_year_id].teacherByClass.country;
                         
-                        let numberOfTeacherFullPeriod = parseFloat(((teachingTimeFullPeriod / journey) * currentTeacherByClass).toFixed(2));
-                        let numberOfTeacherNight = parseFloat(((teachingTimeNight / journey) * currentTeacherByClass).toFixed(2));
-                        let numberOfTeacherDay = parseFloat(((teachingTimeDay / journey) * currentTeacherByClass).toFixed(2));
+                        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
                         }
-    
-                        // schoolYear.teacherNumber.careerLevels = [];
-                        // req.teacherFormation.forEach((formation, i) => {
-                        //     let totalTeacherFullPeriodCareer = Math.ceil(schoolYear.teacherNumber.total_teacher_full_period * teacherByFormation[i]);
-                        //     let totalTeacherPartialCareer = Math.ceil(schoolYear.teacherNumber.total_teacher_partial * teacherByFormation[i]);
-
-                        //     schoolYear.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,
-                        //     })
-                        // })
-
-                        // // Garantimos que a soma das porcentagens deu 100% usando reduce, geralmente não ocorre devido à função teto.
-                        // function reducer(key) { return (sum, elem) => sum + elem[key]};
-                        // let teacherDiffFullPeriod = schoolYear.teacherNumber.careerLevels.reduce(reducer('total_teacher_full_period_career'), 0) - schoolYear.teacherNumber.total_teacher_full_period;
-                        // let teacherDiffPartial = schoolYear.teacherNumber.careerLevels.reduce(reducer('total_teacher_partial_career'), 0) - schoolYear.teacherNumber.total_teacher_partial;
-
-                        // // Remove primeiro do ensino superior, caso não tenha suficiente remove do nível médio.
-                        // schoolYear.teacherNumber.careerLevels[1].total_teacher_full_period_career -= teacherDiffFullPeriod;
-                        // if (schoolYear.teacherNumber.careerLevels[1].total_teacher_full_period_career < 0) {
-                        //     teacherDiffFullPeriod = (-1)*schoolYear.teacherNumber.careerLevels[1].total_teacher_full_period_career;
-                        //     schoolYear.teacherNumber.careerLevels[1].total_teacher_full_period_career = 0;
-
-                        //     schoolYear.teacherNumber.careerLevels[0].total_teacher_full_period_career -= teacherDiffFullPeriod;
-                        //     if (schoolYear.teacherNumber.careerLevels[0].total_teacher_full_period_career < 0)
-                        //         schoolYear.teacherNumber.careerLevels[0].total_teacher_full_period_career = 0;
-                        // }
-
-                        // // Repete calculos para parcial
-                        // schoolYear.teacherNumber.careerLevels[1].total_teacher_partial_career -= teacherDiffPartial;
-                        // if (schoolYear.teacherNumber.careerLevels[1].total_teacher_partial_career < 0) {
-                        //     teacherDiffPartial = (-1)*schoolYear.teacherNumber.careerLevels[1].total_teacher_partial_career;
-                        //     schoolYear.teacherNumber.careerLevels[1].total_teacher_partial_career = 0;
-
-                        //     schoolYear.teacherNumber.careerLevels[0].total_teacher_partial_career -= teacherDiffPartial;
-                        //     if (schoolYear.teacherNumber.careerLevels[0].total_teacher_partial < 0)
-                        //         schoolYear.teacherNumber.careerLevels[0].total_teacher_partial_career = 0;
-                        // }
-
-                        // // Atualiza os totais das carreiras
-                        // schoolYear.teacherNumber.careerLevels[1].total_teacher_career = schoolYear.teacherNumber.careerLevels[1].total_teacher_full_period_career + schoolYear.teacherNumber.careerLevels[1].total_teacher_partial_career;
-                        // schoolYear.teacherNumber.careerLevels[0].total_teacher_career = schoolYear.teacherNumber.careerLevels[0].total_teacher_full_period_career + schoolYear.teacherNumber.careerLevels[0].total_teacher_partial_career;
-                    
                     })
 
                     // Calculamos para o educationLevel usando reduce
@@ -1064,9 +1127,19 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
 
                     let currentTeacherByClass = (location.location_id === 1) ? req.educationSchoolYear[educationLevelId].teacherByClass.urban : req.educationSchoolYear[educationLevelId].teacherByClass.country;
         
-                    let numberOfTeacherFullPeriod = parseFloat(((teachingTimeFullPeriod / journey) * currentTeacherByClass).toFixed(2));
-                    let numberOfTeacherNight = parseFloat(((teachingTimeNight / journey) * currentTeacherByClass).toFixed(2));
-                    let numberOfTeacherDay = parseFloat(((teachingTimeDay / journey) * currentTeacherByClass).toFixed(2));
+                    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,
@@ -1089,37 +1162,6 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
                         })
                     })
 
-
-                    // // Garantimos que a soma das porcentagens deu 100% usando reduce, geralmente não ocorre devido à função teto.
-                    // function reducer(key) {return (sum, elem) => sum + elem[key]};
-                    // let teacherDiffFullPeriod = educationLevel.teacherNumber.careerLevels.reduce(reducer('total_teacher_full_period_career'), 0) - educationLevel.teacherNumber.total_teacher_full_period;
-                    // let teacherDiffPartial = educationLevel.teacherNumber.careerLevels.reduce(reducer('total_teacher_partial_career'), 0) - educationLevel.teacherNumber.total_teacher_partial;
-
-                    // // Remove primeiro do ensino superior, caso não tenha suficiente remove do nível médio.
-                    // educationLevel.teacherNumber.careerLevels[1].total_teacher_full_period_career -= teacherDiffFullPeriod;
-                    // if (educationLevel.teacherNumber.careerLevels[1].total_teacher_full_period_career < 0) {
-                    //     teacherDiffFullPeriod = (-1)*educationLevel.teacherNumber.careerLevels[1].total_teacher_full_period_career;
-                    //     educationLevel.teacherNumber.careerLevels[1].total_teacher_full_period_career = 0;
-
-                    //     educationLevel.teacherNumber.careerLevels[0].total_teacher_full_period_career -= teacherDiffFullPeriod;
-                    //     if (educationLevel.teacherNumber.careerLevels[0].total_teacher_full_period_career < 0)
-                    //         educationLevel.teacherNumber.careerLevels[0].total_teacher_full_period_career = 0;
-                    // }
-
-                    // // Repete calculos para parcial
-                    // educationLevel.teacherNumber.careerLevels[1].total_teacher_partial_career -= teacherDiffPartial;
-                    // if (educationLevel.teacherNumber.careerLevels[1].total_teacher_partial_career < 0) {
-                    //     teacherDiffPartial = (-1)*educationLevel.teacherNumber.careerLevels[1].total_teacher_partial_career;
-                    //     educationLevel.teacherNumber.careerLevels[1].total_teacher_partial_career = 0;
-
-                    //     educationLevel.teacherNumber.careerLevels[0].total_teacher_partial_career -= teacherDiffPartial;
-                    //     if (educationLevel.teacherNumber.careerLevels[0].total_teacher_partial < 0)
-                    //         educationLevel.teacherNumber.careerLevels[0].total_teacher_partial_career = 0;
-                    // }
-
-                    // // Atualiza os totais das carreiras
-                    // educationLevel.teacherNumber.careerLevels[1].total_teacher_career = educationLevel.teacherNumber.careerLevels[1].total_teacher_full_period_career + educationLevel.teacherNumber.careerLevels[1].total_teacher_partial_career;
-                    // educationLevel.teacherNumber.careerLevels[0].total_teacher_career = educationLevel.teacherNumber.careerLevels[0].total_teacher_full_period_career + educationLevel.teacherNumber.careerLevels[0].total_teacher_partial_career;
                 }
             })
         })
@@ -1129,3 +1171,4 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => {
 }, response('classroom_count'));
 
 module.exports = classroomCountApp;
+
diff --git a/src/libs/routes/courseCount.js b/src/libs/routes/courseCount.js
index fce35171d07995e2a82b9bae60ad4e0ea2918eaf..b72181c52bfc56da079baf5126357d3df5262894 100644
--- a/src/libs/routes/courseCount.js
+++ b/src/libs/routes/courseCount.js
@@ -19,6 +19,7 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 const express = require('express');
+const { join } = require('lodash');
 
 const courseCountApp = express.Router();
 
@@ -42,6 +43,8 @@ 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) {
@@ -129,7 +132,7 @@ courseCountApp.get('/ocde_detailed', (req, res, next) => {
 
 courseCountApp.get('/cine_geral', (req, res, next) => {
     req.result = [];
-    for(let i = 0; i <= 10; ++i) {
+    for(let i = 1; i <= 10; ++i) {
         req.result.push({
             id: i,
             name: id2str.cineGeral(i)
@@ -189,7 +192,7 @@ courseCountApp.get('/academic_level', (req, res, next) => {
 
 courseCountApp.get('/upper_education_mod', (req, res, next) => {
     req.result = [];
-    for(let i = 1; i <= 3; ++i) {
+    for(let i = 1; i <= 2; ++i) {
         req.result.push({
             id: i,
             name: id2str.upperEducationMod(i)
@@ -208,11 +211,16 @@ courseCountApp.get('/is_free', (req, res, next) => {
 }, response('is_free'));
 
 courseCountApp.get('/night_time', (req, res, next) => {
-    req.result = [
-        {id: null, name: 'Não Classificado'},
-        {id: 0, name: 'Não'},
-        {id: 1, name: 'Sim'}
-    ];
+    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'));
 
@@ -230,6 +238,165 @@ courseCountApp.get('/localoffer', (req, res, next) => {
     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,
@@ -270,6 +437,38 @@ rqf.addField({
         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',
@@ -302,6 +501,22 @@ rqf.addField({
 	    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',
@@ -312,6 +527,16 @@ rqf.addField({
         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',
@@ -439,7 +664,7 @@ rqf.addField({
     resultField: 'night_time_id',
     where: {
         relation: '=',
-        type: 'boolean',
+        type: 'integer',
         field: 'noturno_curso_t'
     }
 }).addValue({
@@ -484,11 +709,32 @@ rqf.addField({
         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(1))
+        }
+    }
+    next();
+}, id2str.transform(), response('count_by_name'));
 
 courseCountApp.get('/', rqf.parse(), (req, res, next) => {
-    if ("localoffer" in req.dims) {
-        if ("university" in req.dims) {
+    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')
@@ -511,17 +757,29 @@ courseCountApp.get('/', rqf.parse(), (req, res, next) => {
                 .order('curso_ens_superior.ano_censo')
                 .order('localoferta_ens_superior.cod_local_oferta');
         }
-    } else if (("state" in req.dims) || ("city" in req.dims) || ("region" in req.dims) ||
-        ("state" in req.filter) || ("city" in req.filter) || ("region" in req.filter)) {
-        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) {
+    } 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')
@@ -543,6 +801,14 @@ courseCountApp.get('/', rqf.parse(), (req, res, next) => {
             .where('curso_ens_superior.cod_nivel_academico = 1');
     }
     next();
-}, rqf.build(), query, id2str.transform(), addMissing(rqf), response('course_count'));
+}, 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/courseStudents.js b/src/libs/routes/courseStudents.js
new file mode 100644
index 0000000000000000000000000000000000000000..77180cb2b23489df7f2ebf74c57cc0471fddbc3e
--- /dev/null
+++ b/src/libs/routes/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/cub.js b/src/libs/routes/cub.js
index 3707e7f0df6daa731ae482a0d261184a7a32ce7f..cfc2848a19ef2f831c6562a89d5fd5ea7f938b22 100644
--- a/src/libs/routes/cub.js
+++ b/src/libs/routes/cub.js
@@ -81,11 +81,11 @@ rqf.addField({
         field: 'estado_id',
         table: 'cub'
     },
-    join: {
-        primary: 'id',
-        foreign: 'estado_id',
-        foreignTable: 'cub'
-    }
+    // join: {
+    //     primary: 'id',
+    //     foreign: 'estado_id',
+    //     foreignTable: 'cub'
+    // }
 }).addValue({
     name: 'min_year',
     table: 'cub',
@@ -132,6 +132,55 @@ rqf.addField({
     }
 });
 
+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) {
diff --git a/src/libs/routes/disciplines.js b/src/libs/routes/disciplines.js
index 2c5a9c968a71e1e54f025deee19a71c54978654a..63b05f327152d7deaa4122d05fbbc0f80355a5a4 100644
--- a/src/libs/routes/disciplines.js
+++ b/src/libs/routes/disciplines.js
@@ -162,12 +162,16 @@ disciplinesApp.get('/gender', (req, res, next) => {
 
 
 disciplinesApp.get('/contract_type', (req, res, next) => {
-    req.result = [
-        { id: 1, name: 'Concursado/Efetivo/Estável' },
-        { id: 2, name: 'Contrato temporário' },
-        { id: 3, name: 'Contrato terceirizado' },
-        { id: 4, name: 'Contrato CLT' }
-    ];
+    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'));
 
@@ -459,8 +463,12 @@ 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')
 
-        req.sql.field('SUM(quimica_not_null)', 'total_quimica')
+            .field('SUM(quimica_not_null)', 'total_quimica')
             .field('SUM(adequacao_quimica)', 'total_suitable_quimica')
 
             .field('SUM(fisica_not_null)', 'total_fisica')
@@ -523,9 +531,9 @@ disciplinesApp.get('/', rqf.parse(), (req, res, next) => {
             .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 \
-                etapas_mod_ensino_segmento_id <> 6 AND etapas_mod_ensino_segmento_id <> 12');
+            ((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']
@@ -555,7 +563,7 @@ disciplinesApp.get('/', rqf.parse(), (req, res, next) => {
             .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 \
-                etapas_mod_ensino_segmento_id <> 6 AND etapas_mod_ensino_segmento_id <> 12');
+                docente.etapas_mod_ensino_segmento_id <> 6 AND docente.etapas_mod_ensino_segmento_id <> 12');
     }
     else {
         req.sql.field('SUM(n_disc)', 'total')
@@ -567,41 +575,108 @@ disciplinesApp.get('/', rqf.parse(), (req, res, next) => {
             .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 \
-           etapas_mod_ensino_segmento_id <> 6 AND etapas_mod_ensino_segmento_id <> 12');
+            ((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 disciplinesNotSuitable = [];
-    let disciplinesSuitable = [];
-
-    req.result.forEach((r) => {
-        let objNotSuitable = {
-            total: parseInt(r.total) - parseInt(r.total_suitable),
-            suitable: 0
-        }
-
-        let objSuitable = {
-            total: parseInt(r.total_suitable),
-            suitable: 1
-        }
-        Object.keys(r).forEach(k => {
-            if (k !== 'total' && k !== 'total_suitable') {
-                objNotSuitable[k] = r[k];
-                objSuitable[k] = r[k];
+    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
             }
-        })
 
-        disciplinesNotSuitable.push(objNotSuitable)
-        disciplinesSuitable.push(objSuitable)
-    })
+	        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)
 
-    req.result = disciplinesNotSuitable.concat(disciplinesSuitable);
+	        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/educationalBudget.js b/src/libs/routes/educationalBudget.js
new file mode 100644
index 0000000000000000000000000000000000000000..30f6afc16ce86fe0c981b58b905b87b77d51cec1
--- /dev/null
+++ b/src/libs/routes/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/employees.js b/src/libs/routes/employees.js
index dba25468b284894ed2e9053eb784cd6a20b23754..e1b954aeec95765506ad407e9233a41931eee974 100644
--- a/src/libs/routes/employees.js
+++ b/src/libs/routes/employees.js
@@ -70,6 +70,24 @@ employeesApp.get('/source', (req, res, next) => {
     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) {
@@ -92,29 +110,6 @@ employeesApp.get('/adm_dependency', (req, res, next) => {
     next();
 }, response('adm_dependency'));
 
-employeesApp.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'));
-
-employeesApp.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'));
-
 employeesApp.get('/function', (req, res, next) => {
     req.result = [
         {id: 0, name: "Administrativos"},
@@ -253,6 +248,16 @@ rqfSchool.addField({
         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: '@',
@@ -423,6 +428,16 @@ rqfTeacher.addField({
         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: '@',
@@ -460,7 +475,6 @@ 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.
-    console.log(dims)
     let name = {
         qtde_admin: "Administrativos",
         qtde_servicos_gerais: "Serviços Gerais",
@@ -617,7 +631,7 @@ employeesApp.get('/', rqfSchool.parse(), (req, res, next) => {
     }
     next();
 
-}, rqfSchool.build(), query,  rqfSchool.parse(), id2str.transform(),  (req, res, 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);
diff --git a/src/libs/routes/enrollment.js b/src/libs/routes/enrollment.js
index b3310b30cbcdc0c9f4316dd1de1179936ba4bfa3..872593852ad783b18d3491405184d63132558872 100644
--- a/src/libs/routes/enrollment.js
+++ b/src/libs/routes/enrollment.js
@@ -19,6 +19,7 @@ along with simcaq-node.  If not, see <https://www.gnu.org/licenses/>.
 */
 
 const express = require('express');
+const { result } = require('lodash');
 
 const enrollmentApp = express.Router();
 
@@ -69,26 +70,22 @@ enrollmentApp.get('/source', (req, res, next) => {
 }, query, response('source'));
 
 enrollmentApp.get('/location', (req, res, next) => {
-    req.result = [];
-    for(let i = 1; i <= 2; ++i) {
-        req.result.push({
-            id: i,
-            name: id2str.location(i)
-        });
-    };
+    req.result = [
+        {id: 1, name: 'Urbana'},
+        {id: 2, name: 'Rural'}
+    ];
     next();
 }, response('location'));
 
-enrollmentApp.get('/rural_location', (req, res, next) => {
-    req.result = [];
-    for (let i = 1; i <= 8; i++) {
-        req.result.push({
-            id: i,
-            name: id2str.ruralLocation(i)
-        });
-    };
+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('rural_location'));
+}, response('diff_location'));
 
 // Returns all school years available
 enrollmentApp.get('/school_year', (req, res, next) => {
@@ -198,7 +195,7 @@ enrollmentApp.get('/gender', (req, res, next) => {
 // Return ethnic group
 enrollmentApp.get('/ethnic_group', (req, res, next) => {
     req.result = [];
-    for(let i = 1; i <=5; ++i) {
+    for(let i = 0; i <=5; ++i) {
         req.result.push({
             id: i,
             name: id2str.ethnicGroup(i)
@@ -224,11 +221,13 @@ enrollmentApp.get('/period', (req, res, next) => {
 
 // Returns integral-time avaible
 enrollmentApp.get('/integral_time', (req, res, next) => {
-    req.result = [
-        {id: null, name: 'Não Disponível'},
-        {id: 0, name: 'Não'},
-        {id: 1, name: 'Sim'}
-    ];
+    req.result = [];
+    for(let i = 0; i <= 2; ++i) {
+        req.result.push({
+            id: i,
+            name: id2str.integralTime(i)
+        });
+    }
     next();
 }, response('integral_time'));
 
@@ -241,6 +240,25 @@ enrollmentApp.get('/special_class', (req, res, next) => {
     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'},
@@ -498,6 +516,16 @@ rqf.addField({
         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',
@@ -565,7 +593,7 @@ rqf.addField({
   resultField: 'integral_time_id',
   where: {
       relation: '=',
-      type: 'boolean',
+      type: 'integer',
       field: 'tempo_integral'
   }
 }).addValue({
@@ -588,17 +616,233 @@ rqf.addField({
       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) => {
-    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))');
+    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();
-}, rqf.build(), query, id2str.transform(false), response('enrollment'));
+}, response('enrollment'));
 
 enrollmentApp.get('/diagnosis', rqf.parse(), (req, res, next) => {
     req.dims = {};
diff --git a/src/libs/routes/enrollmentProjection.js b/src/libs/routes/enrollmentProjection.js
index 5018440bbf565de9a9ed805ccc11921337ee0669..4dd92e5df7985a6bb34632dfc3b4a685c5873e64 100644
--- a/src/libs/routes/enrollmentProjection.js
+++ b/src/libs/routes/enrollmentProjection.js
@@ -59,7 +59,7 @@ rqf.addField({
     join: {
         primary: 'id',
         foreign: 'estado_id',
-        foreignTable: 'projecao_matricula'
+        foreignTable: 'projecao_matricula_por_dependencia'
     }
 }, 'dims').addValueToField({
     name: 'state',
@@ -74,7 +74,7 @@ rqf.addField({
     join: {
         primary: 'id',
         foreign: 'estado_id',
-        foreignTable: 'projecao_matricula'
+        foreignTable: 'projecao_matricula_por_dependencia'
     }
 }, 'filter').addValueToField({
     name: 'city',
@@ -89,7 +89,7 @@ rqf.addField({
     join: {
         primary: 'id',
         foreign: 'municipio_id',
-        foreignTable: 'projecao_matricula'
+        foreignTable: 'projecao_matricula_por_dependencia'
     }
 }, 'dims').addValueToField({
     name: 'city',
@@ -104,11 +104,11 @@ rqf.addField({
     join: {
         primary: 'id',
         foreign: 'municipio_id',
-        foreignTable: 'projecao_matricula'
+        foreignTable: 'projecao_matricula_por_dependencia'
     }
 }, 'filter').addValue({
     name: 'min_year',
-    table: 'projecao_matricula',
+    table: 'projecao_matricula_por_dependencia',
     tableField: 'ano_censo',
     resultField: 'year',
     where: {
@@ -118,7 +118,7 @@ rqf.addField({
     }
 }).addValue({
     name: 'max_year',
-    table: 'projecao_matricula',
+    table: 'projecao_matricula_por_dependencia',
     tableField: 'ano_censo',
     resultField: 'year',
     where: {
@@ -126,22 +126,32 @@ rqf.addField({
         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.urbano_dia_total)', 'urban_day_total')
-        .field('SUM(projecao_matricula.urbano_noite_total)', 'urban_night_total')
-        .field('SUM(projecao_matricula.rural_dia_total)', 'rural_day_total')
-        .field('SUM(projecao_matricula.rural_noite_total)', 'rural_night_total')
-        .field('projecao_matricula.etapa_ensino_escola_ano_id', 'education_level_school_year_id')
-        .field('projecao_matricula.ano_censo', 'year')
-        .from('projecao_matricula')
-        .where('projecao_matricula.etapa_ensino_escola_ano_id <> 7 AND projecao_matricula.etapa_ensino_escola_ano_id < 71')
-        .group('projecao_matricula.etapa_ensino_escola_ano_id')
-        .group('projecao_matricula.ano_censo')
-        .order('projecao_matricula.ano_censo')
-        .order('projecao_matricula.etapa_ensino_escola_ano_id');
+        .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) => {
diff --git a/src/libs/routes/financial.js b/src/libs/routes/financial.js
index bfe272058ce1d385bce3934b49a094140c496f1e..dab9dfe8f107ab4a16c94e8c2f7f3f2340baba21 100644
--- a/src/libs/routes/financial.js
+++ b/src/libs/routes/financial.js
@@ -181,6 +181,6 @@ financialApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
 	    .group('indicadores_financeiros.esfera_adm')
 		}
     next();
-}, query, addMissing(rqf), id2str.transform(), response('financial'));
+}, query, id2str.transform(), response('financial'));
 
 module.exports = financialApp;
diff --git a/src/libs/routes/mesoregion.js b/src/libs/routes/mesoregion.js
index 0feb76270835ba64e9c4a7adfed6bd8f8a676c09..001976f2f053e9226249fc1bfdda4d68f36916da 100644
--- a/src/libs/routes/mesoregion.js
+++ b/src/libs/routes/mesoregion.js
@@ -60,6 +60,15 @@ rqf.addField({
         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) => {
@@ -69,7 +78,8 @@ mesoregionApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
         .field('municipio.estado_id', 'state_id')
         .group('municipio.nome_mesorregiao')
         .group('municipio.mesorregiao_id')
-        .group('municipio.estado_id');
+        .group('municipio.estado_id')
+        .order('municipio.mesorregiao_id');
     next();
 }, query, response('mesoregion'));
 
diff --git a/src/libs/routes/message.js b/src/libs/routes/message.js
new file mode 100644
index 0000000000000000000000000000000000000000..f9e0e330a9aba1c098308ca4b4aaf67153c69aac
--- /dev/null
+++ b/src/libs/routes/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/microregion.js b/src/libs/routes/microregion.js
index 0b9b0e1a3f5f04b0a768283d7aaffa7b353aafc6..c4aba0fea760cbadeba7264e1f081436bc850634 100644
--- a/src/libs/routes/microregion.js
+++ b/src/libs/routes/microregion.js
@@ -60,6 +60,24 @@ rqf.addField({
         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) => {
@@ -73,7 +91,8 @@ microregionApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
         .group('municipio.microrregiao_id')
         .group('municipio.nome_mesorregiao')
         .group('municipio.mesorregiao_id')
-        .group('municipio.estado_id');
+        .group('municipio.estado_id')
+        .order('municipio.microrregiao_id');
     next();
 }, query, response('microregion'));
 
diff --git a/src/libs/routes/region.js b/src/libs/routes/region.js
index b1076e6484836b8a4911b8d0ada3631f1304e3c0..5df65e726e1895f256f276ce22a32b1c7cc41712 100644
--- a/src/libs/routes/region.js
+++ b/src/libs/routes/region.js
@@ -36,6 +36,16 @@ rqf.addField({
         field: 'id',
         table: '@'
     }
+}).addValue({
+    name: 'id_not',
+    table: '@',
+    tableField: 'id',
+    where: {
+        relation: '<>',
+        type: 'integer',
+        field: 'id',
+        table: '@'
+    }
 }).addField({
     name: 'search',
     field: false,
diff --git a/src/libs/routes/school.js b/src/libs/routes/school.js
index b72df7c78071c3c379abd7fec621c835f95e6586..73b765e210544787944540532ae56489617c6593 100644
--- a/src/libs/routes/school.js
+++ b/src/libs/routes/school.js
@@ -58,20 +58,19 @@ schoolApp.get('/location', cache('15 day'), (req, res, next) => {
     next();
 }, response('location'));
 
-schoolApp.get('/rural_location', cache('15 day'), (req, res, next) => {
+schoolApp.get('/diff_location', cache('15 day'), (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"}
+        {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('rural_location'));
+}, response('diff_location'));
 
 schoolApp.get('/adm_dependency', (req, res, next) => {
     req.result = [];
+
     for(let i = 1; i <= 4; ++i) {
         req.result.push({
             id: i,
@@ -83,7 +82,7 @@ schoolApp.get('/adm_dependency', (req, res, next) => {
 
 schoolApp.get('/adm_dependency_detailed', cache('15 day'), (req, res, next) => {
     req.result = [];
-    for(let i = 1; i <= 6; ++i) {
+    for(let i = 1; i <= 8; i++) {
         req.result.push({
             id: i,
             name: id2str.admDependencyPriv(i)
@@ -93,11 +92,14 @@ schoolApp.get('/adm_dependency_detailed', cache('15 day'), (req, res, next) => {
 }, response('adm_dependency_detailed'));
 
 schoolApp.get('/government_agreement', cache('15 day'), (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.governmentAgreement("null")
+    }];
     for(let i = 1; i <= 6; ++i) {
         req.result.push({
             id: i,
-            name: id2str.govermentAgreement(i)
+            name: id2str.governmentAgreement(i)
         });
     };
     next();
@@ -192,11 +194,13 @@ schoolApp.get('/arrangement', cache('15 day'), (req, res, next) => {
 }, response('arrangement'));
 
 schoolApp.get('/integral_time', cache('15 day'), (req, res, next) => {
-    req.result = [
-        {id: 0, name: 'Não'},
-        {id: 1, name: 'Sim'},
-        {id: 2, name: 'Não se aplica - Semipresencial e EaD.'}
-    ];
+    req.result = [];
+    for(let i = 0; i <= 2; ++i) {
+        req.result.push({
+            id: i,
+            name: id2str.integralTime(i)
+        });
+    }
     next();
 }, response('integral_time'));
 
@@ -294,7 +298,17 @@ rqf.addField({
       foreign: 'estado_id',
       foreignTable: 'escola'
     }
-}, 'search');
+}, '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',
@@ -429,6 +443,16 @@ rqfCount.addField({
         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',
@@ -476,8 +500,8 @@ rqfCount.addField({
     resultField: 'government_agreement_id',
     where: {
         relation: '=',
-        type: 'boolean',
-        field: 'conveniada_pp'
+        type: 'integer',
+        field: 'dependencia_convenio_publico'
     }
 }).addValue({
     name: 'integral_time',
@@ -612,7 +636,6 @@ schoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
 }, query, response('school'));
 
 schoolApp.get('/count', cache('15 day'), rqfCount.parse(), (req, res, next) => {
-	console.log(req.filter);
 	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')
diff --git a/src/libs/routes/state.js b/src/libs/routes/state.js
index 453ca6ebbe30aa330fc1e8949cc8db4ae1bf7bb7..c9830b20a52b2997ab96f020c893a00e10d4c3df 100644
--- a/src/libs/routes/state.js
+++ b/src/libs/routes/state.js
@@ -53,6 +53,15 @@ rqf.addField({
         type: 'integer',
         field: 'id'
     }
+}).addValue({
+    name: 'id_not',
+    table: 'estado',
+    tableField: 'id',
+    where: {
+        relation: '<>',
+        type: 'integer',
+        field: 'id'
+    }
 }).addValue({
     name: 'region',
     table: 'regiao',
diff --git a/src/libs/routes/studentsAee.js b/src/libs/routes/studentsAee.js
new file mode 100644
index 0000000000000000000000000000000000000000..2a45a2f5f038407b2fe6b9dbb4b44c504ce4e77e
--- /dev/null
+++ b/src/libs/routes/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/teacher.js b/src/libs/routes/teacher.js
index b2a4dc4ea23b1bac3d9085badf2c1676bb0bafae..94e6d86c60933d906b9f0f8264ebfd14da5534c4 100644
--- a/src/libs/routes/teacher.js
+++ b/src/libs/routes/teacher.js
@@ -67,6 +67,24 @@ teacherApp.get('/source', (req, res, next) => {
     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) {
@@ -118,28 +136,6 @@ teacherApp.get('/education_level_short', (req, res, next) => {
     next();
 }, response('education_level_short'));
 
-teacherApp.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'));
-
-teacherApp.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'));
-
 teacherApp.get('/education_type', (req, res, next) => {
     req.sql.from('docente')
     .field('DISTINCT nivel_tipo_formacao', 'id')
@@ -162,12 +158,16 @@ teacherApp.get('/gender', (req, res, next) => {
 
 
 teacherApp.get('/contract_type', (req, res, next) => {
-    req.result = [
-        {id: 1, name: 'Concursado/Efetivo/Estável'},
-        {id: 2, name: 'Contrato temporário'},
-        {id: 3, name: 'Contrato terceirizado'},
-        {id: 4, name: 'Contrato CLT'}
-    ];
+    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'));
 
@@ -184,7 +184,7 @@ teacherApp.get('/ethnic_group', (req, res, next) => {
 
 teacherApp.get('/initial_training', (req, res, next) => {
     req.result = [];
-    for(let i = 1; i <=4; ++i) {
+    for(let i = 1; i <=5; ++i) {
         req.result.push({
             id: i,
             name: id2str.initialTraining(i)
@@ -204,6 +204,17 @@ teacherApp.get('/pos_training', (req, res, next) => {
   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,
@@ -404,6 +415,16 @@ rqf.addField({
         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',
@@ -474,8 +495,31 @@ rqf.addField({
         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')
@@ -487,7 +531,7 @@ teacherApp.get('/', rqf.parse(), (req, res, next) => {
     .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)');     // não devemos trazer SC em 2009.
+        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;
@@ -495,6 +539,38 @@ teacherApp.get('/', rqf.parse(), (req, res, next) => {
     // }
 
     next();
-}, rqf.build(), query, addMissing(rqf), id2str.transform(), response('teacher'));
+}, 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/transport.js b/src/libs/routes/transport.js
index afe7049a624c043b052ed650f59056962c6cd5ff..74c1b0954a8cb71cb5e5fd275cdb82143c4dc944 100644
--- a/src/libs/routes/transport.js
+++ b/src/libs/routes/transport.js
@@ -322,7 +322,6 @@ transportApp.get('/', rqf.parse(), (req, res, next) => {
     next();
 }, rqf.build(), query, id2str.transform(), (req, res, next) => {
     req.total = req.result;
-    console.log('here');
     req.resetSql();
     next();
 }, rqf.parse(), (req, res, next) => {
@@ -335,7 +334,6 @@ transportApp.get('/', rqf.parse(), (req, res, next) => {
     next();
 }, rqf.build(), query, id2str.transform(), (req, res, next) => {
     req.public_total = req.result;
-    console.log('here');
     req.resetSql();
     next();
 
diff --git a/src/libs/routes/universityEnrollment.js b/src/libs/routes/universityEnrollment.js
index d1670f7c0d6994a94e389bb99b4a393e4219f203..3a1d6e4776004cbeaac79d95c622e694d3dd4e12 100644
--- a/src/libs/routes/universityEnrollment.js
+++ b/src/libs/routes/universityEnrollment.js
@@ -93,10 +93,13 @@ universityEnrollmentApp.get('/ocde_geral', (req, res, next) => {
 
 
 universityEnrollmentApp.get('/finish', (req, res, next) => {
-    req.result = [
-        {id: 0, name: "Não"},
-        {id: 1, name: "Sim"},
-    ];
+    req.result = []
+    for (let i = 0; i <= 1; ++i){
+        req.result.push({
+            id: i,
+            name: id2str.finishUniversity(i)
+        })
+    }
     next();
 
 }, response('finish'));
@@ -189,7 +192,10 @@ universityEnrollmentApp.get('/cine_detailed', (req, res, next) => {
 }, response('cine_detailed'));
 
 universityEnrollmentApp.get('/upper_turn', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.upperTurn("null")
+    }];
     for(let i = 1; i <= 4; ++i) {
         req.result.push({
             id: i,
@@ -200,7 +206,10 @@ universityEnrollmentApp.get('/upper_turn', (req, res, next) => {
 }, response('upper_turn'));
 
 universityEnrollmentApp.get('/student_deficiency', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: 9,
+        name: id2str.studentDeficiency(9)
+    }];
     for(let i = 0; i <= 1; ++i) {
         req.result.push({
             id: i,
@@ -211,8 +220,11 @@ universityEnrollmentApp.get('/student_deficiency', (req, res, next) => {
 }, response('student_deficiency'));
 
 universityEnrollmentApp.get('/ethnic_group_ies', (req, res, next) => {
-    req.result = [];
-    for(let i = 1; i <=5; ++i) {
+    req.result = [{
+        id: 9,
+        name: id2str.ethnicGroupIES(9)
+    }];
+    for(let i = 0; i <=5; ++i) {
         req.result.push({
             id: i,
             name: id2str.ethnicGroupIES(i)
@@ -222,7 +234,10 @@ universityEnrollmentApp.get('/ethnic_group_ies', (req, res, next) => {
 }, response('ethnic_group_ies'));
 
 universityEnrollmentApp.get('/school_type', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: 9,
+        name: id2str.schoolType(9)
+    }];
     for(let i = 1; i <= 2; ++i) {
         req.result.push({
             id: i,
@@ -283,6 +298,41 @@ universityEnrollmentApp.get('/age_student_code', function (req, res, next) {
     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')
@@ -363,6 +413,16 @@ rqf.addField({
         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: '@',
@@ -406,8 +466,8 @@ rqf.addField({
 }).addValue({
     name:'ocde_specific',
     table: '@',
-    tableField: ['par_cod_ocde_area_especifica', 'nome_ocde_area_especifica'],
-    resultField: ['ocde_specific_id', 'ocde_specific_name'],
+    tableField: ['par_cod_ocde_area_especifica'],
+    resultField: ['ocde_specific_id'],
     where: {
         relation: '=',
         type: 'integer',
@@ -416,8 +476,8 @@ rqf.addField({
 }).addValue({
     name:'ocde_geral',
     table: '@',
-    tableField: ['par_cod_ocde_area_geral', 'nome_ocde_area_geral'],
-    resultField: ['ocde_geral_id', 'ocde_geral_name'],
+    tableField: ['par_cod_ocde_area_geral'],
+    resultField: ['ocde_geral_id'],
     where: {
         relation: '=',
         type: 'integer',
@@ -426,8 +486,8 @@ rqf.addField({
 }).addValue({
     name:'ocde_detailed',
     table: '@',
-    tableField: ['par_cod_ocde_area_detalhada', 'nome_ocde_area_detalhada'],
-    resultField: ['ocde_detailed_id', 'ocde_detailed_name'],
+    tableField: ['par_cod_ocde_area_detalhada'],
+    resultField: ['ocde_detailed_id'],
     where: {
         relation: '=',
         type: 'integer',
@@ -647,6 +707,22 @@ rqf.addField({
         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) => {
@@ -683,8 +759,6 @@ universityEnrollmentApp.get('/', rqf.parse(), (req, res, next) => {
         .field('COUNT(*)', 'total')
         .field("'Brasil'", 'name')
         .field('aluno_ens_superior.ano_censo', 'year')
-        .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')
         .group('aluno_ens_superior.cod_ies')
         .group('aluno_ens_superior.ano_censo')
         .order('aluno_ens_superior.cod_ies')
@@ -698,6 +772,65 @@ universityEnrollmentApp.get('/', rqf.parse(), (req, res, next) => {
         .order('localoferta_ens_superior_matricula.ano_censo')
     }
     next();
-}, rqf.build(), query, id2str.transform(), addMissing(rqf), response('universityEnrollment'));
+}, 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_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_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/universityLocalOffer.js b/src/libs/routes/universityLocalOffer.js
index 4a594f62d7c132dd875a7f334df8b5728905a25b..535094c492915b6b3d38a5e02a267a4196910c36 100644
--- a/src/libs/routes/universityLocalOffer.js
+++ b/src/libs/routes/universityLocalOffer.js
@@ -126,13 +126,38 @@ rqf.addField({
         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')
diff --git a/src/libs/routes/universityTeacher.js b/src/libs/routes/universityTeacher.js
index 42851c2b85c9dbdd1ec69da7983f2306597dca29..f65a29b2e7ce54a9b374873352a744809fc0a4f0 100644
--- a/src/libs/routes/universityTeacher.js
+++ b/src/libs/routes/universityTeacher.js
@@ -91,7 +91,10 @@ teacherEnrollmentApp.get('/teacher_situation', (req, res, next) => {
 }, response('teacher_situation'));
 
 teacherEnrollmentApp.get('/work_regime', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.workRegime("null")
+    }];
     for(let i = 1; i <= 4; ++i) {
         req.result.push({
             id: i,
@@ -102,7 +105,10 @@ teacherEnrollmentApp.get('/work_regime', (req, res, next) => {
 }, response('work_regime'));
 
 teacherEnrollmentApp.get('/substitute', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.booleanVariable("null")
+    }];
     for(let i = 0; i <= 1; ++i) {
         req.result.push({
             id: i,
@@ -113,7 +119,10 @@ teacherEnrollmentApp.get('/substitute', (req, res, next) => {
 }, response('substitute'));
 
 teacherEnrollmentApp.get('/visitor', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.booleanVariable("null")
+    }];
     for(let i = 0; i <= 1; ++i) {
         req.result.push({
             id: i,
@@ -124,7 +133,10 @@ teacherEnrollmentApp.get('/visitor', (req, res, next) => {
 }, response('visitor'));
 
 teacherEnrollmentApp.get('/ead_teacher', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.booleanVariable("null")
+    }];
     for(let i = 0; i <= 1; ++i) {
         req.result.push({
             id: i,
@@ -135,7 +147,10 @@ teacherEnrollmentApp.get('/ead_teacher', (req, res, next) => {
 }, response('ead_teacher'));
 
 teacherEnrollmentApp.get('/graduation_presential', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.booleanVariable("null")
+    }];
     for(let i = 0; i <= 1; ++i) {
         req.result.push({
             id: i,
@@ -146,7 +161,10 @@ teacherEnrollmentApp.get('/graduation_presential', (req, res, next) => {
 }, response('graduation_presential'));
 
 teacherEnrollmentApp.get('/postgraduate_ead_teacher', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.booleanVariable("null")
+    }];
     for(let i = 0; i <= 1; ++i) {
         req.result.push({
             id: i,
@@ -157,7 +175,10 @@ teacherEnrollmentApp.get('/postgraduate_ead_teacher', (req, res, next) => {
 }, response('postgraduate_ead_teacher'));
 
 teacherEnrollmentApp.get('/postgraduate_presential_teacher', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: "null",
+        name: id2str.booleanVariable("null")
+    }];
     for(let i = 0; i <= 1; ++i) {
         req.result.push({
             id: i,
@@ -168,18 +189,24 @@ teacherEnrollmentApp.get('/postgraduate_presential_teacher', (req, res, next) =>
 }, response('postgraduate_presential_teacher'));
 
 teacherEnrollmentApp.get('/deficiency', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: 9,
+        name: id2str.studentDeficiency(9)
+    }];
     for(let i = 0; i <= 1; ++i) {
         req.result.push({
             id: i,
-            name: id2str.booleanVariable(i)
+            name: id2str.studentDeficiency(i)
         });
     };
     next();
 }, response('deficiency'));
 
 teacherEnrollmentApp.get('/ethnic_group_teacher_ies', (req, res, next) => {
-    req.result = [];
+    req.result = [{
+        id: 9,
+        name: id2str.ethnicGroupTeacherIES(9)
+    }];
     for(let i = 0; i <= 5; ++i) {
         req.result.push({
             id: i,
@@ -368,7 +395,7 @@ rqf.addField({
     resultField: 'substitute_id',
     where: {
         relation: '=',
-        type: 'integer',
+        type: 'boolean',
         field: 'docente_substituto'
     }
 }).addValue({
@@ -378,7 +405,7 @@ rqf.addField({
     resultField: 'visitor_id',
     where: {
         relation: '=',
-        type: 'integer',
+        type: 'boolean',
         field: 'docente_visitante'
     }
 }).addValue({
@@ -388,7 +415,7 @@ rqf.addField({
     resultField: 'ead_teacher_id',
     where: {
         relation: '=',
-        type: 'integer',
+        type: 'boolean',
         field: 'ministra_aula_ead'
     }
 }).addValue({
@@ -398,7 +425,7 @@ rqf.addField({
     resultField: 'graduation_presential_id',
     where: {
         relation: '=',
-        type: 'integer',
+        type: 'boolean',
         field: 'atua_atividade_graduacao_presencial'
     }
 }).addValue({
@@ -408,7 +435,7 @@ rqf.addField({
     resultField: 'postgraduate_ead_teacher_id',
     where: {
         relation: '=',
-        type: 'integer',
+        type: 'boolean',
         field: 'atua_atividade_posgraduacao_distancia'
     }
 }).addValue({
@@ -418,7 +445,7 @@ rqf.addField({
     resultField: 'postgraduate_presential_teacher_id',
     where: {
         relation: '=',
-        type: 'integer',
+        type: 'boolean',
         field: 'atua_atividade_posgraduacao_presencial'
     }
 }).addValue({
diff --git a/src/libs/routes/user.js b/src/libs/routes/user.js
index d7ef04e5a94779f9ad377f9494e4467f5660592a..7ff088eea62f34ffd3b66de4a28ae42807a97e8d 100644
--- a/src/libs/routes/user.js
+++ b/src/libs/routes/user.js
@@ -195,8 +195,6 @@ userApp.post('/', (req, res, next) => {
 });
 
 userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => {
-  console.log(req.params.id);
-  console.log(req.user._id);
   User.findById(req.params.id, (err, user) => {
     if (err) {
       log.error(err);
@@ -210,8 +208,6 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, r
       }});
     }
 
-    console.log(req.body);
-
     user.email = req.body.email || user.email;
     user.name = req.body.name || user.name;
     user.nickname = req.body.nickname || user.nickname || user.name;
@@ -230,7 +226,6 @@ userApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, r
     user.citesegment = req.body.citesegment || user.citesegment;
     user.citerole = req.body.citerole || user.citerole;
 
-    // console.log(user.checkPassword(req.body.password));
     if ((req.body.password) && (req.body.newpassword)) {
         if (req.body.password != req.body.newpassword) {
             if (user.checkPassword(req.body.password)) {