diff --git a/src/libs/app.js b/src/libs/app.js
index 8be3a95b9a3e78f9ce54093196facfed9f0223c1..1184e1e026ac6d17e79a90e975d273f1a700f918 100644
--- a/src/libs/app.js
+++ b/src/libs/app.js
@@ -44,6 +44,18 @@ app.use((req, res, next) => {
         };
     };
     req.resetSql();
+
+    req.sql.oldClone = req.sql.clone;
+    req.sql.clone = () => {
+        let cloned = req.sql.oldClone();
+        cloned.oldFrom = cloned.from;
+        cloned.from = (name, alias = null) => {
+            cloned.oldFrom(name, alias || null);
+            cloned.tableFrom = name;
+            return cloned;
+        };
+        return cloned;
+    };
     next();
 });
 app.use(passport.initialize());
diff --git a/src/libs/convert/contractType.js b/src/libs/convert/contractType.js
new file mode 100644
index 0000000000000000000000000000000000000000..6c9167ce6e3758feb8de1d20c7a3b228be1e4f17
--- /dev/null
+++ b/src/libs/convert/contractType.js
@@ -0,0 +1,14 @@
+module.exports = function idhmLevel(id) {
+    switch (id) {
+        case 1:
+        return 'Concursado/Efetivo/Estavél';
+        case 2:
+        return 'Contrato temporário';
+        case 3:
+        return 'Contrato terceirizado';
+        case 4:
+        return 'Contrato CLT';
+        default:
+        return 'Não classificado';
+    }
+};
diff --git a/src/libs/db/query_exec.js b/src/libs/db/query_exec.js
index c43b1dbee3640a71e1957db722e6eab84e1d8533..691117c5672df92ed565c2d4db5e27937b34dfbf 100644
--- a/src/libs/db/query_exec.js
+++ b/src/libs/db/query_exec.js
@@ -40,4 +40,10 @@ function execSqlQuery(sqlQuery, sqlQueryParams = []) {
     });
 }
 
-module.exports = execSqlQuery;
+function execMultiQuery(querySet = []) {
+    // Issue all queries concurrently to the database, for every query object in the iterable
+    // NOTE: Array.map() returns a copy of the original array with each object 'mapped'.
+    return querySet.map((qry) => { return execSqlQuery(qry.toString()); });
+}
+
+module.exports = {execSqlQuery, execMultiQuery};
diff --git a/src/libs/middlewares/id2str.js b/src/libs/middlewares/id2str.js
index 833c160bea187efc150f3f91a2a41b1a0b6fe58a..e37e854e67c6ae1e52affba7c381ddb3a804bd05 100644
--- a/src/libs/middlewares/id2str.js
+++ b/src/libs/middlewares/id2str.js
@@ -17,6 +17,7 @@ const citySize = require(`${libs}/convert/citySize`);
 const incomeLevel = require(`${libs}/convert/incomeLevel`);
 const idhmLevel = require(`${libs}/convert/idhmLevel`);
 const stateName = require(`${libs}/convert/stateName`);
+const contractType = require(`${libs}/convert/contractType`);
 
 const ids = {
     gender_id: gender,
@@ -29,6 +30,7 @@ const ids = {
     adm_dependency_detailed_id: admDependencyPriv,
     location_id: location,
     rural_location_id: ruralLocation,
+    location_detailed_id: ruralLocation,
     ethnic_group_id: ethnicGroup,
     agreement_id: agreement,
     integral_time_id: booleanVariable,
@@ -44,7 +46,8 @@ const ids = {
     income_level_id: incomeLevel,
     city_size_id: citySize,
     idhm_level_id: idhmLevel,
-    state_id: stateName
+    state_id: stateName,
+    contract_type_id: contractType
 };
 
 function transform(removeId=false) {
@@ -63,8 +66,25 @@ function transform(removeId=false) {
     };
 }
 
+function multitransform(removeId=false) {
+    return (req, res, next) => {
+        Object.keys(req.result[0]).forEach((query) => {
+            req.result[0][query].forEach((obj) => {
+                Object.keys(obj).forEach((key) => {
+                    if(typeof ids[key] === 'undefined') return;
+                    let id = obj[key];
+                    obj[key.replace('_id', '_name')] = ids[key](id);
+                    if(removeId) delete obj[key];
+                });
+            })
+        });
+        next();
+    }
+}
+
 module.exports = {
     transform,
+    multitransform,
     gender,
     period,
     schoolYear,
@@ -82,5 +102,6 @@ module.exports = {
     incomeLevel,
     citySize,
     idhmLevel,
-    stateName
+    stateName,
+    contractType
 };
diff --git a/src/libs/middlewares/multiQuery.js b/src/libs/middlewares/multiQuery.js
new file mode 100644
index 0000000000000000000000000000000000000000..7bf37c5d9086f3a97405ef2bfbb61553afd0d2bf
--- /dev/null
+++ b/src/libs/middlewares/multiQuery.js
@@ -0,0 +1,16 @@
+const libs = `${process.cwd()}/libs`;
+const log = require(`${libs}/log`)(module);
+const db = require(`${libs}/db/query_exec`);
+
+// Middleware that executes multiples queries 
+function multiQuery(req, res, next) {
+    Promise.all(db.execMultiQuery(req.querySet)).then((queryResults) => {
+        req.result = queryResults;
+        next();
+    }).catch((err) => {
+        log.error(`[SQL query error] ${err}`);
+        next(err);
+    });
+}
+
+module.exports = multiQuery;
diff --git a/src/libs/middlewares/query.js b/src/libs/middlewares/query.js
index 6d4c2537759c5676b720db336eec07981e6efb56..ae002df2fb13727152497dc9ad61c1371d98d194 100644
--- a/src/libs/middlewares/query.js
+++ b/src/libs/middlewares/query.js
@@ -1,6 +1,6 @@
 const libs = `${process.cwd()}/libs`;
 const log = require(`${libs}/log`)(module);
-const execQuery = require(`${libs}/db/query_exec`);
+const db = require(`${libs}/db/query_exec`);
 
  // Middleware that executes a query defined by a squel object in req.sql
 function query(req, res, next) {
@@ -18,10 +18,11 @@ function query(req, res, next) {
 }
 
 function execute(text, values, cb) {
-    execQuery(text, values).then((result) => {
+    db.execSqlQuery(text, values).then((result) => {
         cb(null, result);
     }, (error) => {
-        cb(error);
+        log.error(error.stack);
+        cb(new Error('Request could not be satisfied due to a database error.'));
     });
 }
 
diff --git a/src/libs/middlewares/reqQueryFields.js b/src/libs/middlewares/reqQueryFields.js
index c821852b423fb9d9d41d60a579e3b064b88ab427..993aae5bd282199b33d5ff8228cd90dcaf8c275c 100644
--- a/src/libs/middlewares/reqQueryFields.js
+++ b/src/libs/middlewares/reqQueryFields.js
@@ -192,126 +192,142 @@ class ReqQueryFields {
         };
     }
 
-    build() {
+    buildQuery(req, sql) {
         // "Constrói" o SQL
-        return (req, res, next) => {
-            let hasJoined = {};
-            let thisTable = req.sql.tableFrom;
-            // Foreach no campos
-            Object.keys(this.fields).forEach((key) => {
-                // Campo
-                let field = this.fields[key];
-                log.debug(field);
-                // `param` aqui é o atributo no objeto `req` (dims, filter, search, ...)
-                let param = req[field.name];
-                // Fazemos um foreach nos parametros dentro do atributo
-                Object.keys(param).forEach((k) => {
-                    let values = _.merge(this.fieldValues, field.values);
-                    if(typeof values[k] !== 'undefined') {
-                        // Clonamos para não alterar o original
-                        let value = _.clone(values[k]);
-                        if(value.parseOnly) return;
-                        // Checa se não fizemos o join para este valor e se é necessário fazer
-                        if(!hasJoined[value.table] && typeof value.join !== 'undefined') {
-                            let foreignTable = '';
-                            if(value.join.foreignTable) foreignTable = value.join.foreignTable+'.';
-                            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;
-                            }
-                            req.sql.join(value.table, null, onClause);
-                            // Marcamos o join como feito para não ter problemas
-                            hasJoined[value.table] = true;
+        let hasJoined = {};
+        let thisTable = sql.tableFrom;
+        // Foreach no campos
+        Object.keys(this.fields).forEach((key) => {
+            // Campo
+            let field = this.fields[key];
+            log.debug(field);
+            // `param` aqui é o atributo no objeto `req` (dims, filter, search, ...)
+            let param = req[field.name];
+            // Fazemos um foreach nos parametros dentro do atributo
+            Object.keys(param).forEach((k) => {
+                let values = _.merge(this.fieldValues, field.values);
+                if(typeof values[k] !== 'undefined') {
+                    // Clonamos para não alterar o original
+                    let value = _.clone(values[k]);
+                    if(value.parseOnly) return;
+                    // Checa se não fizemos o join para este valor e se é necessário fazer
+                    if(!hasJoined[value.table] && typeof value.join !== 'undefined') {
+                        let foreignTable = '';
+                        if(value.join.foreignTable) foreignTable = value.join.foreignTable+'.';
+                        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;
                         }
-                        // Se o valor é um campo a ser incluído no SELECT
-                        if(typeof field.field !== 'undefined' && field.field) {
-                            log.debug('SELECT');
-                            let table = value.table;
-                            if(table === '@') table = thisTable;
-                            if (Array.isArray(value.resultField)) {
-                                value.tableField.forEach((f, i) => {
-                                    req.sql.field(table+'.'+f, value.resultField[i] || f)
-                                        .group(table+'.'+f)
-                                        .order(table+'.'+f);
-                                })
-                            }else{
-                                req.sql.field(table+'.'+value.tableField, value.resultField || value.tableField)
-                                    .order(table+'.'+value.tableField)
-                                    .group(table+'.'+value.tableField);
-                            }
+                        sql.join(value.table, null, onClause);
+                        // Marcamos o join como feito para não ter problemas
+                        hasJoined[value.table] = true;
+                    }
+                    // Se o valor é um campo a ser incluído no SELECT
+                    if(typeof field.field !== 'undefined' && field.field) {
+                        log.debug('SELECT');
+                        let table = value.table;
+                        if(table === '@') table = thisTable;
+                        if (Array.isArray(value.resultField)) {
+                            value.tableField.forEach((f, i) => {
+                                sql.field(table+'.'+f, value.resultField[i] || f)
+                                    .group(table+'.'+f)
+                                    .order(table+'.'+f);
+                            })
+                        }else{
+                            sql.field(table+'.'+value.tableField, value.resultField || value.tableField)
+                                .order(table+'.'+value.tableField)
+                                .group(table+'.'+value.tableField);
                         }
-                        // Se o valor é um campo para ser usado no WHERE
-                        if(typeof field.where !== 'undefined' && field.where) {
-                            log.debug('WHERE');
-                            // Valor do where
-
-                            let whereValue = param[k];
-                            log.debug('whereValue');
-                            log.debug(whereValue);
-                            log.debug(`Where value é array? ${Array.isArray(whereValue)}`);
+                    }
+                    // Se o valor é um campo para ser usado no WHERE
+                    if(typeof field.where !== 'undefined' && field.where) {
+                        log.debug('WHERE');
+                        // Valor do where
 
-                            let tbl = value.where.table || value.table;
-                            if (tbl === '@') tbl = thisTable;
-                            // multiple where
-                            if (Array.isArray(value.where.field)) {
-                                let lower = (value.where.type === 'string') ? ' LOWER(?) ' : ' ? ';
-                                let whereField = '';
-                                let whereValues = [];
-                                value.where.field.forEach((f, i, arr) => {
-                                    whereField += (value.where.type === 'string') ? 'LOWER(' + tbl + '.' + value.where.field[i] + ')' : tbl + '.' + value.where.field[i];
-                                    whereField += ' ' + value.where.relation + ' ?';
-                                    if (i < arr.length - 1) {
-                                        whereField += ' ' + value.where.condition + ' ';
-                                    }
+                        let whereValue = param[k];
+                        log.debug('whereValue');
+                        log.debug(whereValue);
+                        log.debug(`Where value é array? ${Array.isArray(whereValue)}`);
 
-                                    if (Array.isArray(whereValue)) {
-                                        let whereString = '(';
-                                        for(let i = 0; i < whereValue.length; ++i) {
-                                            whereString += whereField;
-                                            whereValues.push(parseWhereValue(value.where.type, whereValue[i]));
-                                            if(i < whereValue.length-1) {
-                                                whereString += ' OR ';
-                                            }
-                                        }
-                                        whereString += ')';
-                                    } else {
-                                        whereValues.push(parseWhereValue(value.where.type, whereValue));
-                                    }
-                                });
+                        let tbl = value.where.table || value.table;
+                        if (tbl === '@') tbl = thisTable;
+                        // multiple where
+                        if (Array.isArray(value.where.field)) {
+                            let lower = (value.where.type === 'string') ? ' LOWER(?) ' : ' ? ';
+                            let whereField = '';
+                            let whereValues = [];
+                            value.where.field.forEach((f, i, arr) => {
+                                whereField += (value.where.type === 'string') ? 'LOWER(' + tbl + '.' + value.where.field[i] + ')' : tbl + '.' + value.where.field[i];
+                                whereField += ' ' + value.where.relation + ' ?';
+                                if (i < arr.length - 1) {
+                                    whereField += ' ' + value.where.condition + ' ';
+                                }
 
-                                req.sql.where(whereField, ...whereValues);
-                            } else {
-                                let whereField = (value.where.type === 'string') ? 'LOWER(' + tbl + '.' + value.where.field + ')' : tbl + '.' + value.where.field;
-                                let lower = (value.where.type === 'string') ? ' LOWER(?) ' : ' ? ';
-                                if(Array.isArray(whereValue)) {
+                                if (Array.isArray(whereValue)) {
                                     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]));
+                                        whereString += whereField;
+                                        whereValues.push(parseWhereValue(value.where.type, whereValue[i]));
                                         if(i < whereValue.length-1) {
                                             whereString += ' OR ';
                                         }
                                     }
                                     whereString += ')';
-                                    req.sql.where(whereString, ...arrayWhereValues);
                                 } else {
-                                    req.sql.where(whereField + ' ' + value.where.relation + lower, parseWhereValue(value.where.type, whereValue));
+                                    whereValues.push(parseWhereValue(value.where.type, whereValue));
                                 }
+                            });
+
+                            sql.where(whereField, ...whereValues);
+                        } else {
+                            let whereField = (value.where.type === 'string') ? 'LOWER(' + tbl + '.' + value.where.field + ')' : tbl + '.' + value.where.field;
+                            let lower = (value.where.type === 'string') ? ' LOWER(?) ' : ' ? ';
+                            if(Array.isArray(whereValue)) {
+                                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]));
+                                    if(i < whereValue.length-1) {
+                                        whereString += ' OR ';
+                                    }
+                                }
+                                whereString += ')';
+                                sql.where(whereString, ...arrayWhereValues);
+                            } else {
+                                sql.where(whereField + ' ' + value.where.relation + lower, parseWhereValue(value.where.type, whereValue));
                             }
                         }
                     }
-                });
+                }
+            });
+        });
+        return sql;
+    }
+
+    build() {
+        return (req, res, next) => {
+            req.sql = this.buildQuery(req, req.sql);
+            next();
+        };
+    }
+
+    multibuild() {
+        return (req, res, next) => {
+            req.querySet.forEach((query) => {
+                console.log("query");
+                console.log(query.tableFrom);
+                query = this.buildQuery(req, query);
             });
             next();
         };
diff --git a/src/libs/models/pqr.js b/src/libs/models/pqr.js
new file mode 100644
index 0000000000000000000000000000000000000000..f92703188323cef17807f70f1f2198b54a13aa1b
--- /dev/null
+++ b/src/libs/models/pqr.js
@@ -0,0 +1,16 @@
+const mongoose = require('mongoose')
+
+const libs = `${process.cwd()}/libs`;
+const log = require(`${libs}/log`)(module);
+const User = require(`${libs}/models/user`);
+
+const Schema = mongoose.Schema;
+
+let PQRSchema = new Schema({
+    content: {
+        type: String,
+        required: true,
+    }
+});
+
+module.exports = mongoose.model('PQR', PQRSchema);
diff --git a/src/libs/models/simulation.js b/src/libs/models/simulation.js
index e70c93a9f88dea76d017744b15f3b3fe61b5ca21..8cbbd3a599bf78d6b41082445a4d44ac0d1db890 100644
--- a/src/libs/models/simulation.js
+++ b/src/libs/models/simulation.js
@@ -2,114 +2,20 @@ const mongoose = require('mongoose')
 
 const libs = `${process.cwd()}/libs`;
 const log = require(`${libs}/log`)(module);
+const User = require(`${libs}/models/user`);
 
 const Schema = mongoose.Schema;
 
-// Should define this somewhere else
-const MAX_SIMULATION_TIME = 10;
-
-
 let SimulationSchema = new Schema({
-    name: {
-        type: String,
+    userId: {
+        type: Schema.Types.ObjectId,
         required: true,
+        ref: 'User'
     },
-    location: Object,
-    time: Number,
-    failure_rate: Array,
-    goals_care: Array,
-    goals_inclusion: Array,
-    enrollments: Array,
-    timestamp: Date,
-});
-
-SimulationSchema.methods.setTime = function (t) {
-    t = parseInt(t, 10);
-    if (!t || t > MAX_SIMULATION_TIME) {
-        // Throw an error?
-        return false;
-    }
-    this.time = t;
-    return true;
-};
-SimulationSchema.methods.setLocation = function (l) {
-    // Should sanitize
-    this.location = l;
-    return true;
-};
-SimulationSchema.methods.setFailureRate = function (fr) {
-    // Should sanitize
-    this.failure_rate = fr;
-    return true;
-};
-SimulationSchema.methods.setCareGoals = function (g) {
-    // Should sanitize
-    this.goals_care = g;
-    return true;
-};
-SimulationSchema.methods.setInclusionGoals = function (g) {
-    // Should sanitize
-    this.goals_inclusion = g;
-    return true;
-};
-SimulationSchema.methods.setEnrollments = function (e) {
-    try{
-        e = JSON.parse(e);
-    } catch (err) {
-        return false;
-    }
-    let success = true;
-    for(let i=0; i<e.length; i++){
-        if(!(e[i] instanceof Array)){
-            return false;
-        }
-        if(e[i].length !== this.time){
-            return false;
-        }
-        e[i].forEach((n, i, array) => {
-            if(n !== parseInt(n, 10)){
-                success = false;
-            }
-        });
-
-    }
-    if (success) this.enrollments = e;
-
-    return success;
-}
-SimulationSchema.methods.update = function (property, value) {
-    let success = true;
-    switch(property){
-        case 'time':
-            if (!this.setTime(value)) success = false;
-            break;
-        case 'location':
-            if (!this.setLocation(value)) success = false;
-            break;
-        case 'failure_rate':
-            if (!this.setFailureRate(value)) success = false;
-            break;
-        case 'goals_care':
-            if (!this.setCareGoals(value)) success = false;
-            break;
-        case 'goals_inclusion':
-            if (!this.setInclusionGoals(value)) success = false;
-            break;
-        case 'enrollments':
-            if (!this.setEnrollments(value)) success = false;
-            break;
-        case 'name':
-            this.name = value;
-            break;
+    content: {
+        type: String,
+        required: true,
     }
-    return success;
-};
-
-SimulationSchema.methods.run = function () {
-    /* Runs the Simulation with given parameters */
-    // if (!this.name || !this.location || !this.time) {
-    //     console.log('This is supposed to be an error.');
-    // }
-};
+});
 
 module.exports = mongoose.model('Simulation', SimulationSchema);
diff --git a/src/libs/models/user.js b/src/libs/models/user.js
index 4f1618caa3c16408814f3d6390185857b8eafcc7..0d54e4175fbf3336c4386bcc252d235dc6b478ce 100644
--- a/src/libs/models/user.js
+++ b/src/libs/models/user.js
@@ -82,7 +82,7 @@ var UserSchema = new Schema({
     origin: {
         type: String,
         enum: ['LDE', 'SimCAQ'],
-        required: true
+        required: [true, 'O campo origem é obrigatória e aceita apenas os valores "LDE" ou "SimCAQ"']
     },
     verified: {
         type: Boolean,
@@ -93,6 +93,10 @@ var UserSchema = new Schema({
     },
     citerole: {
         type: String
+    },
+    admin: {
+        type: Boolean,
+        default: false
     }
 });
 
diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js
index ff441d3eac10cd81cc5b0089d9d5aa04da0f827b..8dbc4cb0bfd35289924e9469fac17f95ec5f5f39 100644
--- a/src/libs/routes/api.js
+++ b/src/libs/routes/api.js
@@ -18,8 +18,6 @@ const city = require('./city');
 
 const school = require('./school');
 
-const spatial = require('./spatial');
-
 const simulation = require('./simulation');
 
 const user = require('./user');
@@ -50,6 +48,12 @@ const educationYears = require(`${libs}/routes/educationYears`);
 
 const downloads = require(`${libs}/routes/downloads`);
 
+const infrastructure = require(`${libs}/routes/infrastructure`);
+
+const distributionFactor = require(`${libs}/routes/distributionFactor`);
+
+const siope = require(`${libs}/routes/siope`);
+
 api.get('/', (req, res) => {
     res.json({ msg: 'SimCAQ API is running' });
 });
@@ -63,7 +67,6 @@ api.use('/state', state);
 api.use('/region', region);
 api.use('/city', city);
 api.use('/school', school);
-// api.use('/spatial', spatial);
 api.use('/classroom', classroom);
 api.use('/teacher', teacher);
 api.use('/idhmr', idhmr);
@@ -77,5 +80,8 @@ api.use('/verify', verifyToken);
 api.use('/reset', resetToken);
 api.use('/education_years', educationYears);
 api.use('/downloads', downloads);
+api.use('/infrastructure', infrastructure);
+api.use('/distribution_factor', distributionFactor);
+api.use('/siope', siope);
 
 module.exports = api;
diff --git a/src/libs/routes/class.js b/src/libs/routes/class.js
index ec2c54dc51cea0d4a70fce87edb0275a6fc48434..1d944ccd1a45bd47a8409daf804fbc61480a0bb3 100644
--- a/src/libs/routes/class.js
+++ b/src/libs/routes/class.js
@@ -33,15 +33,13 @@ classApp.use(cache('15 day'));
 classApp.get('/year_range', (req, res, next) => {
     req.sql.from('turma')
     .field('MIN(turma.ano_censo)', 'start_year')
-    .field('MAX(turma.ano_censo)', 'end_year')
-    .where('turma.ano_censo > 2014');
+    .field('MAX(turma.ano_censo)', 'end_year');
     next();
 }, query, response('range'));
 
 classApp.get('/years', (req, res, next) => {
     req.sql.from('turma')
-    .field('DISTINCT turma.ano_censo', 'year')
-    .where('turma.ano_censo > 2014');
+    .field('DISTINCT turma.ano_censo', 'year');
     next();
 }, query, response('years'));
 
diff --git a/src/libs/routes/classroom.js b/src/libs/routes/classroom.js
index 1895c0021e10871a5c1b8eb538f009ad9887befc..084291a740014d2811897b62fc16f51aeef3c0d1 100644
--- a/src/libs/routes/classroom.js
+++ b/src/libs/routes/classroom.js
@@ -27,15 +27,13 @@ let rqfCount = new ReqQueryFields();
 classroomApp.get('/year_range', (req, res, next) => {
     req.sql.from('escola')
     .field('MIN(escola.ano_censo)', 'start_year')
-    .field('MAX(escola.ano_censo)', 'end_year')
-    .where('escola.ano_censo > 2014');
+    .field('MAX(escola.ano_censo)', 'end_year');
     next();
 }, query, response('range'));
 
 classroomApp.get('/years', (req, res, next) => {
     req.sql.from('escola')
-    .field('DISTINCT escola.ano_censo', 'year')
-    .where('escola.ano_censo > 2014');
+    .field('DISTINCT escola.ano_censo', 'year');
     next();
 }, query, response('years'));
 
diff --git a/src/libs/routes/distributionFactor.js b/src/libs/routes/distributionFactor.js
new file mode 100644
index 0000000000000000000000000000000000000000..5cd08ebacb275672df829fe86a0ad0ae4ba42796
--- /dev/null
+++ b/src/libs/routes/distributionFactor.js
@@ -0,0 +1,190 @@
+const express = require('express');
+
+const distributionApp = express.Router();
+
+const libs = `${process.cwd()}/libs`;
+
+const squel = require('squel');
+
+const query = require(`${libs}/middlewares/query`).query;
+
+const multiQuery = require(`${libs}/middlewares/multiQuery`);
+
+const response = require(`${libs}/middlewares/response`);
+
+const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
+
+const id2str = require(`${libs}/middlewares/id2str`);
+
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
+let rqf = new ReqQueryFields();
+
+distributionApp.use(cache('15 day'));
+
+rqf.addField({
+    name: 'dims',
+    field: true,
+    where: false
+}).addField({
+    name: 'filter',
+    field: false,
+    where: true
+}).addValueToField({
+    name: 'city',
+    table: 'municipio',
+    tableField: ['nome', 'id'],
+    resultField: ['city_name', 'city_id'],
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'municipio_id',
+        table: 'fatores_matricula'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'municipio_id',
+        foreignTable: 'fatores_matricula'
+    }
+}, 'dims').addValueToField({
+    name: 'city',
+    table: 'municipio',
+    tableField: 'nome',
+    resultField: 'city_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'municipio_id',
+        table: 'fatores_matricula'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'municipio_id',
+        foreignTable: 'fatores_matricula'
+    }
+}, 'filter').addValue({
+    name: 'state',
+    table: 'estado',
+    tableField: 'nome',
+    resultField: 'state_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'estado_id',
+        table: 'fatores_matricula'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'estado_id',
+        foreignTable: 'fatores_matricula'
+    }
+}).addValue({
+    name: 'region',
+    table: 'regiao',
+    tableField: 'nome',
+    resultField: 'region_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'id'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'regiao_id',
+        foreignTable: 'fatores_matricula'
+    }
+})
+
+// Return all cities
+distributionApp.get('/', rqf.parse(), (req, res, next) => {
+    req.querySet = [];
+    req.queryIndex = {};
+
+    let relation = req.sql.clone();
+    relation.from('relacao_fatores_matricula').field('*');
+    req.queryIndex.relation = req.querySet.push(relation) - 1;
+
+    req.sql.from('fatores_matricula')
+    .field('fatores_matricula.municipio_id', 'municipio_id')
+    .field('fatores_matricula."mais_CRE_0"')
+	.field('fatores_matricula."mais_CRE_1"')
+	.field('fatores_matricula."mais_CRE_2"')
+	.field('fatores_matricula."mais_CRE_3"')
+	.field('fatores_matricula."mais_PRE"')
+	.field('fatores_matricula."mais_EFAI"')
+	.field('fatores_matricula."mais_EFAF"')
+	.field('fatores_matricula."mais_EM"')
+	.field('fatores_matricula."mais_EJA"')
+	.field('fatores_matricula."menos_CRE_0"')
+	.field('fatores_matricula."menos_CRE_1"')
+	.field('fatores_matricula."menos_CRE_2"')
+	.field('fatores_matricula."menos_CRE_3"')
+	.field('fatores_matricula."menos_PRE"')
+	.field('fatores_matricula."menos_EFAI"')
+	.field('fatores_matricula."menos_EFAF"')
+	.field('fatores_matricula."menos_EM"')
+	.field('fatores_matricula."menos_EJA"')
+    .group('fatores_matricula.municipio_id')
+    .group('fatores_matricula."mais_CRE_0"')
+	.group('fatores_matricula."mais_CRE_1"')
+	.group('fatores_matricula."mais_CRE_2"')
+	.group('fatores_matricula."mais_CRE_3"')
+	.group('fatores_matricula."mais_PRE"')
+	.group('fatores_matricula."mais_EFAI"')
+	.group('fatores_matricula."mais_EFAF"')
+	.group('fatores_matricula."mais_EM"')
+	.group('fatores_matricula."mais_EJA"')
+	.group('fatores_matricula."menos_CRE_0"')
+	.group('fatores_matricula."menos_CRE_1"')
+	.group('fatores_matricula."menos_CRE_2"')
+	.group('fatores_matricula."menos_CRE_3"')
+	.group('fatores_matricula."menos_PRE"')
+	.group('fatores_matricula."menos_EFAI"')
+	.group('fatores_matricula."menos_EFAF"')
+	.group('fatores_matricula."menos_EM"')
+	.group('fatores_matricula."menos_EJA"');
+
+    if(typeof req.dims.state !== 'undefined' || typeof req.filter.state !== 'undefined') {
+        req.sql.where('fatores_matricula.nivel = \'UF\'');
+    } else {
+        req.sql.where('fatores_matricula.nivel = \'BR\'');
+    }
+
+    next();
+}, rqf.build(), query, (req, res, next) => {
+    req.enrollmentFactor = req.result;
+    next();
+}, multiQuery, (req, res, next) => {
+    let relation = req.result[req.queryIndex.relation];
+    let result = [];
+    let first = true;
+    req.enrollmentFactor.forEach((city) => {
+        if(first) console.log(city);
+        let obj = {
+            level: city.nivel,
+            region_id: city.regiao_id,
+            region_name: city.region_name,
+            state_id: city.state_id,
+            state_name: city.state_name,
+            city_id: city.municipio_id,
+            city_name: city.city_name,
+            series: []
+        };
+        if(first) console.log(obj);
+        first = false;
+        relation.forEach((serie) => {
+            obj.series.push({
+                serie_id: serie.id,
+                distribution_factor_addition: city[serie.fator_adicao],
+                distribution_factor_reduction: city[serie.fator_reducao]
+            });
+        });
+        result.push(obj);
+    });
+    req.result = result;
+    next();
+}, response('ditributionFactor'));
+
+module.exports = distributionApp;
diff --git a/src/libs/routes/enrollment.js b/src/libs/routes/enrollment.js
index 3ab46ca9df12fdfd36c79321cfa43c18a2739696..1b9ad6ba46ea8bdff092529bfe504355eeff414a 100644
--- a/src/libs/routes/enrollment.js
+++ b/src/libs/routes/enrollment.js
@@ -16,7 +16,7 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
-const config = require(`${libs}/config`); 
+const config = require(`${libs}/config`);
 
 const passport = require('passport');
 
@@ -33,15 +33,13 @@ let rqf = new ReqQueryFields();
 enrollmentApp.get('/year_range', (req, res, next) => {
     req.sql.from('matricula')
     .field('MIN(matricula.ano_censo)', 'start_year')
-    .field('MAX(matricula.ano_censo)', 'end_year')
-    .where('matricula.ano_censo > 2014');
+    .field('MAX(matricula.ano_censo)', 'end_year');
     next();
 }, query, response('range'));
 
 enrollmentApp.get('/years', (req, res, next) => {
     req.sql.from('matricula')
-    .field('DISTINCT matricula.ano_censo', 'year')
-    .where('matricula.ano_censo > 2014');
+    .field('DISTINCT matricula.ano_censo', 'year');
     next();
 }, query, response('years'));
 
@@ -116,7 +114,7 @@ enrollmentApp.get('/education_level', (req, res, next) => {
 // Returns all school years available
 enrollmentApp.get('/education_level_mod', (req, res, next) => {
     req.result = [];
-    for(let i = 1; i <= 11; ++i) {
+    for(let i = 1; i <= 10; ++i) {
         req.result.push({
             id: i,
             name: id2str.educationLevelMod(i)
diff --git a/src/libs/routes/idhm.js b/src/libs/routes/idhm.js
index 26f1ef665884f66beefc805b0fcf16e2104a06cd..278ca24b319c30b0b9a38aead8d09abc5dfbeb5b 100644
--- a/src/libs/routes/idhm.js
+++ b/src/libs/routes/idhm.js
@@ -27,14 +27,12 @@ idhmApp.use(cache('15 day'));
 idhmApp.get('/year_range', (req, res, next) => {
     req.sql.from('adh_idh')
     .field('MIN(adh_idh.ano_censo)', 'start_year')
-    .field('MAX(adh_idh.ano_censo)', 'end_year')
-    .where('adh_idh.ano_censo <> 2014 AND adh_idh.ano_censo <> 2013');
+    .field('MAX(adh_idh.ano_censo)', 'end_year');
     next();
 }, query, (req, res, next) => {
     req.sql.from('adh_idh_uf')
     .field('MIN(adh_idh_uf.ano_censo)', 'start_year')
-    .field('MAX(adh_idh_uf.ano_censo)', 'end_year')
-    .where('adh_idh_uf.ano_censo <> 2014 AND adh_idh_uf.ano_censo <> 2013');
+    .field('MAX(adh_idh_uf.ano_censo)', 'end_year');
     req.old_result = req.result;
     next();
 }, query, (req, res, next) => {
@@ -49,8 +47,7 @@ idhmApp.get('/year_range', (req, res, next) => {
 
 idhmApp.get('/years', (req, res, next) => {
     req.sql.from('adh_idh')
-    .field('DISTINCT adh_idh.ano_censo', 'year')
-    .where('adh_idh.ano_censo <> 2014 AND adh_idh.ano_censo <> 2013');
+    .field('DISTINCT adh_idh.ano_censo', 'year');
     next();
 }, query, (req, res, next) => {
     req.oldResult = req.result;
@@ -58,8 +55,7 @@ idhmApp.get('/years', (req, res, next) => {
     req.sql = squel.select();
 
     req.sql.from('adh_idh_uf')
-    .field('DISTINCT adh_idh_uf.ano_censo', 'year')
-    .where('adh_idh_uf.ano_censo <> 2014 AND adh_idh_uf.ano_censo <> 2013');
+    .field('DISTINCT adh_idh_uf.ano_censo', 'year');
     next();
 }, query, (req, res, next) => {
     let result = Object.assign(req.oldResult, req.result);
diff --git a/src/libs/routes/idhme.js b/src/libs/routes/idhme.js
index 4fdbf09c3e6ff54e4779324a3da7afb40ce5f782..f9ba82b60b8312e492d71fecbba1e2e46b5c8789 100644
--- a/src/libs/routes/idhme.js
+++ b/src/libs/routes/idhme.js
@@ -25,14 +25,12 @@ idhmeApp.use(cache('15 day'));
 idhmeApp.get('/year_range', (req, res, next) => {
     req.sql.from('adh_idh')
     .field('MIN(adh_idh.ano_censo)', 'start_year')
-    .field('MAX(adh_idh.ano_censo)', 'end_year')
-    .where('adh_idh.ano_censo <> 2014 AND adh_idh.ano_censo <> 2013');
+    .field('MAX(adh_idh.ano_censo)', 'end_year');
     next();
 }, query, (req, res, next) => {
     req.sql.from('adh_idh_uf')
     .field('MIN(adh_idh_uf.ano_censo)', 'start_year')
-    .field('MAX(adh_idh_uf.ano_censo)', 'end_year')
-    .where('adh_idh_uf.ano_censo <> 2014 AND adh_idh_uf.ano_censo <> 2013');
+    .field('MAX(adh_idh_uf.ano_censo)', 'end_year');
     req.old_result = req.result;
     next();
 }, query, (req, res, next) => {
@@ -47,8 +45,7 @@ idhmeApp.get('/year_range', (req, res, next) => {
 
 idhmeApp.get('/years', (req, res, next) => {
     req.sql.from('adh_idh')
-    .field('DISTINCT adh_idh.ano_censo', 'year')
-    .where('adh_idh.ano_censo <> 2014 AND adh_idh.ano_censo <> 2013');
+    .field('DISTINCT adh_idh.ano_censo', 'year');
     next();
 }, query, (req, res, next) => {
     req.oldResult = req.result;
@@ -56,8 +53,7 @@ idhmeApp.get('/years', (req, res, next) => {
     req.sql = squel.select();
 
     req.sql.from('adh_idh_uf')
-    .field('DISTINCT adh_idh_uf.ano_censo', 'year')
-    .where('adh_idh_uf.ano_censo <> 2014 AND adh_idh_uf.ano_censo <> 2013');
+    .field('DISTINCT adh_idh_uf.ano_censo', 'year');
     next();
 }, query, (req, res, next) => {
     let result = Object.assign(req.oldResult, req.result);
diff --git a/src/libs/routes/idhml.js b/src/libs/routes/idhml.js
index 20550543f658421be2a96742bb690483ab0d88ef..d8dd79c324a00ae03176bdcc4465e6493e779bf4 100644
--- a/src/libs/routes/idhml.js
+++ b/src/libs/routes/idhml.js
@@ -25,14 +25,12 @@ idhmlApp.use(cache('15 day'));
 idhmlApp.get('/year_range', (req, res, next) => {
     req.sql.from('adh_idh')
     .field('MIN(adh_idh.ano_censo)', 'start_year')
-    .field('MAX(adh_idh.ano_censo)', 'end_year')
-    .where('adh_idh.ano_censo <> 2014 AND adh_idh.ano_censo <> 2013');
+    .field('MAX(adh_idh.ano_censo)', 'end_year');
     next();
 }, query, (req, res, next) => {
     req.sql.from('adh_idh_uf')
     .field('MIN(adh_idh_uf.ano_censo)', 'start_year')
-    .field('MAX(adh_idh_uf.ano_censo)', 'end_year')
-    .where('adh_idh_uf.ano_censo <> 2014 AND adh_idh_uf.ano_censo <> 2013');
+    .field('MAX(adh_idh_uf.ano_censo)', 'end_year');
     req.old_result = req.result;
     next();
 }, query, (req, res, next) => {
@@ -47,8 +45,7 @@ idhmlApp.get('/year_range', (req, res, next) => {
 
 idhmlApp.get('/years', (req, res, next) => {
     req.sql.from('adh_idh')
-    .field('DISTINCT adh_idh.ano_censo', 'year')
-    .where('adh_idh.ano_censo <> 2014 AND adh_idh.ano_censo <> 2013');
+    .field('DISTINCT adh_idh.ano_censo', 'year');
     next();
 }, query, (req, res, next) => {
     req.oldResult = req.result;
@@ -56,8 +53,7 @@ idhmlApp.get('/years', (req, res, next) => {
     req.sql = squel.select();
 
     req.sql.from('adh_idh_uf')
-    .field('DISTINCT adh_idh_uf.ano_censo', 'year')
-    .where('adh_idh_uf.ano_censo <> 2014 AND adh_idh_uf.ano_censo <> 2013');
+    .field('DISTINCT adh_idh_uf.ano_censo', 'year');
     next();
 }, query, (req, res, next) => {
     let result = Object.assign(req.oldResult, req.result);
diff --git a/src/libs/routes/idhmr.js b/src/libs/routes/idhmr.js
index 4646ea2a26f13768ba414f08af61501cc85f515b..c2d29659d0aa0f063bce90b683fa197127655b11 100644
--- a/src/libs/routes/idhmr.js
+++ b/src/libs/routes/idhmr.js
@@ -27,14 +27,12 @@ idhmrApp.use(cache('15 day'));
 idhmrApp.get('/year_range', (req, res, next) => {
     req.sql.from('adh_idh')
     .field('MIN(adh_idh.ano_censo)', 'start_year')
-    .field('MAX(adh_idh.ano_censo)', 'end_year')
-    .where('adh_idh.ano_censo <> 2014 AND adh_idh.ano_censo <> 2013');
+    .field('MAX(adh_idh.ano_censo)', 'end_year');
     next();
 }, query, (req, res, next) => {
     req.sql.from('adh_idh_uf')
     .field('MIN(adh_idh_uf.ano_censo)', 'start_year')
-    .field('MAX(adh_idh_uf.ano_censo)', 'end_year')
-    .where('adh_idh_uf.ano_censo <> 2014 AND adh_idh_uf.ano_censo <> 2013');
+    .field('MAX(adh_idh_uf.ano_censo)', 'end_year');
     req.old_result = req.result;
     next();
 }, query, (req, res, next) => {
@@ -49,8 +47,7 @@ idhmrApp.get('/year_range', (req, res, next) => {
 
 idhmrApp.get('/years', (req, res, next) => {
     req.sql.from('adh_idh')
-    .field('DISTINCT adh_idh.ano_censo', 'year')
-    .where('adh_idh.ano_censo <> 2014 AND adh_idh.ano_censo <> 2013');
+    .field('DISTINCT adh_idh.ano_censo', 'year');
     next();
 }, query, (req, res, next) => {
     req.oldResult = req.result;
@@ -58,8 +55,7 @@ idhmrApp.get('/years', (req, res, next) => {
     req.sql = squel.select();
 
     req.sql.from('adh_idh_uf')
-    .field('DISTINCT adh_idh_uf.ano_censo', 'year')
-    .where('adh_idh_uf.ano_censo <> 2014 AND adh_idh_uf.ano_censo <> 2013');
+    .field('DISTINCT adh_idh_uf.ano_censo', 'year');
     next();
 }, query, (req, res, next) => {
     let result = Object.assign(req.oldResult, req.result);
diff --git a/src/libs/routes/infrastructure.js b/src/libs/routes/infrastructure.js
new file mode 100644
index 0000000000000000000000000000000000000000..2e5ebec3aac4b03d8a8c89d5c6069b7760666a0f
--- /dev/null
+++ b/src/libs/routes/infrastructure.js
@@ -0,0 +1,542 @@
+const express = require('express');
+
+const infrastructureApp = express.Router();
+
+const libs = `${process.cwd()}/libs`;
+
+const log = require(`${libs}/log`)(module);
+
+const squel = require('squel');
+
+const query = require(`${libs}/middlewares/query`).query;
+
+const multiQuery = require(`${libs}/middlewares/multiQuery`);
+
+const response = require(`${libs}/middlewares/response`);
+
+const id2str = require(`${libs}/middlewares/id2str`);
+
+const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
+
+const config = require(`${libs}/config`); 
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
+let rqf = new ReqQueryFields();
+
+infrastructureApp.use(cache('15 day'));
+
+infrastructureApp.get('/year_range', (req, res, next) => {
+    req.sql.from('escola')
+    .field('MIN(escola.ano_censo)', 'start_year')
+    .field('MAX(escola.ano_censo)', 'end_year');
+    next();
+}, query, response('range'));
+
+infrastructureApp.get('/years', (req, res, next) => {
+    req.sql.from('escola')
+    .field('DISTINCT escola.ano_censo', 'year');
+    next();
+}, query, response('years'));
+
+infrastructureApp.get('/source', (req, res, next) => {
+    req.sql.from('fonte')
+    .field('fonte', 'source')
+    .where('tabela = \'escola\'');
+    next();
+}, query, response('source'));
+
+infrastructureApp.get('/location', (req, res, next) => {
+    req.result = [
+        {id: 1, name: 'Urbana'},
+        {id: 2, name: 'Rural'}
+    ];
+    next();
+}, response('location'));
+
+infrastructureApp.get('/location_detailed', (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('location_detailed'));
+
+infrastructureApp.get('/adm_dependency', (req, res, next) => {
+    req.sql.from('dependencia_adm')
+    .field('id')
+    .field('nome', 'name')
+    .where('id <= 4');
+    next();
+}, query, response('adm_dependency'));
+
+infrastructureApp.get('/adm_dependency_detailed', (req, res, next) => {
+    req.sql.from('dependencia_adm_priv')
+    .field('id', 'id')
+    .field('nome', 'name');
+    next();
+}, query, response('adm_dependency_detailed'));
+
+rqf.addField({
+    name: 'filter',
+    field: false,
+    where: true
+}).addField({
+    name: 'dims',
+    field: true,
+    where: false
+}).addValueToField({
+    name: 'city',
+    table: 'municipio',
+    tableField: ['nome', 'id'],
+    resultField: ['city_name', 'city_id'],
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'municipio_id',
+        table: 'escola'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'municipio_id',
+        foreignTable: 'escola'
+    }
+}, 'dims').addValueToField({
+    name: 'city',
+    table: 'municipio',
+    tableField: 'nome',
+    resultField: 'city_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'municipio_id',
+        table: 'escola'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'municipio_id',
+        foreignTable: 'escola'
+    }
+}, 'filter').addValue({
+    name: 'state',
+    table: 'estado',
+    tableField: 'nome',
+    resultField: 'state_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'estado_id',
+        table: 'escola'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'estado_id',
+        foreignTable: 'escola'
+    }
+}).addValue({
+    name: 'region',
+    table: 'regiao',
+    tableField: 'nome',
+    resultField: 'region_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'id'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'regiao_id',
+        foreignTable: 'escola'
+    }
+}).addValue({
+    name: 'location',
+    table: 'escola',
+    tableField: 'cod_localizacao',
+    resultField: 'location_id',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'cod_localizacao'
+    }
+}).addValue({
+    name: 'location_detailed',
+    table: 'escola',
+    tableField: 'localidade_area_rural',
+    resultField: 'location_detailed_id',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'localidade_area_rural'
+    }
+}).addValue({
+    name: 'adm_dependency',
+    table: 'escola',
+    tableField: 'dependencia_adm_id',
+    resultField: 'adm_dependency_id',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'dependencia_adm_id'
+    }
+}).addValue({
+    name: 'adm_dependency_detailed',
+    table: 'escola',
+    tableField: 'dependencia_adm_priv',
+    resultField: 'adm_dependency_detailed_id',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'dependencia_adm_priv'
+    }
+}).addValue({
+    name: 'min_year',
+    table: 'escola',
+    tableField: 'ano_censo',
+    resultField: 'year',
+    where: {
+        relation: '>=',
+        type: 'integer',
+        field: 'ano_censo'
+    }
+}).addValue({
+    name: 'max_year',
+    table: 'escola',
+    tableField: 'ano_censo',
+    resultField: 'year',
+    where: {
+        relation: '<=',
+        type: 'integer',
+        field: 'ano_censo'
+    }
+});
+
+function matchQueries(queryTotal, queryPartial) {
+    let match = [];
+    queryTotal.forEach((result) => {
+        let newObj = {};
+        let keys = Object.keys(result);
+        keys.forEach((key) => {
+            newObj[key] = result[key];
+        });
+        let index = keys.indexOf('total');
+        if(index > -1) keys.splice(index, 1);
+        let objMatch = null;
+
+        for(let i = 0; i < queryPartial.length; ++i) {
+            let partial = queryPartial[i];
+            let foundMatch = true;
+            for(let j = 0; j < keys.length; ++j) {
+                let key = keys[j];
+                if(partial[key] !== result[key]) {
+                    foundMatch = false;
+                    break;
+                }
+            }
+            if(foundMatch) {
+                objMatch = partial;
+                break;
+            }
+        }
+
+        if(objMatch) {
+            newObj.total = result.total;
+            newObj.partial = objMatch.total;
+            newObj.percentage = (objMatch.total / result.total) * 100;
+            match.push(newObj);
+        }
+    });
+
+    return match;
+}
+
+infrastructureApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
+    req.querySet = [];
+    req.queryIndex = {};
+
+    // Local de funcionamento
+    let allSchools = req.sql.clone();
+    allSchools.from('escola').field('COUNT(escola.id)', 'total')
+    .field("'Brasil'", 'name')
+    .field('escola.ano_censo', 'year')
+    .group('escola.ano_censo')
+    .where('escola.situacao_de_funcionamento = 1')
+    .order('escola.ano_censo');
+    req.queryIndex.allSchools = req.querySet.push(allSchools) - 1;
+
+    let schoolPlace = allSchools.clone();
+    schoolPlace.where('escola.func_predio_escolar = 1 AND escola.func_salas_empresa = 0 AND escola.func_templo_igreja = 0 AND escola.func_casa_professor = 0 AND escola.func_galpao = 0 AND escola.biblioteca = 1');
+    req.queryIndex.schoolPlace = req.querySet.push(schoolPlace) - 1;
+
+    // Bibliotecas
+    let allLibraries = allSchools.clone();
+    allLibraries.where('escola.func_predio_escolar = 1 AND escola.cod_localizacao = 1');
+    req.queryIndex.allLibraries = req.querySet.push(allLibraries) - 1;
+
+    let haveLibraries = allLibraries.clone();
+    haveLibraries.where('escola.biblioteca = 1');
+    req.queryIndex.haveLibraries = req.querySet.push(haveLibraries) - 1;
+
+    // Bibliotecas/Sala de leitura
+    let allLibrariesReadingRoom = allSchools.clone();
+    allLibrariesReadingRoom.where('escola.func_predio_escolar = 1 AND escola.cod_localizacao = 2');
+    req.queryIndex.allLibrariesReadingRoom = req.querySet.push(allLibrariesReadingRoom) - 1;
+
+    let haveLibrariesReadingRoom = allLibrariesReadingRoom.clone();
+    haveLibrariesReadingRoom.where('escola.sala_leitura = 1');
+    req.queryIndex.haveLibrariesReadingRoom = req.querySet.push(haveLibrariesReadingRoom) - 1;
+
+    // Laboratório de informática
+    let allInfLab = allSchools.clone();
+    allInfLab.where('escola.func_predio_escolar = 1')
+    .where('escola.reg_fund_ai = 1 OR escola.reg_fund_af = 1 OR escola.reg_medio_medio = 1 OR escola.reg_medio_integrado = 1 OR escola.reg_medio_normal = 1 OR escola.ensino_eja_fund = 1 OR escola.ensino_eja_medio = 1 OR escola.ensino_eja_prof = 1');
+    req.queryIndex.allInfLab = req.querySet.push(allInfLab) - 1;
+
+    let haveInfLab = allInfLab.clone();
+    haveInfLab.where('escola.lab_informatica = 1');
+    req.queryIndex.haveInfLab = req.querySet.push(haveInfLab) - 1;
+
+    // Laboratório de ciências
+    let allScienceLab = allInfLab.clone();
+    req.queryIndex.allScienceLab = req.querySet.push(allScienceLab) - 1;
+
+    let haveScienceLab = allScienceLab.clone();
+    haveScienceLab.where('escola.lab_ciencias = 1');
+    req.queryIndex.haveScienceLab = req.querySet.push(haveScienceLab) - 1;
+
+    // Parque infantil
+    let allKidsPark = allSchools.clone();
+    allKidsPark.where('escola.func_predio_escolar = 1')
+    .where('escola.reg_infantil_creche = 1 OR escola.reg_infantil_preescola = 1 OR escola.reg_fund_ai = 1 OR escola.esp_infantil_creche = 1 OR escola.esp_exclusiva_creche = 1 OR escola.reg_esp_exclusiva_fund_ai = 1');
+    req.queryIndex.allKidsPark = req.querySet.push(allKidsPark) - 1;
+
+    let haveKidsPark = allKidsPark.clone();
+    haveKidsPark.where('escola.parque_infantil = 1');
+    req.queryIndex.haveKidsPark = req.querySet.push(haveKidsPark) - 1;
+
+    // Berçário
+    let allCribs = allSchools.clone();
+    allCribs.where('escola.func_predio_escolar = 1')
+    .where('escola.reg_infantil_creche = 1 OR escola.esp_infantil_creche = 1');
+    req.queryIndex.allCribs = req.querySet.push(allCribs) - 1;
+
+    let haveCribs = allCribs.clone();
+    haveCribs.where('escola.bercario = 1');
+    req.queryIndex.haveCribs = req.querySet.push(haveCribs) - 1;
+
+    // Quadra
+    let allSportsCourt = allScienceLab.clone();
+    allSportsCourt.where('escola.cod_localizacao = 1');
+    req.queryIndex.allSportsCourt = req.querySet.push(allSportsCourt) - 1;
+
+    let haveSportsCourt = allSportsCourt.clone();
+    haveSportsCourt.where('escola.quadra_esportes = 1');
+    req.queryIndex.haveSportsCourt = req.querySet.push(haveSportsCourt) - 1;
+
+    // Quadra coberta
+    req.queryIndex.allCoveredSportsCourt = req.queryIndex.allSportsCourt;
+
+    let haveCoveredSportsCourt = allSportsCourt.clone();
+    haveCoveredSportsCourt.where('escola.quadra_esportes_coberta = 1');
+    req.queryIndex.haveCoveredSportsCourt = req.querySet.push(haveCoveredSportsCourt) - 1;
+
+    // Quadra Descoberta
+    let allUncoveredSportsCourt = allSportsCourt.clone();
+    allUncoveredSportsCourt.where('escola.quadra_esportes_coberta = 0');
+    req.queryIndex.allUncoveredSportsCourt = req.querySet.push(allUncoveredSportsCourt) - 1;
+
+    let haveUncoveredSportsCourt = allUncoveredSportsCourt.clone();
+    haveUncoveredSportsCourt.where('escola.quadra_esportes_descoberta = 1');
+    req.queryIndex.haveUncoveredSportsCourt = req.querySet.push(haveUncoveredSportsCourt) - 1;
+
+    // Sala de direção
+    let allDirectorRoom = allSchools.clone();
+    allDirectorRoom.where('escola.func_predio_escolar = 1 AND escola.cod_localizacao = 1');
+    req.queryIndex.allDirectorRoom = req.querySet.push(allDirectorRoom) - 1;
+
+    let haveDirectorRoom = allDirectorRoom.clone();
+    haveDirectorRoom.where('escola.sala_diretoria = 1');
+    req.queryIndex.haveDirectorRoom = req.querySet.push(haveDirectorRoom) - 1;
+
+    // Secretaria
+    let allSecretary = allSchools.clone();
+    allSecretary.where('escola.func_predio_escolar = 1');
+    req.queryIndex.allSecretary = req.querySet.push(allSecretary) - 1;
+
+    let haveSecretary = allSecretary.clone();
+    haveSecretary.where('escola.secretaria = 1');
+    req.queryIndex.haveSecretary = req.querySet.push(haveSecretary) - 1;
+
+    // Sala de professores
+    req.queryIndex.allTeacherRoom = req.queryIndex.allSecretary;
+
+    let haveTeacherRoom = allSecretary.clone();
+    haveTeacherRoom.where('escola.sala_professor = 1');
+    req.queryIndex.haveTeacherRoom = req.querySet.push(haveTeacherRoom) - 1;
+
+    // Cozinha
+    req.queryIndex.allKitchen = req.queryIndex.allSecretary;
+
+    let haveKitchen = allSecretary.clone();
+    haveKitchen.where('escola.cozinha = 1');
+    req.queryIndex.haveKitchen = req.querySet.push(haveKitchen) - 1;
+
+    // Despensa
+    req.queryIndex.allStoreroom = req.queryIndex.allSecretary;
+
+    let haveStoreroom = allSecretary.clone();
+    haveStoreroom.where('escola.despensa = 1');
+    req.queryIndex.haveStoreroom = req.querySet.push(haveStoreroom) - 1;
+
+    // Almoxarifado
+    req.queryIndex.allWarehouse = req.queryIndex.allSecretary;
+
+    let haveWarehouse = allSecretary.clone();
+    haveWarehouse.where('escola.almoxarifado = 1');
+    req.queryIndex.haveWarehouse = req.querySet.push(haveWarehouse) - 1;
+
+    // Internet
+    req.queryIndex.allInternet = req.queryIndex.allLibrariesReadingRoom;
+
+    let haveInternet = allLibrariesReadingRoom.clone();
+    haveInternet.where('escola.internet = 1');
+    req.queryIndex.haveInternet = req.querySet.push(haveInternet) - 1;
+
+    // Internet banda larga
+    req.queryIndex.allBroadbandInternet = req.queryIndex.allLibraries;
+
+    let haveBroadbandInternet = allLibraries.clone();
+    haveBroadbandInternet.where('escola.internet_banda_larga = 1');
+    req.queryIndex.haveBroadbandInternet = req.querySet.push(haveBroadbandInternet) - 1;
+
+    // Banheiro dentro do prédio
+    req.queryIndex.allInsideBathroom = req.queryIndex.allSecretary;
+
+    let haveInsideBathroom = allSecretary.clone();
+    haveInsideBathroom.where('escola.sanitario_dentro_predio = 1');
+    req.queryIndex.haveInsideBathroom = req.querySet.push(haveInsideBathroom) - 1;
+
+    // Banheiro adequado para educação infantil dentro do prédio
+    req.queryIndex.allInsideKidsBathroom = req.queryIndex.allKidsPark;
+
+    let haveInsideKidsBathroom = allKidsPark.clone();
+    haveInsideKidsBathroom.where('escola.sanitario_ei = 1');
+    req.queryIndex.haveInsideKidsBathroom = req.querySet.push(haveInsideKidsBathroom) - 1;
+
+    // Fornecimento de energia
+    req.queryIndex.allEletricEnergy = req.queryIndex.allSecretary;
+
+    let haveEletricEnergy = allSecretary.clone();
+    haveEletricEnergy.where('escola.fornecimento_energia = 1');
+    req.queryIndex.haveEletricEnergy = req.querySet.push(haveEletricEnergy) - 1;
+
+    // Abastecimento de água
+    req.queryIndex.allWaterSupply = req.queryIndex.allSecretary;
+
+    let haveWaterSupply = allSecretary.clone();
+    haveWaterSupply.where('escola.fornecimento_agua = 1');
+    req.queryIndex.haveWaterSupply = req.querySet.push(haveWaterSupply) - 1;
+
+    // Água filtrada
+    req.queryIndex.allFilteredWater = req.queryIndex.allSecretary;
+
+    let haveFilteredWater = allSecretary.clone();
+    haveFilteredWater.where('escola.agua_filtrada = 1');
+    req.queryIndex.haveFilteredWater = req.querySet.push(haveFilteredWater) - 1;
+
+    // Coleta de esgoto
+    req.queryIndex.allSewage = req.queryIndex.allSecretary;
+
+    let haveSewage = allSecretary.clone();
+    haveSewage.where('escola.esgoto_sanitario = 1');
+    req.queryIndex.haveSewage = req.querySet.push(haveSewage) - 1;
+
+    // Sala de recursos multifuncionais para Atendimento Educacional Especializado
+    req.queryIndex.allMultifunctionRoom = req.queryIndex.allSecretary;
+
+    let haveMultifunctionRoom = allSecretary.clone();
+    haveMultifunctionRoom.where('escola.sala_atendimento_especial = 1');
+    req.queryIndex.haveMultifunctionRoom = req.querySet.push(haveMultifunctionRoom) - 1;
+
+    // Banheiros adaptados para pessoas com deficiências
+    req.queryIndex.allSpecialBathroom = req.queryIndex.allSecretary;
+
+    let haveSpecialBathroom = allSecretary.clone();
+    haveSpecialBathroom.where('escola.sanitario_pne = 1');
+    req.queryIndex.haveSpecialBathroom = req.querySet.push(haveSpecialBathroom) - 1;
+
+    // Dependências adaptada para pessoas com deficiências
+    req.queryIndex.allAdaptedBuilding = req.queryIndex.allSecretary;
+
+    let haveAdaptedBuilding = allSecretary.clone();
+    haveAdaptedBuilding.where('escola.dependencias_pne = 1');
+    req.queryIndex.haveAdaptedBuilding = req.querySet.push(haveAdaptedBuilding) - 1;
+
+    next();
+}, multiQuery, (req, res, next) => {
+    // Faz o matching entre os resultados
+    let school_place = matchQueries(req.result[req.queryIndex.allSchools], req.result[req.queryIndex.schoolPlace]);
+    let libraries = matchQueries(req.result[req.queryIndex.allLibraries], req.result[req.queryIndex.haveLibraries]);
+    let libraries_reading_room = matchQueries(req.result[req.queryIndex.allLibrariesReadingRoom], req.result[req.queryIndex.haveLibrariesReadingRoom]);
+    let computer_lab = matchQueries(req.result[req.queryIndex.allInfLab], req.result[req.queryIndex.haveInfLab]);
+    let science_lab = matchQueries(req.result[req.queryIndex.allScienceLab], req.result[req.queryIndex.haveScienceLab]);
+    let kids_park = matchQueries(req.result[req.queryIndex.allKidsPark], req.result[req.queryIndex.haveKidsPark]);
+    let nursery = matchQueries(req.result[req.queryIndex.allCribs], req.result[req.queryIndex.haveCribs]);
+    let sports_court = matchQueries(req.result[req.queryIndex.allSportsCourt], req.result[req.queryIndex.haveSportsCourt]);
+    let covered_sports_court = matchQueries(req.result[req.queryIndex.allCoveredSportsCourt], req.result[req.queryIndex.haveCoveredSportsCourt]);
+    let uncovered_sports_court = matchQueries(req.result[req.queryIndex.allUncoveredSportsCourt], req.result[req.queryIndex.haveUncoveredSportsCourt]);
+    let director_room = matchQueries(req.result[req.queryIndex.allDirectorRoom], req.result[req.queryIndex.haveDirectorRoom]);
+    let secretary = matchQueries(req.result[req.queryIndex.allSecretary], req.result[req.queryIndex.haveSecretary]);
+    let teacher_room = matchQueries(req.result[req.queryIndex.allTeacherRoom], req.result[req.queryIndex.haveTeacherRoom]);
+    let kitchen = matchQueries(req.result[req.queryIndex.allKitchen], req.result[req.queryIndex.haveKitchen]);
+    let storeroom = matchQueries(req.result[req.queryIndex.allStoreroom], req.result[req.queryIndex.haveStoreroom]);
+    let warehouse = matchQueries(req.result[req.queryIndex.allWarehouse], req.result[req.queryIndex.haveWarehouse]);
+    let internet = matchQueries(req.result[req.queryIndex.allInternet], req.result[req.queryIndex.haveInternet]);
+    let broadband_internet = matchQueries(req.result[req.queryIndex.allBroadbandInternet], req.result[req.queryIndex.haveBroadbandInternet]);
+    let inside_bathroom = matchQueries(req.result[req.queryIndex.allInsideBathroom], req.result[req.queryIndex.haveInsideBathroom]);
+    let inside_kids_bathroom = matchQueries(req.result[req.queryIndex.allInsideKidsBathroom], req.result[req.queryIndex.haveInsideKidsBathroom]);
+    let eletric_energy = matchQueries(req.result[req.queryIndex.allEletricEnergy], req.result[req.queryIndex.haveEletricEnergy]);
+    let water_supply = matchQueries(req.result[req.queryIndex.allWaterSupply], req.result[req.queryIndex.haveWaterSupply]);
+    let filtered_water = matchQueries(req.result[req.queryIndex.allFilteredWater], req.result[req.queryIndex.haveFilteredWater]);
+    let sewage_treatment = matchQueries(req.result[req.queryIndex.allSewage], req.result[req.queryIndex.haveSewage]);
+    let special_multifunction_room = matchQueries(req.result[req.queryIndex.allMultifunctionRoom], req.result[req.queryIndex.haveMultifunctionRoom]);
+    let special_bathroom = matchQueries(req.result[req.queryIndex.allSpecialBathroom], req.result[req.queryIndex.haveSpecialBathroom]);
+    let adapted_building = matchQueries(req.result[req.queryIndex.allAdaptedBuilding], req.result[req.queryIndex.haveAdaptedBuilding]);
+
+    req.result = [{
+        school_place,
+        libraries,
+        libraries_reading_room,
+        computer_lab,
+        science_lab,
+        kids_park,
+        nursery,
+        sports_court,
+        covered_sports_court,
+        uncovered_sports_court,
+        director_room,
+        secretary,
+        teacher_room,
+        kitchen,
+        storeroom,
+        warehouse,
+        internet,
+        broadband_internet,
+        inside_bathroom,
+        inside_kids_bathroom,
+        eletric_energy,
+        water_supply,
+        filtered_water,
+        sewage_treatment,
+        special_multifunction_room,
+        special_bathroom,
+        adapted_building
+    }];
+
+    next();
+}, id2str.multitransform(false), response('infrastructure'));
+
+module.exports = infrastructureApp;
diff --git a/src/libs/routes/pibpercapita.js b/src/libs/routes/pibpercapita.js
index b2b5e010996e6e8436b635aafbd47e1a5538fc69..c7aaebc1662f2ade26dd2e1e280a4b5a23ec2ab0 100644
--- a/src/libs/routes/pibpercapita.js
+++ b/src/libs/routes/pibpercapita.js
@@ -28,14 +28,14 @@ pibpercapitaApp.get('/year_range', (req, res, next) => {
     req.sql.from('ibge_pib')
     .field('MIN(ibge_pib.ano_censo)', 'start_year')
     .field('MAX(ibge_pib.ano_censo)', 'end_year')
-    .where('ibge_pib.ano_censo <> 2014 AND ibge_pib.ano_censo <> 2013');
+    .where('ibge_pib.ano_censo > 2013');
     next();
 }, query, response('range'));
 
 pibpercapitaApp.get('/years', (req, res, next) => {
     req.sql.from('ibge_pib').
     field('DISTINCT ibge_pib.ano_censo', 'year')
-    .where('ibge_pib.ano_censo <> 2014 AND ibge_pib.ano_censo <> 2013');
+    .where('ibge_pib.ano_censo > 2013');
     next();
 }, query, response('years'));
 
@@ -147,20 +147,37 @@ rqf.addField({
 
 pibpercapitaApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => {
   log.debug(req.sql.toParam());
-  req.sql.from('ibge_pib')
-  .field('SUM(ibge_pib.pib)/SUM(ibge_pib.populacao)', 'total')
-  .field('ibge_pib.ano_censo', 'year')
-  .group('ibge_pib.ano_censo')
-  .order('ibge_pib.ano_censo')
 
+  if (("city" in req.dims) || ("city" in req.filter)) {
+      req.sql.from('ibge_pib')
+      .field('ibge_pib.pib_per_capita', 'total')
+      .field('ibge_pib.ano_censo', 'year')
+      .group('ibge_pib.ano_censo')
+      .group('ibge_pib.pib_per_capita')
+      .order('ibge_pib.ano_censo')
+  } else  {
+      req.sql.from('ibge_pib')
+      .field('SUM(ibge_pib.pib)/SUM(ibge_pib.populacao)', 'total')
+      .field('ibge_pib.ano_censo', 'year')
+      .group('ibge_pib.ano_censo')
+      .order('ibge_pib.ano_censo')
+   }
    next();
 }, query, id2str.transform(false), (req, res, next) => {
-    req.result.forEach((i) => {
-        let value = i.total;
-        let res = value.toString().split(".");
-        i.total = res[0] + "." +  res[1].toString().substring(0,3)  + "," + res[1].toString().substring(4,7) 
-    });
-    next();
-} ,response("pibpercapita"));
+     req.result.forEach((i) => {
+         let value = i.total;
+         let res = value.toString().split(".");
+         //rounding decimal.
+         let decimal = Math.round(res[1].toString().substring(0,2) + (".") + res[1].toString().substring(2,3));
+         //case 0 after comma
+         if (res[1].toString().substring(0,1) == 0) {
+              i.total = parseFloat(res[0] + "." + "0" + decimal);
+         } else {
+         i.total = parseFloat(res[0] + "." +  decimal);
+       }
+     });
+     next();
+ } ,response("pibpercapita"));
+
 
 module.exports = pibpercapitaApp;
diff --git a/src/libs/routes/population.js b/src/libs/routes/population.js
index c45717774448044a4603cb5ab32325d8e98a1e7a..f08991b308147b7747b10ed461ccf45ac2424110 100644
--- a/src/libs/routes/population.js
+++ b/src/libs/routes/population.js
@@ -27,15 +27,13 @@ populationApp.use(cache('15 day'));
 populationApp.get('/year_range', (req, res, next) => {
     req.sql.from('ibge_populacao')
     .field('MIN(ibge_populacao.ano_censo)', 'start_year')
-    .field('MAX(ibge_populacao.ano_censo)', 'end_year')
-    .where('ibge_populacao.ano_censo <> 2014 AND ibge_populacao.ano_censo <> 2013');
+    .field('MAX(ibge_populacao.ano_censo)', 'end_year');
     next();
 }, query, response('range'));
 
 populationApp.get('/years', (req, res, next) => {
     req.sql.from('ibge_populacao').
-    field('DISTINCT ibge_populacao.ano_censo', 'year')
-    .where('ibge_populacao.ano_censo <> 2014 AND ibge_populacao.ano_censo <> 2013');
+    field('DISTINCT ibge_populacao.ano_censo', 'year');
     next();
 }, query, response('years'));
 
diff --git a/src/libs/routes/school.js b/src/libs/routes/school.js
index c91151cc11efcadb1ca47e84749753b74a74e524..4cbd1314327eb0b12147041cacff73dbfdae306e 100644
--- a/src/libs/routes/school.js
+++ b/src/libs/routes/school.js
@@ -33,15 +33,13 @@ let rqfCount = new ReqQueryFields();
 schoolApp.get('/year_range', cache('15 day'), (req, res, next) => {
     req.sql.from('escola')
     .field('MIN(escola.ano_censo)', 'start_year')
-    .field('MAX(escola.ano_censo)', 'end_year')
-    .where('escola.ano_censo > 2014');
+    .field('MAX(escola.ano_censo)', 'end_year');
     next();
 }, query, response('range'));
 
 schoolApp.get('/years', cache('15 day'), (req, res, next) => {
     req.sql.from('escola').
-    field('DISTINCT escola.ano_censo', 'year')
-    .where('escola.ano_censo > 2014');
+    field('DISTINCT escola.ano_censo', 'year');
     next();
 }, query, response('years'));
 
diff --git a/src/libs/routes/simulation.js b/src/libs/routes/simulation.js
index 365d8bc7e262a6558063b1e5bb6dc8ae3c101ef5..13dcd9e5f9b0d87edf4c9e22a75b975c55b0a2f5 100644
--- a/src/libs/routes/simulation.js
+++ b/src/libs/routes/simulation.js
@@ -14,6 +14,10 @@ const response = require(`${libs}/middlewares/response`);
 
 const Simulation = require(`${libs}/models/simulation`);
 
+const PQR = require(`${libs}/models/pqr`);
+
+const passport = require('passport');
+
 simulationApp.get('/time', (req, res, next) => {
     const maxTime = parseInt(req.query.max_time, 10);
     log.debug('maxTime: ', maxTime);
@@ -29,133 +33,122 @@ simulationApp.get('/time', (req, res, next) => {
     });
 });
 
-simulationApp.get('/', (req, res) => {
-    let out = { success: true, msg: 'controller working' };
-    out.result = new Array()
-    Simulation.find({}, function(err, sims) {
-        sims.forEach((sim) => {
-            out.result.push(sim);
-        });
-        res.send(out);
+simulationApp.get('/pqr', (req, res) => {
+    PQR.findOne((err, pqr) => {
+        if(err) {
+            log.error(err);
+            return next({err});
+        }
+
+        res.json(pqr);
     });
 });
 
-simulationApp.post('/', (req, res, next) => {
-    // This method must associate new entry with user.
-    /* Creates a new simulation. Requires a name. */
-    if (!req.body.name) {
-        res.send({ success: false, msg: 'Must send a name for new entry' });
-    } else {
-        next();
-    }
-}, (req, res) => {
-    let currentdate = new Date();
-    let newSimulation = new Simulation({
-        name: req.body.name,
-        timestamp: currentdate.getDate(),
-    });
-    newSimulation.save((err) => {
-        if (err) {
-            res.send({ success: false, msg: err });
-        } else {
-            res.send({
-                success: true,
-                msg: 'new sim created',
-                id: newSimulation._id,
-            });
+simulationApp.put('/pqr', passport.authenticate('bearer', { session: false }), (req, res, next) => {
+    let user = req.user.toObject();
+
+    PQR.findOne((err, pqr) => {
+        if(err) {
+            log.error(err)
+            return next({err});
+        }
+
+        if(!user.admin) {
+            log.info(`Usuário ${user.email} tentou alterar o PQR, mas não tem privilégio`);
+            res.statusCode = 401;
+            return next({err: { msg: 'Unauthorized'}});
         }
+        pqr.content = req.body.content | pqr.content;
+        pqr.save((err) => {
+            if(err) {
+                log.error(err);
+                return next({err});
+            }
+            res.json({msg: 'PQR updated'})
+        });
     });
 });
 
-simulationApp.get('/:id', (req, res) => {
-    /* Can be used to check simulation construction status */
-    Simulation.findById(req.params.id, (err, simulation) => {
-        log.debug(req.params.id);
-        if (err) {
-            res.send({ success: false, msg: err });
-            return;
+simulationApp.get('/', passport.authenticate('bearer', { session: false }), (req, res) => {
+    let user = req.user.toObject();
+    Simulation.find({userId: user._id}, (err, simulations) => {
+        if(err) {
+            log.error(err);
+            return next({err});
         }
 
-        if (!simulation) {
-            res.send({ success: false, msg: 'Entry not found' });
-        } else {
-            res.send(simulation);
-        }
+        res.json(simulations);
     });
 });
 
-simulationApp.post('/:id', (req, res, next) => {
-    if (!Object.keys(req.body).length) {
-        res.send({ success: false, msg: 'No field informed to update' });
-    } else {
-        next();
-    }
-}, (req, res, next) => {
-    let simulation = Simulation.findById(req.params.id, (err, simulation) => {
-        if (err) {
-            res.send({ success: false, msg: err });
-        } else {
-            if (!simulation) {
-                res.send({ success: false, msg: 'Entry not found' });
-            } else {
-                req.simulation = simulation;
-                next();
-            }
-        }
+simulationApp.post('/', passport.authenticate('bearer', { session: false }), (req, res, next) => {
+    let user = req.user.toObject();
+
+    let simulation = new Simulation({
+        userId: user._id,
+        content: req.body.content
     });
-}, (req, res) => {
-    for (let property in req.body) {
-        if (Simulation.schema.tree.hasOwnProperty(property)) {
-            if(!req.simulation.update(property, req.body[property])){
-                res.send({
-                    success: false,
-                    msg: 'Invalid format for ' + property,
-                });
-                return ;
-            }
-        } else {
-            res.send({
-                success: false,
-                msg: 'Unknown property ' + property,
-            });
-            return ;
+
+    simulation.save((err) => {
+        if(err) {
+            log.error(err);
+            return next({err});
         }
-    }
-    req.simulation.save((err) => {
-        if (err) {
-            res.send({ success: false, msg: err });
-        } else {
-            res.send({
-                success: true,
-                msg: 'sim updated',
-                id: req.simulation._id,
-            });
+
+        res.json({msg: 'Simulation created', simulation});
+    })
+});
+
+simulationApp.get('/:id', passport.authenticate('bearer', { session: false }), (req, res) => {
+    let user = req.user.toObject();
+
+    Simulation.findOne({_id: req.params.id, userId: user._id}, (err, simulation) => {
+        if(err) {
+            log.error(err);
+            return next({err});
         }
+
+        res.json(simulation);
     });
 });
 
-simulationApp.delete('/:id', (req, res, next) => {
-    let simulation = Simulation.findById(req.params.id, (err, simulation) => {
-        if (err) {
-            res.send({ success: false, msg: err });
-        } else {
-            if (!simulation) {
-                res.send({ success: false, msg: 'Entry not found' });
-            } else {
-                next();
-            }
+simulationApp.put('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => {
+    let user = req.user.toObject();
+
+    Simulation.findOne({_id: req.params.id, userId: user._id}, (err, simulation) => {
+        if(err) {
+            log.error(err);
+            return next({err});
+        }
+
+        if(!simulation) {
+            res.statusCode = 404;
+            return next({err: { msg: 'Simulation not found'}});
         }
+
+        simulation.content = req.body.content | simulation.content;
+
+        simulation.save((err) => {
+            if(err) {
+                log.error(err);
+                return next(err);
+            }
+
+            res.json(simulation);
+        });
     });
-}, (req, res) => {
-    Simulation.remove({"_id": req.params.id}, (err) => {
-        if (err) {
-            res.send({ success: false, msg: err });
-        } else {
-            res.send({
-                success: true,
-                msg: 'sim removed',
-            });
+});
+
+simulationApp.delete('/:id', passport.authenticate('bearer', { session: false }), (req, res, next) => {
+    let user = req.user.toObject();
+
+    Simulation.remove({_id: req.params.id, userId: user._id}, (err, simulation) => {
+        if(err) {
+            log.error(err);
+            return next({err});
         }
+
+        res.json({msg: 'Simulation removed'});
     });
 });
 
diff --git a/src/libs/routes/siope.js b/src/libs/routes/siope.js
new file mode 100644
index 0000000000000000000000000000000000000000..51c1c36833b99ff097cf8a85a0c90c20598f737b
--- /dev/null
+++ b/src/libs/routes/siope.js
@@ -0,0 +1,166 @@
+const express = require('express');
+
+const siopeApp = express.Router();
+
+const libs = `${process.cwd()}/libs`;
+
+const log = require(`${libs}/log`)(module);
+
+const squel = require('squel');
+
+const query = require(`${libs}/middlewares/query`).query;
+
+const multiQuery = require(`${libs}/middlewares/multiQuery`);
+
+const response = require(`${libs}/middlewares/response`);
+
+const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
+
+const id2str = require(`${libs}/middlewares/id2str`);
+
+const config = require(`${libs}/config`);
+
+const cache = require('apicache').options({ debug: config.debug, statusCodes: {include: [200]} }).middleware;
+
+let rqf = new ReqQueryFields();
+
+siopeApp.use(cache('15 day'));
+
+siopeApp.get('/years', (req, res, next) => {
+    req.sql.from('siope_mun')
+    .field('DISTINCT siope_mun.ano_censo', 'year');
+    next();
+}, query, (req, res, next) => {
+    req.oldResult = req.result;
+
+    req.sql = squel.select();
+
+    req.sql.from('siope_uf')
+    .field('DISTINCT siope_uf.ano_censo', 'year');
+    next();
+}, query, (req, res, next) => {
+    let result = Object.assign(req.oldResult, req.result);
+    req.result = result;
+    next();
+}, response('years'));
+
+rqf.addField({
+    name: 'filter',
+    field: true,
+    where: true
+}).addField({
+    name: 'dims',
+    field: true,
+    where: false
+}).addValue({
+    name: 'city',
+    table: 'municipio',
+    tableField: 'nome',
+    resultField: 'city_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'municipio_id',
+        table: 'siope_mun'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'municipio_id',
+        foreignTable: 'siope_mun'
+    }
+}).addValue({
+    name: 'state',
+    table: 'estado',
+    tableField: ['id','nome','sigla'],
+    resultField: ['state_id','state_name','state_abbreviation'],
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'estado_id',
+        table: '@'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'estado_id',
+        foreignTable: '@'
+    }
+}).addValue({
+    name: 'min_year',
+    table: '@',
+    tableField: 'ano_censo',
+    resultField: 'year',
+    where: {
+        relation: '>=',
+        type: 'integer',
+        table: '@',
+        field: 'ano_censo'
+    }
+}).addValue({
+    name: 'max_year',
+    table: '@',
+    tableField: 'ano_censo',
+    resultField: 'year',
+    where: {
+        relation: '<=',
+        type: 'integer',
+        table: '@',
+        field: 'ano_censo'
+    }
+});
+
+
+
+siopeApp.get('/', rqf.parse(), (req, res, next) => {
+    req.querySet = [];
+    req.queryIndex = {};
+
+    let siopeUf = req.sql.clone();
+    siopeUf.from('siope_uf')
+    .field('siope_uf.ano_censo', 'year')
+    .field('siope_uf.estado_id', 'state_id')
+    .field('siope_uf.fundeb', 'fundeb')
+    .field('siope_uf.total_impostos', 'impostos')
+    .field('siope_uf.total_mde', 'MDE')
+    .group('siope_uf.ano_censo')
+    .group('siope_uf.estado_id')
+    .group('siope_uf.fundeb')
+    .group('siope_uf.total_impostos')
+    .group('siope_uf.total_mde')
+    .order('siope_uf.ano_censo');
+    req.queryIndex.siopeUf = req.querySet.push(siopeUf) - 1;
+
+    let siopeMun = req.sql.clone();
+    siopeMun.from('siope_mun')
+    .field('siope_mun.ano_censo', 'year')
+    .field('siope_mun.estado_id', 'state_id')
+    .field('siope_mun.municipio_id', 'city_id')
+    .field('siope_mun.fundeb', 'fundeb')
+    .field('siope_mun.total_impostos', 'impostos')
+    .field('siope_mun.total_mde', 'MDE')
+    .group('siope_mun.ano_censo')
+    .group('siope_mun.estado_id')
+    .group('siope_mun.municipio_id')
+    .group('siope_mun.fundeb')
+    .group('siope_mun.total_impostos')
+    .group('siope_mun.total_mde')
+    .order('siope_mun.ano_censo');
+    req.queryIndex.siopeMun = req.querySet.push(siopeMun) - 1;
+
+    next();
+}, rqf.multibuild(), multiQuery, (req, res, next) => {
+
+    let result = []
+
+    req.result[req.queryIndex.siopeUf].forEach((item) => {
+        result.push(item)
+    });
+    req.result[req.queryIndex.siopeMun].forEach((item) => {
+        result.push(item)
+    });
+
+    req.result = result;
+    next();
+
+}, response('siope'));
+
+module.exports = siopeApp;
diff --git a/src/libs/routes/teacher.js b/src/libs/routes/teacher.js
index 99aea83e034b8df0fa26d7bdf43fdc6962f81510..5dd885489544239f35d067d1bd0a3aede03bdeeb 100644
--- a/src/libs/routes/teacher.js
+++ b/src/libs/routes/teacher.js
@@ -16,7 +16,7 @@ const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
 
 const id2str = require(`${libs}/middlewares/id2str`);
 
-const config = require(`${libs}/config`); 
+const config = require(`${libs}/config`);
 
 const passport = require('passport');
 
@@ -32,15 +32,13 @@ teacherApp.use(cache('15 day'));
 teacherApp.get('/year_range', (req, res, next) => {
     req.sql.from('docente')
     .field('MIN(docente.ano_censo)', 'start_year')
-    .field('MAX(docente.ano_censo)', 'end_year')
-    .where('docente.ano_censo > 2014');;
+    .field('MAX(docente.ano_censo)', 'end_year');
     next();
 }, query, response('range'));
 
 teacherApp.get('/years', (req, res, next) => {
     req.sql.from('docente').
-    field('DISTINCT docente.ano_censo', 'year')
-    .where('docente.ano_censo > 2014');
+    field('DISTINCT docente.ano_censo', 'year');
     next();
 }, query, response('years'));
 
@@ -136,6 +134,17 @@ teacherApp.get('/gender', (req, res, next) => {
     next();
 }, response('gender'));
 
+
+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'}
+    ];
+    next();
+}, response('contract_type'));
+
 teacherApp.get('/ethnic_group', (req, res, next) => {
     req.result = [];
     for(let i = 0; i <=5; ++i) {
@@ -175,6 +184,16 @@ rqf.addField({
         type: 'integer',
         field: 'dependencia_adm_priv'
     }
+}).addValue({
+    name: 'contract_type',
+    table: 'docente',
+    tableField: 'tipo_contratacao',
+    resultField: 'contract_type_id',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'tipo_contratacao'
+    }
 }).addValue({
     name: 'education_level_mod',
     table: 'docente',
diff --git a/src/libs/routes/user.js b/src/libs/routes/user.js
index 9bdc38de32e2a544970d326ff7896e7f839c80ab..24f67b710d5b13568c95cfac8fff0d223eb805c4 100644
--- a/src/libs/routes/user.js
+++ b/src/libs/routes/user.js
@@ -137,7 +137,8 @@ userApp.post('/', (req, res, next) => {
     receiveEmails: false || req.body.receiveEmails,
     origin: req.body.origin,
     citesegment: req.body.citesegment,
-    citerole: req.body.citerole
+    citerole: req.body.citerole,
+    admin: false
   });
 
   if (typeof req.body.password === 'undefined' || !req.body.password) {
diff --git a/src/test/class.js b/src/test/class.js
index 8b6039ccf3131139fe4f85fbe50861f52b653b66..ef5254f45d847a568c17b31afafc8119273cb50e 100644
--- a/src/test/class.js
+++ b/src/test/class.js
@@ -38,6 +38,19 @@ describe('request class', () => {
             });
     });
 
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/class/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
     it('should list the rural locations', (done) => {
         chai.request(server)
             .get('/api/v1/class/rural_location')
@@ -122,6 +135,20 @@ describe('request class', () => {
             });
     });
 
+    it('should list the periods', (done) => {
+        chai.request(server)
+            .get('/api/v1/class/integral_time')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
     it('should list class', (done) => {
         chai.request(server)
             .get('/api/v1/class')
diff --git a/src/test/classroom.js b/src/test/classroom.js
index 08950d6875fb2bda4562943ef9be6177f748814a..9a6fd00a18afe4f1c584bea4f033dd0dcb3a84a6 100644
--- a/src/test/classroom.js
+++ b/src/test/classroom.js
@@ -109,6 +109,32 @@ describe('request classrooms', () => {
             });
     });
 
+    it('should list classrooms with year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/classroom/years')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list classrooms with year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/classroom/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
     it('should list classrooms with valid filters', (done) => {
         chai.request(server)
             .get('/api/v1/classroom?filter=region:4')
diff --git a/src/test/enrollment.js b/src/test/enrollment.js
index 7a3ffaeae8197d7ea2915a3e35a2aab5c6b76dfc..997e5f70077c2d4b008845d33f452e0b7a9df679 100644
--- a/src/test/enrollment.js
+++ b/src/test/enrollment.js
@@ -38,6 +38,32 @@ describe('request enrollments', () => {
             });
     });
 
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/enrollment/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
+    it('should list the years', (done) => {
+        chai.request(server)
+            .get('/api/v1/enrollment/years')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
     it('should list the locations', (done) => {
         chai.request(server)
             .get('/api/v1/enrollment/location')
diff --git a/src/test/idhm.js b/src/test/idhm.js
index 3b6eae6b5d655115f7faca5d0fe27898327d4d44..cea8893e9a4bbe92b6028615f3c8c841d9abdca1 100644
--- a/src/test/idhm.js
+++ b/src/test/idhm.js
@@ -38,6 +38,56 @@ describe('request idhm', () => {
             });
     });
 
+    it('should list the year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhm/years')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list the idhm levels', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhm/idhm_level')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhm/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
+    it('should return 400 with no filters', function (done) {
+        chai.request(server).get('/api/v1/idhm').end(function (err, res) {
+            res.should.have.status(400);
+            res.should.be.json;
+            res.body.should.have.property('error');
+            res.body.error.should.be.equal('Wrong/No filter specified');
+            done();
+        });
+    });
+
     it('should list idhm with valid filters', (done) => {
         chai.request(server)
             .get('/api/v1/idhm?filter=min_year:2000,state:41')
@@ -72,6 +122,22 @@ describe('request idhm', () => {
             });
     });
 
+    it('should list idhm with valid dims', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhm?dims=state')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                res.body.result[0].should.have.property('state_id');
+                res.body.result[0].should.have.property('state_name');
+                done();
+            });
+    });
+
     it('should list idhm with valid filtes and dims', (done) => {
         chai.request(server)
             .get('/api/v1/idhm?filter=state:41&dims=idhm_level')
@@ -90,4 +156,39 @@ describe('request idhm', () => {
             })
     });
 
+    it('should list idhm with valid filtes and dims', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhm?filter=city:4100202')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                res.body.result[0].should.have.property('city_id');
+                res.body.result[0].should.have.property('state_id');
+                res.body.result[0].should.have.property('state_name');
+                done();
+            })
+    });
+
+    it('should list idhm with valid filtes and dims', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhm?dims=idhm_level,state')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                res.body.result[0].should.have.property('state_id');
+                res.body.result[0].should.have.property('state_name');
+                res.body.result[0].should.have.property('idhm_level_name');
+                res.body.result[0].should.have.property('idhm_level_id');
+                done();
+            })
+    });
+
 });
diff --git a/src/test/idhme.js b/src/test/idhme.js
index 4962c8a68b3ca9a42d32ecb2554496f4384667f1..dc338d38adbbb0ce8362a0a9f1e950671b49295b 100644
--- a/src/test/idhme.js
+++ b/src/test/idhme.js
@@ -51,6 +51,19 @@ describe('request idhme', () => {
             });
     });
 
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhme/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
     it('should list idhme with valid filters', (done) => {
         chai.request(server)
             .get('/api/v1/idhme?filter=min_year:2000,state:41')
diff --git a/src/test/idhml.js b/src/test/idhml.js
index 9ddf8f345f78b8732ef6228659fb22190f9787c2..90312b0684f5b033d98e4f1b281a5e716a372cbd 100644
--- a/src/test/idhml.js
+++ b/src/test/idhml.js
@@ -51,6 +51,19 @@ describe('request idhml', () => {
             });
     });
 
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhml/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
     it('should list idhml with valid filters', (done) => {
         chai.request(server)
             .get('/api/v1/idhml?filter=min_year:2000,state:41')
diff --git a/src/test/idhmr.js b/src/test/idhmr.js
index 3a7370658adc8d9313739dc60f5f776a7c7def46..eb06b37d0da0e2c5b03cf245906a4edb4e3c035e 100644
--- a/src/test/idhmr.js
+++ b/src/test/idhmr.js
@@ -24,68 +24,115 @@ const server = require(`${libs}/app`);
 
 chai.use(chaiHttp);
 describe('request idhmr', () => {
-  it('should list the year range', (done) => {
-      chai.request(server)
-          .get('/api/v1/idhmr/year_range')
-          .end((err, res) => {
-              res.should.have.status(200);
-              res.should.be.json;
-              res.body.should.have.property('result');
-              res.body.result.should.be.a('array');
-              res.body.result[0].should.have.property('start_year');
-              res.body.result[0].should.have.property('end_year');
-              done();
-          });
-  });
-
-  it('should list idhmr with valid filters', (done) => {
-      chai.request(server)
-          .get('/api/v1/idhmr?filter=min_year:2000,state:41')
-          .end((err, res) => {
-              res.should.have.status(200);
-              res.should.be.json;
-              res.body.should.have.property('result');
-              res.body.result.should.be.a('array');
-              res.body.result[0].should.have.property('total');
-              res.body.result[0].should.have.property('year');
-              res.body.result[0].should.have.property('state_id');
-              res.body.result[0].should.have.property('state_name');
-              done();
-          });
-  });
-
-  it('should list idhmr with valid dims', (done) => {
-      chai.request(server)
-          .get('/api/v1/idhmr?dims=state')
-          .end((err, res) => {
-              res.should.have.status(200);
-              res.should.be.json;
-              res.body.should.have.property('result');
-              res.body.result.should.be.a('array');
-              res.body.result[0].should.have.property('total');
-              res.body.result[0].should.have.property('year');
-              res.body.result[0].should.have.property('state_id');
-              res.body.result[0].should.have.property('state_name');
-              done();
-          });
-  });
-
-  it('should list idhmr with valid filtes and dims', (done) => {
-      chai.request(server)
-          .get('/api/v1/idhm?filter=state:41&dims=city')
-          .end((err, res) => {
-              res.should.have.status(200);
-              res.should.be.json;
-              res.body.should.have.property('result');
-              res.body.result.should.be.a('array');
-              res.body.result[0].should.have.property('total');
-              res.body.result[0].should.have.property('year');
-              res.body.result[0].should.have.property('city_id');
-              res.body.result[0].should.have.property('state_id');
-              res.body.result[0].should.have.property('city_name');
-              res.body.result[0].should.have.property('state_name');
-              done();
-          })
-  });
+    it('should list the year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhmr/year_range')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('start_year');
+                res.body.result[0].should.have.property('end_year');
+                done();
+            });
+    });
+
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhmr/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
+    it('should list the available years', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhmr/years')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list idhmr with valid filters', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhmr?filter=min_year:2000,state:41')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                res.body.result[0].should.have.property('state_id');
+                done();
+            });
+    });
+
+    it('should list idhmr with invalid filters', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhmr?filter=foo:2010,bar:41')
+            .end((err, res) => {
+                res.should.have.status(400);
+                res.should.be.json;
+                res.body.should.have.property('error');
+                res.body.error.should.be.equal('Wrong/No filter specified');
+                done();
+            });
+    });
+
+    it('should list idhmr with valid dimensions', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhmr?dims=state&filter=min_year:2010')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                res.body.result[0].should.have.property('state_id');
+                res.body.result[0].should.have.property('state_name');
+                done();
+            });
+    });
+
+    it('should list idhmr with valid filters and dimensions', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhmr?filter=state:41,min_year:2010&dims=city')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                res.body.result[0].should.have.property('city_id');
+                res.body.result[0].should.have.property('city_name');
+                done();
+            });
+    });
+
+    it('should return 400 with no filters', (done) => {
+        chai.request(server)
+            .get('/api/v1/idhmr')
+            .end((err, res) => {
+                res.should.have.status(400);
+                res.should.be.json;
+                res.body.should.have.property('error');
+                res.body.error.should.be.equal('Wrong/No filter specified');
+                done();
+            });
+    });
 
 });
diff --git a/src/test/infrastructure.js b/src/test/infrastructure.js
new file mode 100644
index 0000000000000000000000000000000000000000..38dee0e203238b729975346d26cb9a731de4afd6
--- /dev/null
+++ b/src/test/infrastructure.js
@@ -0,0 +1,122 @@
+process.env.NODE_ENV = 'test';
+
+const chai = require('chai');
+
+const dirtyChai = require('dirty-chai');
+
+chai.use(dirtyChai);
+
+const chaiXml = require('chai-xml');
+
+chai.use(chaiXml);
+
+const chaiHttp = require('chai-http');
+
+const assert = chai.assert;
+
+const expect = chai.expect;
+
+const should = chai.should(); // actually call the function
+
+const libs = `${process.cwd()}/libs`;
+
+const server = require(`${libs}/app`);
+
+chai.use(chaiHttp);
+describe('request idhme', () => {
+    it('should list default query infrastructure', (done) => {
+        chai.request(server)
+            .get('/api/v1/infrastructure')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('school_place');
+                done();
+            });
+    });
+
+    it('should list the year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/infrastructure/years')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/infrastructure/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
+    it('should list the locations detailed', (done) => {
+        chai.request(server)
+            .get('/api/v1/infrastructure/location_detailed')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list the locations', (done) => {
+        chai.request(server)
+            .get('/api/v1/infrastructure/location')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/infrastructure/adm_dependency_detailed')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/infrastructure/adm_dependency')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+});
diff --git a/src/test/pibpercapita.js b/src/test/pibpercapita.js
new file mode 100644
index 0000000000000000000000000000000000000000..ca679a3440343110d92757fe9c0da05fd7d29b6b
--- /dev/null
+++ b/src/test/pibpercapita.js
@@ -0,0 +1,102 @@
+process.env.NODE_ENV = 'test';
+
+const chai = require('chai');
+
+const dirtyChai = require('dirty-chai');
+
+chai.use(dirtyChai);
+
+const chaiXml = require('chai-xml');
+
+chai.use(chaiXml);
+
+const chaiHttp = require('chai-http');
+
+const assert = chai.assert;
+
+const expect = chai.expect;
+
+const should = chai.should(); // actually call the function
+
+const libs = `${process.cwd()}/libs`;
+
+const server = require(`${libs}/app`);
+
+chai.use(chaiHttp);
+describe('request pibpercapita', () => {
+    it('should list the year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/pibpercapita/year_range')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('start_year');
+                res.body.result[0].should.have.property('end_year');
+                done();
+            });
+    });
+
+    it('should list the year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/pibpercapita/years')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list the pib to state', (done) => {
+        chai.request(server)
+            .get('/api/v1/pibpercapita?filter=state:41')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list the list pib to state and income level', (done) => {
+        chai.request(server)
+            .get('/api/v1/pibpercapita?filter=state:41&dims=income_level')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                res.body.result[0].should.have.property('income_level_name');
+                res.body.result[0].should.have.property('income_level_id');
+                done();
+            });
+    });
+
+    city:4102802
+        it('should list the pib to city', (done) => {
+            chai.request(server)
+                .get('/api/v1/pibpercapita?filter=city=4102802')
+                .end((err, res) => {
+                    res.should.have.status(200);
+                    res.should.be.json;
+                    res.body.should.have.property('result');
+                    res.body.result.should.be.a('array');
+                    res.body.result[0].should.have.property('total');
+                    res.body.result[0].should.have.property('year');
+
+                    done();
+                });
+        });
+
+
+});
diff --git a/src/test/population.js b/src/test/population.js
new file mode 100644
index 0000000000000000000000000000000000000000..37be404fceaa84eb4e1b6d6a763096b2d557c675
--- /dev/null
+++ b/src/test/population.js
@@ -0,0 +1,126 @@
+process.env.NODE_ENV = 'test';
+
+const chai = require('chai');
+
+const dirtyChai = require('dirty-chai');
+
+chai.use(dirtyChai);
+
+const chaiXml = require('chai-xml');
+
+chai.use(chaiXml);
+
+const chaiHttp = require('chai-http');
+
+const assert = chai.assert;
+
+const expect = chai.expect;
+
+const should = chai.should(); // actually call the function
+
+const libs = `${process.cwd()}/libs`;
+
+const server = require(`${libs}/app`);
+
+chai.use(chaiHttp);
+describe('request population', () => {
+    it('should list the year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/population/year_range')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('start_year');
+                res.body.result[0].should.have.property('end_year');
+                done();
+            });
+    });
+
+    it('should list the year range', (done) => {
+        chai.request(server)
+            .get('/api/v1/population/years')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list default population', (done) => {
+        chai.request(server)
+            .get('/api/v1/population')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list default population', (done) => {
+        chai.request(server)
+            .get('/api/v1/population/city_size')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list population with valid filters', (done) => {
+        chai.request(server)
+            .get('/api/v1/population?filter=state:41')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list population with valid filters', (done) => {
+        chai.request(server)
+            .get('/api/v1/population?filter=city:4102802')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
+    it('should list the city size dims', (done) => {
+        chai.request(server)
+            .get('/api/v1/population?dims=city_size')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                res.body.result[0].should.have.property('city_size_id');
+                res.body.result[0].should.have.property('city_size_name');
+                done();
+            });
+    });
+
+});
diff --git a/src/test/school.js b/src/test/school.js
index 7684e2737f9773551020ee976ade98f84d5fb2fb..266c542850095f1469d7952174af80e3a35d18e1 100644
--- a/src/test/school.js
+++ b/src/test/school.js
@@ -40,6 +40,20 @@ describe('request schools', () => {
             });
     });
 
+    it('should list a school by id', (done) => {
+        chai.request(server)
+            .get('/api/v1/school/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                //res.body.result[0].should.have.property('nome_entidade');
+                done();
+            });
+    });
+
     it('should list all schools from a state', (done) => {
         chai.request(server)
             .get('/api/v1/school?filter=state:41')
diff --git a/src/test/schoolCount.js b/src/test/schoolCount.js
index 1867e4569e1d2654793ea167d2892d04fcc4ad7b..305045894b410b0c4215ce2d3d4d85aa065860c2 100644
--- a/src/test/schoolCount.js
+++ b/src/test/schoolCount.js
@@ -301,4 +301,17 @@ describe('request schools count', () => {
                 done();
             });
     });
+
+    it('should list school with dimension agreement', (done) => {
+        chai.request(server)
+            .get('/api/v1/school/count?dims=agreement')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('agreement_name');
+                done();
+            });
+    });
 });
diff --git a/src/test/simulation.js b/src/test/simulation.js
index 91996ce1774c283f522aa7a0d431c76476aeab11..cd68d68048984fb7c23d22f20a64ce5fe3ab73f2 100644
--- a/src/test/simulation.js
+++ b/src/test/simulation.js
@@ -37,397 +37,397 @@ describe('Requires a simulation', () => {
         });
     });
 
-    it('should create a new simulation', (done) => {
-        chai.request(server)
-            .post('/api/v1/simulation')
-            .set('content-type', 'application/x-www-form-urlencoded')
-            .set('x-apicache-bypass', 'true')
-            .send({ name: 'test_entry' })
-            .end((err, res) => {
-                res.should.have.status(200);
-                res.should.be.json;
-                res.body.should.have.property('id');
-                res.body.id.should.be.a('string');
-                Simulation.findById(res.body.id, (err, simulation) => {
-                    simulation.should.have.property('name');
-                    simulation.name.should.be.a('string');
-                    simulation.name.should.equal('test_entry');
-                    done();
-                });
-            });
-    });
-    it('should not create a nameless simulation', (done) => {
-        chai.request(server)
-            .post('/api/v1/simulation')
-            .set('content-type', 'application/x-www-form-urlencoded')
-            .set('x-apicache-bypass', 'true')
-            .end((err, res) => {
-                res.should.have.status(200);
-                res.should.be.json;
-                res.body.should.not.have.property('id');
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                Simulation.findById(res.body.id, (err, simulation) => {
-                    expect(simulation).to.not.exist;
-                    done();
-                });
-            });
-    });
-    it('should find an existing simulation', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .get(`/api/v1/simulation/${id}`)
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('_id');
-                    res.body._id.should.be.a('string');
-                    res.body.should.have.property('name');
-                    res.body._id.should.be.a('string');
-                    done();
-                });
-        });
-    });
-    it('should not find an unexisting simulation', (done) => {
-        newSimulation = new Simulation();
-        let id = newSimulation._id;
-        chai.request(server)
-            .get(`/api/v1/simulation/${id}`)
-            .end((err, res) => {
-                res.should.have.status(200);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                done();
-            });
-    });
-    it('should update an existing simulation\'s location', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({ location: 5 })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('id');
-                    res.body.id.should.be.a('string');
-                    Simulation.findById(res.body.id, (err, simulation) => {
-                        simulation.should.have.property('name');
-                        simulation.name.should.be.a('string');
-                        simulation.name.should.equal('test');
-                        simulation.should.have.property('location');
-                        simulation.location.should.be.a('number');
-                        simulation.location.should.equal(5);
-                        done();
-                    });
-                });
-        });
-    });
-    it('should update multiple fields on a single request', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({
-                    name: 'new_name',
-                    location: 5,
-                    time: 3,
-                    failure_rate: [0.1, 0.2, 0.3],
-                    goals_care: [0.3, 0.2, 0.1],
-                    goals_inclusion: [0.8, 0.9, 1]
-                })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('id');
-                    res.body.id.should.be.a('string');
-                    Simulation.findById(res.body.id, (err, simulation) => {
-                        simulation.should.have.property('name');
-                        simulation.name.should.be.a('string');
-                        simulation.name.should.equal('new_name');
-                        simulation.should.have.property('location');
-                        simulation.location.should.be.a('number');
-                        simulation.location.should.equal(5);
-                        simulation.should.have.property('time');
-                        simulation.time.should.be.a('number');
-                        simulation.time.should.equal(3);
-                        simulation.should.have.property('failure_rate');
-                        simulation.failure_rate.should.be.a('array');
-                        simulation.failure_rate.length.should.equal(3);
-                        simulation.should.have.property('goals_care');
-                        simulation.goals_care.should.be.a('array');
-                        simulation.goals_care.length.should.equal(3);
-                        simulation.should.have.property('goals_inclusion');
-                        simulation.goals_inclusion.should.be.a('array');
-                        simulation.goals_inclusion.length.should.equal(3);
-                        done();
-                    });
-                });
-        });
-    });
-    it('should not update an unexisting simulation', (done) => {
-        newSimulation = new Simulation();
-        let id = newSimulation._id;
-        chai.request(server)
-            .post(`/api/v1/simulation/${id}`)
-            .send({ location: 5 })
-            .end((err, res) => {
-                res.should.have.status(200);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                done();
-            });
-    });
-    it('should update an existing simulation\'s time', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({ time: 5 })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('id');
-                    res.body.id.should.be.a('string');
-                    Simulation.findById(res.body.id, (err, simulation) => {
-                        simulation.should.have.property('name');
-                        simulation.name.should.be.a('string');
-                        simulation.should.have.property('time');
-                        simulation.time.should.be.a('number');
-                        simulation.time.should.equal(5);
-                        done();
-                    });
-                });
-        });
-    });
-    it('should not change results for empty post requests', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('success');
-                    res.body.success.should.equal(false);
-                    done();
-                });
-        });
-    });
-    it('should not update in case of invalid field', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({
-                    name: 'other_name',
-                    totally_not_valid_value_for_an_entry: 'not hacking this api',
-                })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('success');
-                    res.body.success.should.equal(false);
-                    Simulation.findById(id, (err, simulation) => {
-                        simulation.name.should.equal('test');
-                        done();
-                    });
-                });
-        });
-    });
-    it('should include consistent enrollment tables', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({
-                    time: 5,
-                    enrollments: "[[100, 150, 200, 250, 300]]",
-                })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('id');
-                    res.body.id.should.be.a('string');
-                    Simulation.findById(res.body.id, (err, simulation) => {
-                        simulation.should.have.property('name');
-                        simulation.name.should.be.a('string');
-                        simulation.should.have.property('time');
-                        simulation.time.should.be.a('number');
-                        simulation.time.should.equal(5);
-                        done();
-                    });
-                });
-        });
-    });
-    it('should not accept an invalid time', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({
-                    time: "I'm an inocent time entry, don't mind me",
-                })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('success');
-                    res.body.success.should.equal(false);
-                    });
-                    done();
-                });
-    });
-    it('should not accept enrollments table different than provided time', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({
-                    time: 5,
-                    enrollments: "[[1,2,3]]",
-                })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('success');
-                    res.body.success.should.equal(false);
-                    done();
-                });
-        });
-    });
-    it('should not include arrays of non arrays as enrollments', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({
-                    time: 5,
-                    enrollments: "[\"Tomato\"]",
-                })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('success');
-                    res.body.success.should.equal(false);
-                    done();
-                });
-        });
-    });
-    it('should not accept non array enrollments', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({
-                    time: 5,
-                    enrollments: "Am I still wanted here?",
-                })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('success');
-                    res.body.success.should.equal(false);
-                    done();
-                });
-        });
-    });
-    it('should not accept an enrollment with anything other than a number', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .post(`/api/v1/simulation/${id}`)
-                .send({
-                    time: 5,
-                    enrollments: "[[1,2,\"malicious payload\",4,5]]",
-                })
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('success');
-                    res.body.success.should.equal(false);
-                    done();
-                });
-        });
-    });
-    it('should delete an entry', (done) => {
-        newSimulation = new Simulation();
-        newSimulation.name = 'test';
-        newSimulation.save((err, sim) => {
-            let id = sim._id;
-            chai.request(server)
-                .delete(`/api/v1/simulation/${id}`)
-                .end((err, res) => {
-                    res.should.have.status(200);
-                    res.should.be.json;
-                    res.body.should.have.property('success');
-                    res.body.success.should.equal(true);
-                    done();
-                });
-        });
-    });
-    it('should not delete an unexisting entry', (done) => {
-        let sim = new Simulation();
-        let id = sim._id;
-        chai.request(server)
-            .delete(`/api/v1/simulation/${id}`)
-            .end((err, res) => {
-                res.should.have.status(200);
-                res.should.be.json;
-                res.body.should.have.property('success');
-                res.body.success.should.equal(false);
-                done();
-            });
-    });
+    // it('should create a new simulation', (done) => {
+    //     chai.request(server)
+    //         .post('/api/v1/simulation')
+    //         .set('content-type', 'application/x-www-form-urlencoded')
+    //         .set('x-apicache-bypass', 'true')
+    //         .send({ name: 'test_entry' })
+    //         .end((err, res) => {
+    //             res.should.have.status(200);
+    //             res.should.be.json;
+    //             res.body.should.have.property('id');
+    //             res.body.id.should.be.a('string');
+    //             Simulation.findById(res.body.id, (err, simulation) => {
+    //                 simulation.should.have.property('name');
+    //                 simulation.name.should.be.a('string');
+    //                 simulation.name.should.equal('test_entry');
+    //                 done();
+    //             });
+    //         });
+    // });
+    // it('should not create a nameless simulation', (done) => {
+    //     chai.request(server)
+    //         .post('/api/v1/simulation')
+    //         .set('content-type', 'application/x-www-form-urlencoded')
+    //         .set('x-apicache-bypass', 'true')
+    //         .end((err, res) => {
+    //             res.should.have.status(200);
+    //             res.should.be.json;
+    //             res.body.should.not.have.property('id');
+    //             res.body.should.have.property('success');
+    //             res.body.success.should.equal(false);
+    //             Simulation.findById(res.body.id, (err, simulation) => {
+    //                 expect(simulation).to.not.exist;
+    //                 done();
+    //             });
+    //         });
+    // });
+    // it('should find an existing simulation', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .get(`/api/v1/simulation/${id}`)
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('_id');
+    //                 res.body._id.should.be.a('string');
+    //                 res.body.should.have.property('name');
+    //                 res.body._id.should.be.a('string');
+    //                 done();
+    //             });
+    //     });
+    // });
+    // it('should not find an unexisting simulation', (done) => {
+    //     newSimulation = new Simulation();
+    //     let id = newSimulation._id;
+    //     chai.request(server)
+    //         .get(`/api/v1/simulation/${id}`)
+    //         .end((err, res) => {
+    //             res.should.have.status(200);
+    //             res.should.be.json;
+    //             res.body.should.have.property('success');
+    //             res.body.success.should.equal(false);
+    //             done();
+    //         });
+    // });
+    // it('should update an existing simulation\'s location', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({ location: 5 })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('id');
+    //                 res.body.id.should.be.a('string');
+    //                 Simulation.findById(res.body.id, (err, simulation) => {
+    //                     simulation.should.have.property('name');
+    //                     simulation.name.should.be.a('string');
+    //                     simulation.name.should.equal('test');
+    //                     simulation.should.have.property('location');
+    //                     simulation.location.should.be.a('number');
+    //                     simulation.location.should.equal(5);
+    //                     done();
+    //                 });
+    //             });
+    //     });
+    // });
+    // it('should update multiple fields on a single request', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({
+    //                 name: 'new_name',
+    //                 location: 5,
+    //                 time: 3,
+    //                 failure_rate: [0.1, 0.2, 0.3],
+    //                 goals_care: [0.3, 0.2, 0.1],
+    //                 goals_inclusion: [0.8, 0.9, 1]
+    //             })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('id');
+    //                 res.body.id.should.be.a('string');
+    //                 Simulation.findById(res.body.id, (err, simulation) => {
+    //                     simulation.should.have.property('name');
+    //                     simulation.name.should.be.a('string');
+    //                     simulation.name.should.equal('new_name');
+    //                     simulation.should.have.property('location');
+    //                     simulation.location.should.be.a('number');
+    //                     simulation.location.should.equal(5);
+    //                     simulation.should.have.property('time');
+    //                     simulation.time.should.be.a('number');
+    //                     simulation.time.should.equal(3);
+    //                     simulation.should.have.property('failure_rate');
+    //                     simulation.failure_rate.should.be.a('array');
+    //                     simulation.failure_rate.length.should.equal(3);
+    //                     simulation.should.have.property('goals_care');
+    //                     simulation.goals_care.should.be.a('array');
+    //                     simulation.goals_care.length.should.equal(3);
+    //                     simulation.should.have.property('goals_inclusion');
+    //                     simulation.goals_inclusion.should.be.a('array');
+    //                     simulation.goals_inclusion.length.should.equal(3);
+    //                     done();
+    //                 });
+    //             });
+    //     });
+    // });
+    // it('should not update an unexisting simulation', (done) => {
+    //     newSimulation = new Simulation();
+    //     let id = newSimulation._id;
+    //     chai.request(server)
+    //         .post(`/api/v1/simulation/${id}`)
+    //         .send({ location: 5 })
+    //         .end((err, res) => {
+    //             res.should.have.status(200);
+    //             res.should.be.json;
+    //             res.body.should.have.property('success');
+    //             res.body.success.should.equal(false);
+    //             done();
+    //         });
+    // });
+    // it('should update an existing simulation\'s time', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({ time: 5 })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('id');
+    //                 res.body.id.should.be.a('string');
+    //                 Simulation.findById(res.body.id, (err, simulation) => {
+    //                     simulation.should.have.property('name');
+    //                     simulation.name.should.be.a('string');
+    //                     simulation.should.have.property('time');
+    //                     simulation.time.should.be.a('number');
+    //                     simulation.time.should.equal(5);
+    //                     done();
+    //                 });
+    //             });
+    //     });
+    // });
+    // it('should not change results for empty post requests', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('success');
+    //                 res.body.success.should.equal(false);
+    //                 done();
+    //             });
+    //     });
+    // });
+    // it('should not update in case of invalid field', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({
+    //                 name: 'other_name',
+    //                 totally_not_valid_value_for_an_entry: 'not hacking this api',
+    //             })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('success');
+    //                 res.body.success.should.equal(false);
+    //                 Simulation.findById(id, (err, simulation) => {
+    //                     simulation.name.should.equal('test');
+    //                     done();
+    //                 });
+    //             });
+    //     });
+    // });
+    // it('should include consistent enrollment tables', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({
+    //                 time: 5,
+    //                 enrollments: "[[100, 150, 200, 250, 300]]",
+    //             })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('id');
+    //                 res.body.id.should.be.a('string');
+    //                 Simulation.findById(res.body.id, (err, simulation) => {
+    //                     simulation.should.have.property('name');
+    //                     simulation.name.should.be.a('string');
+    //                     simulation.should.have.property('time');
+    //                     simulation.time.should.be.a('number');
+    //                     simulation.time.should.equal(5);
+    //                     done();
+    //                 });
+    //             });
+    //     });
+    // });
+    // it('should not accept an invalid time', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({
+    //                 time: "I'm an inocent time entry, don't mind me",
+    //             })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('success');
+    //                 res.body.success.should.equal(false);
+    //                 });
+    //                 done();
+    //             });
+    // });
+    // it('should not accept enrollments table different than provided time', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({
+    //                 time: 5,
+    //                 enrollments: "[[1,2,3]]",
+    //             })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('success');
+    //                 res.body.success.should.equal(false);
+    //                 done();
+    //             });
+    //     });
+    // });
+    // it('should not include arrays of non arrays as enrollments', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({
+    //                 time: 5,
+    //                 enrollments: "[\"Tomato\"]",
+    //             })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('success');
+    //                 res.body.success.should.equal(false);
+    //                 done();
+    //             });
+    //     });
+    // });
+    // it('should not accept non array enrollments', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({
+    //                 time: 5,
+    //                 enrollments: "Am I still wanted here?",
+    //             })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('success');
+    //                 res.body.success.should.equal(false);
+    //                 done();
+    //             });
+    //     });
+    // });
+    // it('should not accept an enrollment with anything other than a number', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .post(`/api/v1/simulation/${id}`)
+    //             .send({
+    //                 time: 5,
+    //                 enrollments: "[[1,2,\"malicious payload\",4,5]]",
+    //             })
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('success');
+    //                 res.body.success.should.equal(false);
+    //                 done();
+    //             });
+    //     });
+    // });
+    // it('should delete an entry', (done) => {
+    //     newSimulation = new Simulation();
+    //     newSimulation.name = 'test';
+    //     newSimulation.save((err, sim) => {
+    //         let id = sim._id;
+    //         chai.request(server)
+    //             .delete(`/api/v1/simulation/${id}`)
+    //             .end((err, res) => {
+    //                 res.should.have.status(200);
+    //                 res.should.be.json;
+    //                 res.body.should.have.property('success');
+    //                 res.body.success.should.equal(true);
+    //                 done();
+    //             });
+    //     });
+    // });
+    // it('should not delete an unexisting entry', (done) => {
+    //     let sim = new Simulation();
+    //     let id = sim._id;
+    //     chai.request(server)
+    //         .delete(`/api/v1/simulation/${id}`)
+    //         .end((err, res) => {
+    //             res.should.have.status(200);
+    //             res.should.be.json;
+    //             res.body.should.have.property('success');
+    //             res.body.success.should.equal(false);
+    //             done();
+    //         });
+    // });
 
-    it('should returns an array in simulation/time', (done) => {
-        let max_time = 10;
-        chai.request(server)
-            .get(`/api/v1/simulation/time?max_time=${max_time}`)
-            .end((err, res) => {
-                res.should.have.status(200);
-                res.should.be.json;
-                res.body.should.have.property('result');
-                res.body.result.should.be.array;
-                done();
-            });
-    });
+    // it('should returns an array in simulation/time', (done) => {
+    //     let max_time = 10;
+    //     chai.request(server)
+    //         .get(`/api/v1/simulation/time?max_time=${max_time}`)
+    //         .end((err, res) => {
+    //             res.should.have.status(200);
+    //             res.should.be.json;
+    //             res.body.should.have.property('result');
+    //             res.body.result.should.be.array;
+    //             done();
+    //         });
+    // });
 
-    it('should return an error when no max_time is specified in simulation/time', (done) => {
-        chai.request(server)
-            .get(`/api/v1/simulation/time`)
-            .end((err, res) => {
-                res.should.have.status(400);
-                res.should.be.json;
-                res.body.should.have.property('error');
-                res.body.error.should.equal('Invalid value for mandatory parameter max_time');
-                done();
-            });
-    });
+    // it('should return an error when no max_time is specified in simulation/time', (done) => {
+    //     chai.request(server)
+    //         .get(`/api/v1/simulation/time`)
+    //         .end((err, res) => {
+    //             res.should.have.status(400);
+    //             res.should.be.json;
+    //             res.body.should.have.property('error');
+    //             res.body.error.should.equal('Invalid value for mandatory parameter max_time');
+    //             done();
+    //         });
+    // });
 });
diff --git a/src/test/state.js b/src/test/state.js
index df45900d8a1e897ffcf5080e663ad870dcc589e3..5cea7a4f69d6169208367df71571ebefa541a13a 100644
--- a/src/test/state.js
+++ b/src/test/state.js
@@ -72,6 +72,21 @@ describe('request states', () => {
             });
     });
 
+    it('should list states by region id', (done) => {
+        chai.request(server)
+            .get('/api/v1/state?filter=region:1,region:2')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('region_id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
     it('should search for Paraná', (done) => {
         chai.request(server)
             .get('/api/v1/state?search=name:paran')
diff --git a/src/test/teacher.js b/src/test/teacher.js
index 645934d2f7e7b907530d68d0edc6adddc98ec42d..30eddee8a20e6654c2db5f595c44e37f99868a5f 100644
--- a/src/test/teacher.js
+++ b/src/test/teacher.js
@@ -38,6 +38,19 @@ describe('request teachers', () => {
             });
     });
 
+    it('should list the source', (done) => {
+        chai.request(server)
+            .get('/api/v1/teacher/source')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('source');
+                done();
+            });
+    });
+
     it('should list the locations', (done) => {
         chai.request(server)
             .get('/api/v1/teacher/location')
@@ -52,6 +65,19 @@ describe('request teachers', () => {
             });
     });
 
+    it('should list the locations', (done) => {
+        chai.request(server)
+            .get('/api/v1/teacher/years')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+
     it('should list the rural locations', (done) => {
         chai.request(server)
             .get('/api/v1/teacher/rural_location')
@@ -108,6 +134,20 @@ describe('request teachers', () => {
             });
     });
 
+    it('should list the contract type', (done) => {
+        chai.request(server)
+            .get('/api/v1/teacher/contract_type')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
     it('should list the administrative dependencies', (done) => {
         chai.request(server)
             .get('/api/v1/teacher/adm_dependency')
@@ -371,4 +411,19 @@ describe('request teachers', () => {
                 done();
             });
     });
+
+
+
+    it('should list teacher count with dimension contract type', (done) => {
+        chai.request(server)
+            .get('/api/v1/teacher?filter=state:41&dims=contract_type')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('contract_type_name');
+                done();
+            });
+    });
 });