diff --git a/CHANGELOG.md b/CHANGELOG.md index 2985fe62201bab1f5388d1618b43cbbe04e47e32..fa0623bcc181226f977fbff32008824c93aa9063 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## UNRELEASED +### Changed +- Add school building filter/dimension to school count route +- Fixed CSV output when result objects have nested arrays and/or objects + +## 1.3.3 - 2018-06-27 +### Changed +- Removed restriction of year > 2014 of school count route + +## 1.3.2 - 2018-06-20 +### Changed +- Fixed math error in classroom count at total classroom needed expression + +## 1.3.1 - 2018-06-19 +### Changed +- Fixed bug with Federal District and missing cities in classroom count + +## 1.3.0 - 2018-06-18 +### Added +- Daily charge amount route + ## 1.2.3 - 2018-06-14 ### Changed - Fixed roundig error in classroom count route diff --git a/src/libs/convert/ageRange.js b/src/libs/convert/ageRange.js index b24990a1bd9870c90365d0af9b118c1578b1dd3a..30bc9f6c0cd64123a3673f248a222351634627ed 100644 --- a/src/libs/convert/ageRange.js +++ b/src/libs/convert/ageRange.js @@ -1,17 +1,17 @@ module.exports = function ageRange(id) { switch (id) { case 1: - return '0-3'; + return '0 a 3 anos'; case 2: - return '4-5'; + return '4 a 5 anos'; case 3: - return '6-10'; + return '6 a 10 anos'; case 4: - return '11-14'; + return '11 a 14 anos'; case 5: - return '15-17'; + return '15 a 17 anos'; case 6: - return '18-24'; + return '18 a 24 anos'; default: return 'Não declarada'; } diff --git a/src/libs/convert/fullAgeRange.js b/src/libs/convert/fullAgeRange.js index d7b36fdc9aee2e459126feb457695c9ea13aa7d5..e18b9156ed4e723fec83c939e8b01f148580d018 100644 --- a/src/libs/convert/fullAgeRange.js +++ b/src/libs/convert/fullAgeRange.js @@ -1,27 +1,27 @@ module.exports = function ageRange(id) { switch (id) { case 1: - return '0-3'; + return '0 a 3 anos'; case 2: - return '4-5'; + return '4 a 5 anos'; case 3: - return '6-10'; + return '6 a 10 anos'; case 4: - return '11-14'; + return '11 a 14 anos'; case 5: - return '15-17'; + return '15 a 17 anos'; case 6: - return '18-24'; + return '18 a 24 anos'; case 7: - return '25-29'; + return '25 a 29 anos'; case 8: - return '30-40'; + return '30 a 40 anos'; case 9: - return '41-50'; + return '41 a 50 anos'; case 10: - return '51-64'; + return '51 a 64 anos'; case 11: - return '64+'; + return 'Mais de 64 anos'; default: return 'Não declarada'; } diff --git a/src/libs/middlewares/response.js b/src/libs/middlewares/response.js index bd5009cd1e55ea391231348b30eea07568c6258d..62e1d9601c971b67abcf3a596160c9087850df03 100644 --- a/src/libs/middlewares/response.js +++ b/src/libs/middlewares/response.js @@ -3,13 +3,51 @@ const log = require(`${libs}/log`)(module); const xml = require('js2xmlparser'); const csv = require('csv-express'); - // Custom generic middleware used respond requests. - // The function reads the req.query.format param and respond in json, xml or csv +// Função para transformar um resultado que contém objetos com arrays aninhados em vários objetos +// sem arrays aninhandos +function flatObj(obj) { + let flatList = []; + let tempObj = {}; + + Object.keys(obj).forEach((key) => { + if(obj[key] instanceof Array) { + obj[key].forEach((i) => { + let flatten = flatObj(i); + if(flatten instanceof Array) { + flatten.forEach((j) => { + flatList.push(Object.assign({}, tempObj, j)); + }); + } else { + flatList.push(Object.assign({}, tempObj, flatten)); + } + }); + } else if(obj[key] instanceof Object) { + tempObj = Object.assign({}, tempObj, obj[key]); + } else { + tempObj[key] = obj[key]; + } + }); + + if(flatList.length > 0) return flatList; + return tempObj; +} + + // Custom generic middleware used to answer requests. + // The function reads the req.query.format param and answers in json, xml or csv function response(value) { return (req, res, next) => { if (req.query.format === 'csv') { + let result = []; + req.result.forEach((i) => { + let flatten = flatObj(i); + if(flatten instanceof Array) { + result = [...result, ...flatten]; + } else { + result.push(flatten); + } + }); res.attachment(`${value}.csv`); - res.csv(req.result, true); + res.csv(result, true); } else if (req.query.format === 'xml') { res.send(xml.parse('result', { [value]: req.result })); } else { diff --git a/src/libs/routes/classroomCount.js b/src/libs/routes/classroomCount.js index efb64d267dc622d1bb9c41059d2c25a205e2dd85..e3144507debb9c080a9893304bd50fd05eb68aa0 100644 --- a/src/libs/routes/classroomCount.js +++ b/src/libs/routes/classroomCount.js @@ -246,6 +246,7 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { let result = []; let hashSet = new Set(); let enrollments = [...req.enrollment]; + let leftovers = []; while (i < req.classroom.length) { let classroom = req.classroom[i]; // Cria hash única para cada espacialidade, dado um ano @@ -305,7 +306,12 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { enrollmentMatch = false; continue; } else if(classroom.city_name > enrollment.city_name) { - ++j; + let enrollmentHash = '' + enrollment.year + enrollment.state_id + enrollment.city_id; + if(hashSet.has(enrollmentHash)) { + leftovers.push(enrollments.splice(j, 1)); // Para inspeção, adiciona os que "sobram" no array de sobras + } else { + ++j; + } continue; } @@ -385,10 +391,12 @@ classroomCountApp.post('/', rqf.parse(), (req, res, next) => { educationLevel.enrollment.night_classes = Math.ceil((educationLevel.enrollment.total_enrollment_night / enrollmentEducationLevel.numberStudentClass)); // Total de salas - educationLevel.enrollment.total_classrooms_needed = (educationLevel.enrollment.full_period_classes + educationLevel.enrollment.day_classes); + educationLevel.enrollment.total_classrooms_needed = (educationLevel.enrollment.full_period_classes + educationLevel.enrollment.day_classes/2); if(educationLevel.enrollment.night_classes > educationLevel.enrollment.day_classes) educationLevel.enrollment.total_classrooms_needed += (educationLevel.enrollment.night_classes - educationLevel.enrollment.day_classes); + educationLevel.enrollment.total_classrooms_needed = Math.ceil(educationLevel.enrollment.total_classrooms_needed); + enrollment = enrollments[j]; } diff --git a/src/libs/routes/outOfSchool.js b/src/libs/routes/outOfSchool.js index b3b6e930dc265ecd198ba95a1862679448627a6b..822ef3a8e2bf5959b977a0fc2b1e807756efbd9c 100644 --- a/src/libs/routes/outOfSchool.js +++ b/src/libs/routes/outOfSchool.js @@ -41,17 +41,17 @@ outOfSchoolApp.get('/years', (req, res, next) => { outOfSchoolApp.get('/full_age_range', (req, res, next) => { req.result = [ - {id: 1, name: '0-3'}, - {id: 2, name: '4-5'}, - {id: 3, name: '6-10'}, - {id: 4, name: '11-14'}, - {id: 5, name: '15-17'}, - {id: 6, name: '18-24'}, - {id: 7, name: '25-29'}, - {id: 8, name: '30-40'}, - {id: 9, name: '41-50'}, - {id: 10, name: '51-64'}, - {id: 11, name: '64+'} + {id: 1, name: '0 a 3 anos'}, + {id: 2, name: '4 a 5 anos'}, + {id: 3, name: '6 a 10 anos'}, + {id: 4, name: '11 a 14 anos'}, + {id: 5, name: '15 a 17 anos'}, + {id: 6, name: '18 a 24 anos'}, + {id: 7, name: '25 a 29 anos'}, + {id: 8, name: '30 a 40 anos'}, + {id: 9, name: '41 a 50 anos'}, + {id: 10, name: '51 a 64 anos'}, + {id: 11, name: 'Mais de 64 anos'} ]; next(); }, response('full_age_range')); @@ -238,4 +238,4 @@ outOfSchoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { next(); }, query, addMissing(rqf), id2str.transform(), response('out_of_school')); -module.exports = outOfSchoolApp; \ No newline at end of file +module.exports = outOfSchoolApp; diff --git a/src/libs/routes/rateSchool.js b/src/libs/routes/rateSchool.js index 856013220997193c288c99ebd83dd33ffe8d03a8..a45865a9337e027cdbec45bd8b0163bd4477112c 100644 --- a/src/libs/routes/rateSchool.js +++ b/src/libs/routes/rateSchool.js @@ -64,12 +64,12 @@ rateSchoolApp.get('/ethnic_group_pnad', (req, res, next) => { rateSchoolApp.get('/age_range', (req, res, next) => { req.result = [ - {id: 1, name: '0-3'}, - {id: 2, name: '4-5'}, - {id: 3, name: '6-10'}, - {id: 4, name: '11-14'}, - {id: 5, name: '15-17'}, - {id: 6, name: '18-24'} + {id: 1, name: '0 a 3 anos'}, + {id: 2, name: '4 a 5 anos'}, + {id: 3, name: '6 a 10 anos'}, + {id: 4, name: '11 a 14 anos'}, + {id: 5, name: '15 a 17 anos'}, + {id: 6, name: '18 a 24 anos'} ]; next(); }, response('age_range')); diff --git a/src/libs/routes/school.js b/src/libs/routes/school.js index be935636bc20bc9f15ec55926a407d868967b761..33b5e1cf983e146e30c928f50a22af6d1f98e813 100644 --- a/src/libs/routes/school.js +++ b/src/libs/routes/school.js @@ -452,6 +452,16 @@ rqfCount.addField({ type: 'integer', field: 'ano_censo' } +}).addValue({ + name: 'school_building', + table: 'escola', + tableField: 'local_func_predio_escolar', + resultField: 'school_building', + where: { + relation: '=', + type: 'boolean', + field: 'local_func_predio_escolar' + } }); schoolApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { if(typeof req.filter === 'undefined' || Object.keys(req.filter).length === 0) { diff --git a/src/libs/routes/transport.js b/src/libs/routes/transport.js index a93de2e2995599e17d310a9dc498e7c62f03bcae..7af1b9907366b1de7be37f1db0c4d5d4d7dc8487 100644 --- a/src/libs/routes/transport.js +++ b/src/libs/routes/transport.js @@ -211,6 +211,26 @@ rqf.addField({ type: 'integer', field: 'etapas_mod_ensino_segmento_id' } +}).addValue({ + name: 'service_type', + table: 'matricula', + tableField: 'tipo', + resultField: 'service_type_id', + where: { + relation: '=', + type: 'integer', + field: 'tipo' + } +}).addValue({ + name: 'service_type', + table: 'matricula', + tableField: 'tipo', + resultField: 'service_type_id', + where: { + relation: '=', + type: 'integer', + field: 'tipo' + } }).addValue({ name: 'min_year', table: 'matricula', @@ -280,13 +300,23 @@ transportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { allEnrollment.field('COUNT(*)', 'total') .field("'Brasil'", 'name') .field('matricula.ano_censo', 'year') + .from('matricula') + .group('matricula.ano_censo') + .order('matricula.ano_censo') + .where('matricula.tipo <= 3'); + req.queryIndex.allEnrollment = req.querySet.push(allEnrollment) - 1; + + let allEnrollmentTransport = req.sql.clone() + allEnrollmentTransport.field('COUNT(*)', 'total') + .field("'Brasil'", 'name') + .field('matricula.ano_censo', 'year') .field('matricula.transporte_escolar_publico', 'use_transport_id') .from('matricula') .group('matricula.ano_censo') .group('matricula.transporte_escolar_publico') .order('matricula.ano_censo') .where('matricula.tipo <= 3'); - req.queryIndex.allEnrollment = req.querySet.push(allEnrollment) - 1; + req.queryIndex.allEnrollmentTransport = req.querySet.push(allEnrollmentTransport) - 1; let allTransports = req.sql.clone() @@ -379,33 +409,58 @@ transportApp.get('/', rqf.parse(), rqf.build(), (req, res, next) => { next(); }, multiQuery, (req, res, next) => { + let transport_match = []; + let transport_match_0 = JSON.parse(JSON.stringify(req.result[req.queryIndex.allTransports])); + let transport_match_1 = JSON.parse(JSON.stringify(req.result[req.queryIndex.allTransports])); + + let all_enrollment_match = []; + let all_enrollment_match_0 = JSON.parse(JSON.stringify(req.result[req.queryIndex.allEnrollment])); + let all_enrollment_match_1 = JSON.parse(JSON.stringify(req.result[req.queryIndex.allEnrollment])); + + //modifica adicionando use_transport_id=false, com os mesmos valores + //do transport_id=true, usado para dar o match e fazer a divisão. + for (let i = 0; i < transport_match_0.length; i++) { + transport_match_0[i].use_transport_id = true; + transport_match.push(transport_match_0[i]) + transport_match_1[i].use_transport_id = false; + transport_match.push(transport_match_1[i]) + } + + //modifica adicionando use_transport_id=false, com os mesmos valores + //do transport_id=true, usado para dar o match e fazer a divisão. + for (let i = 0; i < all_enrollment_match_0.length; i++) { + all_enrollment_match_0[i].use_transport_id = true; + all_enrollment_match.push(all_enrollment_match_0[i]) + all_enrollment_match_1[i].use_transport_id = false; + all_enrollment_match.push(all_enrollment_match_1[i]) + } - let public_transport = req.result[req.queryIndex.allEnrollment]; - let van_and_kombi = req.result[req.queryIndex.goVansAndKombi]; - let micro_bus = req.result[req.queryIndex.goMicroBus]; - let Bus = req.result[req.queryIndex.goBus]; - let bike = req.result[req.queryIndex.goBikes]; - let animal_traction = req.result[req.queryIndex.goAnimalTraction]; - let other_vehicle = req.result[req.queryIndex.goOtherVehicle]; - let waterway_5_Students = req.result[req.queryIndex.goWaterway_5_Students]; - let waterway_15_Students = req.result[req.queryIndex.goWaterway_15_Students]; - let waterway_35_Students = req.result[req.queryIndex.goWaterway_35_Students]; - let waterway_More_Than_35 = req.result[req.queryIndex.goWaterwayMoreThan_35]; - let subway_and_train = req.result[req.queryIndex.goSubwayAndTrain]; + let public_transport = matchQueries(all_enrollment_match, req.result[req.queryIndex.allEnrollmentTransport]); + let van_and_kombi = matchQueries(transport_match, req.result[req.queryIndex.goVansAndKombi]); + let micro_bus = matchQueries(transport_match, req.result[req.queryIndex.goMicroBus]); + let bus = matchQueries(transport_match, req.result[req.queryIndex.goBus]); + let bike = matchQueries(transport_match, req.result[req.queryIndex.goBikes]); + let animal_traction = matchQueries(transport_match, req.result[req.queryIndex.goAnimalTraction]); + let other_vehicle = matchQueries(transport_match, req.result[req.queryIndex.goOtherVehicle]); + let waterway_5_Students = matchQueries(transport_match, req.result[req.queryIndex.goWaterway_5_Students]); + let waterway_15_Students = matchQueries(transport_match, req.result[req.queryIndex.goWaterway_15_Students]); + let waterway_35_Students = matchQueries(transport_match, req.result[req.queryIndex.goWaterway_35_Students]); + let waterway_More_Than_35 = matchQueries(transport_match, req.result[req.queryIndex.goWaterwayMoreThan_35]); + let subway_and_train = matchQueries(transport_match, req.result[req.queryIndex.goSubwayAndTrain]); req.result = [{ - public_transport, - van_and_kombi, - micro_bus, - Bus, - bike, - animal_traction, - other_vehicle, - waterway_5_Students, - waterway_15_Students, - waterway_35_Students, - waterway_More_Than_35, - subway_and_train + public_transport, + van_and_kombi, + micro_bus, + bus, + bike, + animal_traction, + other_vehicle, + waterway_5_Students, + waterway_15_Students, + waterway_35_Students, + waterway_More_Than_35, + subway_and_train }]; next(); }, id2str.multitransform(false), response('transports'));