Skip to content

Commit

Permalink
Merge pull request #2091 from bcgov/feature/EAC-22
Browse files Browse the repository at this point in the history
Monitor registrations.
  • Loading branch information
arcshiftsolutions authored Nov 7, 2024
2 parents 0b6dad6 + 42fd20b commit 18fd08e
Show file tree
Hide file tree
Showing 18 changed files with 1,664 additions and 35 deletions.
37 changes: 37 additions & 0 deletions backend/src/components/cache-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ let specialEducationCodesMap = new Map();
let duplicateResolutionCodesMap = new Map();
let programDuplicateTypeCodesMap = new Map();

let assessmentTypeCodesMap = new Map();
let assessmentSpecialCaseTypeCodesMap = new Map();

const cacheService = {

async loadAllSchoolsToMap() {
Expand Down Expand Up @@ -231,6 +234,40 @@ const cacheService = {
};
},

async loadAllAssessmentTypeCodesToMap() {
log.debug('Loading all assessment Type Codes during start up');
await retry(async () => {
const assessmentTypeCodesResponse = await getData(config.get('server:eas:assessmentTypeCodeURL'));
assessmentTypeCodesResponse.forEach(entry => {
assessmentTypeCodesMap.set(entry.assessmentTypeCode, entry.label);
});
log.info(`Loaded ${assessmentTypeCodesMap.size} assessmentTypeCodes.`);
}, {
retries: 50
});
},

async loadAllSpecialCaseTypeCodesToMap() {
log.debug('Loading all specialcase Type Codes during start up');
await retry(async () => {
const provincialSpecialCaseTypeCodesResponse = await getData(config.get('server:eas:assessmentSpecialCaseTypeCodeURL'));
provincialSpecialCaseTypeCodesResponse.forEach(entry => {
assessmentSpecialCaseTypeCodesMap.set(entry.provincialSpecialCaseCode, entry.label);
});
log.info(`Loaded ${assessmentSpecialCaseTypeCodesMap.size} assessmentSpecialCaseTypeCodes.`);
}, {
retries: 50
});
},

getAssessmentTypeLabelByCode(assessmentTypeCode) {
return assessmentTypeCodesMap.get(assessmentTypeCode);
},

getSpecialCaseTypeLabelByCode(specialCaseTypeCode) {
return assessmentSpecialCaseTypeCodesMap.get(specialCaseTypeCode);
},

async loadDataToCache(cacheKey,url){
log.debug(` loading all ${cacheKey} during start up`);
await retry(async () => {
Expand Down
88 changes: 86 additions & 2 deletions backend/src/components/eas/eas.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
const { logApiError, getData, errorResponse, handleExceptionResponse } = require('../utils');
const HttpStatus = require('http-status-codes');
const utils = require('../utils');

const config = require('../../config');
const cacheService = require('../cache-service');
const { createMoreFiltersSearchCriteria } = require('./studentFilters');
const moment = require('moment');

async function getAssessmentSessions(req, res) {
try {
Expand All @@ -16,6 +18,22 @@ async function getAssessmentSessions(req, res) {
}
}

async function getAssessmentSessionsBySchoolYear(req, res) {
try {
const url = `${config.get('server:eas:assessmentSessionsURL')}/school-year/${req.params.schoolYear}`;
let data = await getData(url);
data.forEach(session => {
session.assessments.forEach(assessment => {
assessment.assessmentTypeName = cacheService.getAssessmentTypeLabelByCode(assessment.assessmentTypeCode)+' ('+assessment.assessmentTypeCode+')';
});
});
return res.status(200).json(data);
} catch (e) {
logApiError(e, 'getSessions', 'Error occurred while attempting to GET sessions by school year.');
return handleExceptionResponse(e, res);
}
}

async function updateAssessmentSession(req, res) {
if (req.params.sessionID !== req.body.sessionID) {
return res.status(HttpStatus.BAD_REQUEST).json({
Expand All @@ -37,7 +55,73 @@ async function updateAssessmentSession(req, res) {
return errorResponse(res);
}
}

async function getAssessmentStudentsPaginated(req, res) {
try {
const search = [];

if (req.query.searchParams?.['moreFilters']) {
let criteriaArray = createMoreFiltersSearchCriteria(req.query.searchParams['moreFilters']);
criteriaArray.forEach(criteria => {
search.push(criteria);
});
}

const params = {
params: {
pageNumber: req.query.pageNumber,
pageSize: req.query.pageSize,
sort: JSON.stringify(req.query.sort),
searchCriteriaList: JSON.stringify(search),
}
};

let data = await getData(`${config.get('server:eas:assessmentStudentsURL')}/paginated`, params);

if (req?.query?.returnKey) {
let result = data?.content.map((student) => student[req?.query?.returnKey]);
return res.status(HttpStatus.OK).json(result);
}
data?.content.forEach(value => {
let school = cacheService.getSchoolBySchoolID(value.schoolID);
let assessmentCenter = cacheService.getSchoolBySchoolID(value.assessmentCenterID);
let district = cacheService.getDistrictJSONByDistrictId(school.districtID);

value.schoolNumber = school.mincode;
value.schoolName = getSchoolName(school);
value.districtID = school.districtID;
value.districtNumber = district.districtNumber;
value.districtName = getDistrictName(district);
value.assessmentCenterNumber = assessmentCenter.mincode;
value.assessmentCenterName = getSchoolName(assessmentCenter);

value.assessmentTypeName = cacheService.getAssessmentTypeLabelByCode(value.assessmentTypeCode)+' ('+value.assessmentTypeCode+')';
value.provincialSpecialCaseName = cacheService.getSpecialCaseTypeLabelByCode(value.provincialSpecialCaseCode);
value.sessionName = moment(value.courseMonth, 'MM').format('MMMM') +' '+value.courseYear;

});
return res.status(200).json(data);
} catch (e) {
if (e?.status === 404) {
res.status(HttpStatus.OK).json(null);
} else {
await logApiError(e, 'Error getting eas assessment student paginated list');
return errorResponse(res);
}
}
}

function getSchoolName(school) {
return school.mincode + ' - ' + school.schoolName;
}

function getDistrictName(district) {
return district.districtNumber + ' - ' + district.name;
}

module.exports = {
getAssessmentSessions,
updateAssessmentSession
getAssessmentSessionsBySchoolYear,
updateAssessmentSession,
getAssessmentStudentsPaginated
};
145 changes: 145 additions & 0 deletions backend/src/components/eas/studentFilters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
'use strict';
const { FILTER_OPERATION, VALUE_TYPE, CONDITION} = require('../../util/constants');

function createMoreFiltersSearchCriteria(searchFilter = []) {
let searchCriteriaList = [];

let districtNameNumberFilter = [];
let schoolNameNumberFilter = [];
let assessmentCenterNameNumberFilter = [];

for (const [key, filter] of Object.entries(searchFilter)) {
let pValue = filter ? filter.map(filter => filter.value) : null;

//Default Filter Begin
if (key === 'schoolYear' && pValue) {
searchCriteriaList.push({ key: 'assessmentEntity.sessionEntity.schoolYear', value: pValue[0].replace('-', '/'), operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND });
}
//Default Filter End

if (key === 'surName' && pValue) {
searchCriteriaList.push({ key: 'surName', value: pValue.toString(), operation: FILTER_OPERATION.CONTAINS_IGNORE_CASE, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND });
}

if (key === 'pen' && pValue) {
searchCriteriaList.push({ key: 'pen', value: pValue.toString(), operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND });
}

if (key === 'localID' && pValue) {
searchCriteriaList.push({ key: 'localID', value: pValue.toString(), operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND });
}

if (key === 'districtNameNumber' && pValue) {
let districtNameNumberCriteria = createDistrictNameNumberSearchCriteria(pValue.toString());
districtNameNumberFilter = [...districtNameNumberCriteria];
}

if (key === 'schoolNameNumber' && pValue) {
let schoolNameNumberCriteria = createSchoolNameNumberSearchCriteria(pValue.toString());
schoolNameNumberFilter = [...schoolNameNumberCriteria];
}

if (key === 'assessmentCenterNameNumber' && pValue) {
let schoolNameNumberCriteria = createAssessmentCenterNameNumberSearchCriteria(pValue.toString());
assessmentCenterNameNumberFilter = [...schoolNameNumberCriteria];
}

if (key === 'session' && pValue) {
searchCriteriaList.push({ key: 'assessmentEntity.sessionEntity.sessionID', value: pValue.toString(), operation: FILTER_OPERATION.IN, valueType: VALUE_TYPE.UUID, condition: CONDITION.AND });
}

if (key === 'assessmentTypeCode' && pValue) {
searchCriteriaList.push({ key: 'assessmentEntity.assessmentTypeCode', value: pValue.toString(), operation: FILTER_OPERATION.IN, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND });
}

if (key === 'specialCaseCode' && pValue) {
searchCriteriaList.push({ key: 'provincialSpecialCaseCode', value: pValue.toString(), operation: FILTER_OPERATION.IN, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND });
}

if (key === 'proficienyScore' && pValue) {
if(JSON.parse(pValue) === true) {
searchCriteriaList.push({ key: 'proficiencyScore', value: 0, operation: FILTER_OPERATION.NOT_EQUAL, valueType: VALUE_TYPE.INTEGER, condition: CONDITION.AND });
} else {
searchCriteriaList.push({ key: 'proficiencyScore', value:0, operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.INTEGER, condition: CONDITION.AND });
}
}

if (key === 'proficienyScoreValue' && pValue) {
searchCriteriaList.push({ key: 'proficiencyScore', value: pValue.toString(), operation: FILTER_OPERATION.IN, valueType: VALUE_TYPE.INTEGER, condition: CONDITION.AND });
}

}
const search = [];
if (districtNameNumberFilter.length > 0) {
search.push({
condition: CONDITION.AND,
searchCriteriaList: districtNameNumberFilter
});
}
if (schoolNameNumberFilter.length > 0) {
search.push({
condition: CONDITION.AND,
searchCriteriaList: schoolNameNumberFilter
});
}
if (assessmentCenterNameNumberFilter.length > 0) {
search.push({
condition: CONDITION.AND,
searchCriteriaList: assessmentCenterNameNumberFilter
});
}
if (searchCriteriaList.length > 0) {
search.push({
condition: CONDITION.AND,
searchCriteriaList: searchCriteriaList
});
}
return search;
}

function createDistrictNameNumberSearchCriteria(value) {
const searchDistrictCriteriaList = [];

searchDistrictCriteriaList.push({
key: 'districtID',
operation: FILTER_OPERATION.EQUAL,
value: value,
valueType: VALUE_TYPE.UUID,
condition: CONDITION.AND
});

return searchDistrictCriteriaList;
}

function createSchoolNameNumberSearchCriteria(value) {
const searchSchoolCriteriaList = [];

searchSchoolCriteriaList.push({
key: 'schoolID',
operation: FILTER_OPERATION.EQUAL,
value: value,
valueType: VALUE_TYPE.UUID,
condition: CONDITION.AND
});

return searchSchoolCriteriaList;
}

function createAssessmentCenterNameNumberSearchCriteria(value) {
const searchAssessmentCenterCriteriaList = [];

searchAssessmentCenterCriteriaList.push({
key: 'assessmentCenterID',
operation: FILTER_OPERATION.EQUAL,
value: value,
valueType: VALUE_TYPE.UUID,
condition: CONDITION.AND
});

return searchAssessmentCenterCriteriaList;
}


module.exports = {
createMoreFiltersSearchCriteria
};
4 changes: 3 additions & 1 deletion backend/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ nconf.defaults({
},
eas:{
rootURL: process.env.EAS_API_URL,
assessmentSessionsURL: process.env.EAS_API_URL+ '/sessions'
assessmentSessionsURL: process.env.EAS_API_URL+ '/sessions',
assessmentTypesURL: process.env.EAS_API_URL+ '/assessments',
assessmentStudentsURL: process.env.EAS_API_URL+ '/students',
}
},
oidc: {
Expand Down
7 changes: 6 additions & 1 deletion backend/src/routes/eas.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
const passport = require('passport');
const express = require('express');
const router = express.Router();
const { getAssessmentSessions, updateAssessmentSession } = require('../components/eas/eas');
const { getAssessmentSessions, getAssessmentSessionsBySchoolYear, updateAssessmentSession, getAssessmentStudentsPaginated } = require('../components/eas/eas');
const utils = require('../components/utils');
const extendSession = utils.extendSession();
const permUtils = require('../components/permissionUtils');
const perm = require('../util/Permission');

const PERMISSION = perm.PERMISSION;


router.get('/assessment-sessions', passport.authenticate('jwt', {session: false}, undefined), permUtils.checkUserHasPermission(PERMISSION.MANAGE_EAS_SESSIONS_PERMISSION), extendSession, getAssessmentSessions);
router.get('/assessment-sessions/school-year/:schoolYear', passport.authenticate('jwt', {session: false}, undefined), permUtils.checkUserHasPermission(PERMISSION.MANAGE_EAS_SESSIONS_PERMISSION), extendSession, getAssessmentSessionsBySchoolYear);
router.put('/assessment-sessions/:sessionID', passport.authenticate('jwt', {session: false}, undefined), permUtils.checkUserHasPermission(PERMISSION.MANAGE_EAS_SESSIONS_PERMISSION), extendSession, updateAssessmentSession);

router.get('/assessment-registrations/paginated', passport.authenticate('jwt', {session: false}, undefined), permUtils.checkUserHasPermission(PERMISSION.MANAGE_EAS_SESSIONS_PERMISSION), extendSession, getAssessmentStudentsPaginated);


module.exports = router;
12 changes: 12 additions & 0 deletions backend/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ if(!config.get('frontendConfig').disableSdcFunctionality) {
});
}

cacheService.loadAllAssessmentTypeCodesToMap().then(() => {
log.info('Loaded AssessmentTypeCodes data to memory');
}).catch((e) => {
log.error('Error loading AssessmentTypeCodes during boot .', e);
});
cacheService.loadAllSpecialCaseTypeCodesToMap().then(() => {
log.info('Loaded SpecialCaseTypeCodes data to memory');
}).catch((e) => {
log.error('Error loading SpecialCaseTypeCodes during boot .', e);
});


cacheService.loadAllAuthoritiesToMap().then(() => {
log.info('Loaded authorities data to memory');
}).catch((e) => {
Expand Down
Loading

0 comments on commit 18fd08e

Please sign in to comment.