Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

District and school assessment landing page. #1994

Merged
merged 5 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions backend/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const instituteRouter = require('./routes/institute');
const configRouter = require('./routes/config');
const sdcRouter = require('./routes/sdc');
const gradRouter = require('./routes/grad');
const easRouter = require('./routes/eas');
const promMid = require('express-prometheus-middleware');
const messagePubSub = require('./messaging/message-pub-sub');
messagePubSub.init().then(() => {
Expand Down Expand Up @@ -213,6 +214,7 @@ apiRouter.use('/student', studentRouter);
apiRouter.use('/institute',instituteRouter);
apiRouter.use('/sdc',sdcRouter);
apiRouter.use('/grad',gradRouter);
apiRouter.use('/eas',easRouter);

//Handle 500 error
app.use((err, _req, res, next) => {
Expand Down
121 changes: 121 additions & 0 deletions backend/src/components/eas/eas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
'use strict';
const { logApiError, getAccessToken, getData, errorResponse, handleExceptionResponse } = require('../utils');
const HttpStatus = require('http-status-codes');
const config = require('../../config');
const cacheService = require('../cache-service');
const { createMoreFiltersSearchCriteria } = require('./studentFilters');
const moment = require('moment');

async function getAssessmentSessions(req, res) {
try {
const url = `${config.get('eas:assessmentSessionsURL')}`;
const token = getAccessToken(req);
const data = await getData(token, url);
data.forEach(session => {
session.isOpen = new Date(session.activeFromDate) <= new Date() && new Date(session.activeUntilDate) >= new Date();
});
return res.status(200).json(data);
} catch (e) {
logApiError(e, 'getAssessmentSessions', 'Error occurred while attempting to GET assessment sessions.');
return handleExceptionResponse(e, res);
}
}

async function getActiveAssessmentSessions(req, res) {
try {
const url = `${config.get('eas:assessmentSessionsURL')}/active`;
const token = getAccessToken(req);
const data = await getData(token, url);
return res.status(200).json(data);
} catch (e) {
logApiError(e, 'getActiveAssessmentSessions', 'Error occurred while attempting to GET active assessment sessions.');
return handleExceptionResponse(e, res);
}
}

async function getAssessmentSessionsBySchoolYear(req, res) {
try {
const url = `${config.get('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 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,
getActiveAssessmentSessions,
getAssessmentSessionsBySchoolYear,
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 === 'proficiencyScore' && 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 === 'proficiencyScoreValue' && 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
};
1 change: 1 addition & 0 deletions backend/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ nconf.defaults({
bannerColor: process.env.BANNER_COLOR,
disableSdcFunctionality: process.env.DISABLE_SDC_FUNCTIONALITY === 'true',
disableGradFunctionality: process.env.DISABLE_GRAD_FUNCTIONALITY === 'true',
disableEASFunctionality: process.env.DISABLE_EAS_FUNCTIONALITY === 'true',
termsOfUseURL: process.env.TERMS_OF_USE,
helpURL: process.env.HELP,
webSocketURL: process.env.WEB_SOCKET_URL,
Expand Down
1 change: 1 addition & 0 deletions backend/src/routes/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ async function getConfig(req, res) {
BANNER_COLOR: frontendConfig.bannerColor,
DISABLE_SDC_FUNCTIONALITY: frontendConfig.disableSdcFunctionality,
DISABLE_GRAD_FUNCTIONALITY: frontendConfig.disableGradFunctionality,
DISABLE_EAS_FUNCTIONALITY: frontendConfig.disableEASFunctionality,
TERMS_OF_USE_URL: frontendConfig.termsOfUseURL,
HELP_URL: frontendConfig.helpURL,
WEB_SOCKET_URL: frontendConfig.webSocketURL,
Expand Down
18 changes: 18 additions & 0 deletions backend/src/routes/eas.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const passport = require('passport');
const express = require('express');
const router = express.Router();
const { getAssessmentSessions, getActiveAssessmentSessions, getAssessmentSessionsBySchoolYear, getAssessmentStudentsPaginated } = require('../components/eas/eas');
const auth = require('../components/auth');
const isValidBackendToken = auth.isValidBackendToken();
const { validateAccessToken, findInstituteType_params, checkPermissionForRequestedInstitute } = require('../components/permissionUtils');
const { PERMISSION } = require('../util/Permission');


router.get('/assessment-sessions/:instituteType', passport.authenticate('jwt', {session: false}, undefined), isValidBackendToken, validateAccessToken, findInstituteType_params, checkPermissionForRequestedInstitute(PERMISSION.EAS_DIS_EDIT, PERMISSION.EAS_SCH_EDIT), getAssessmentSessions);
router.get('/assessment-sessions/active/:instituteType', passport.authenticate('jwt', {session: false}, undefined), isValidBackendToken, validateAccessToken, findInstituteType_params, checkPermissionForRequestedInstitute(PERMISSION.EAS_DIS_EDIT, PERMISSION.EAS_SCH_EDIT), getActiveAssessmentSessions);
router.get('/assessment-sessions/school-year/:schoolYear/:instituteType', passport.authenticate('jwt', {session: false}, undefined), isValidBackendToken, validateAccessToken, findInstituteType_params, checkPermissionForRequestedInstitute(PERMISSION.EAS_DIS_EDIT, PERMISSION.EAS_SCH_EDIT), getAssessmentSessionsBySchoolYear);

router.get('/assessment-registrations/paginated/:instituteType', passport.authenticate('jwt', {session: false}, undefined), isValidBackendToken, validateAccessToken, findInstituteType_params, checkPermissionForRequestedInstitute(PERMISSION.EAS_DIS_EDIT, PERMISSION.EAS_SCH_EDIT), getAssessmentStudentsPaginated);


module.exports = router;
5 changes: 4 additions & 1 deletion backend/src/util/Permission.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ const PERMISSION = Object.freeze(
SCHOOL_SDC_VIEW: 'SCH_SDC_VIEW',
SUPERINT: 'SUPERINT',
SECR_TRES: 'SECR_TRES',
GRAD_SCH_EDIT: 'GRAD_SCH_EDIT'
GRAD_SCH_EDIT: 'GRAD_SCH_EDIT',
EAS_DIS_EDIT: 'EAS_DIS_EDIT',
EAS_SCH_EDIT: 'EAS_SCH_EDIT'

}
);

Expand Down
Loading
Loading