From 1b6dc04954bd3ded2f19e6178f0562b204e7a97a Mon Sep 17 00:00:00 2001 From: "QSL\\SumathiT" Date: Fri, 1 Nov 2024 07:05:54 -0700 Subject: [PATCH 1/5] Monitor registrations. --- backend/src/components/cache-service.js | 37 ++ backend/src/components/eas/eas.js | 83 +++- backend/src/components/eas/studentFilters.js | 32 ++ backend/src/config/index.js | 4 +- backend/src/routes/eas.js | 7 +- backend/src/server.js | 12 + .../assessments/AssessmentSessions.vue | 25 +- .../assessments/AssessmentSessionsDetail.vue | 164 +++++++ .../registrations/StudentRegistrations.vue | 220 +++++++++ .../StudentRegistrationsCustomTable.vue | 278 +++++++++++ .../StudentRegistrationsFilter.vue | 430 ++++++++++++++++++ .../assessments/sessions/SessionCard.vue | 33 +- frontend/src/components/util/NavBar.vue | 2 +- frontend/src/router.js | 16 +- frontend/src/utils/constants.js | 4 +- .../StudentRegistrationTableConfiguration.js | 95 ++++ 16 files changed, 1426 insertions(+), 16 deletions(-) create mode 100644 backend/src/components/eas/studentFilters.js create mode 100644 frontend/src/components/assessments/AssessmentSessionsDetail.vue create mode 100644 frontend/src/components/assessments/registrations/StudentRegistrations.vue create mode 100644 frontend/src/components/assessments/registrations/StudentRegistrationsCustomTable.vue create mode 100644 frontend/src/components/assessments/registrations/StudentRegistrationsFilter.vue create mode 100644 frontend/src/utils/eas/StudentRegistrationTableConfiguration.js diff --git a/backend/src/components/cache-service.js b/backend/src/components/cache-service.js index f253237c..cdd9882d 100644 --- a/backend/src/components/cache-service.js +++ b/backend/src/components/cache-service.js @@ -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() { @@ -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 () => { diff --git a/backend/src/components/eas/eas.js b/backend/src/components/eas/eas.js index 42ac8105..75c9d513 100644 --- a/backend/src/components/eas/eas.js +++ b/backend/src/components/eas/eas.js @@ -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 { @@ -16,6 +18,17 @@ async function getAssessmentSessions(req, res) { } } +async function getAssessmentSessionsBySchoolYear(req, res) { + try { + const url = `${config.get('server:eas:assessmentSessionsURL')}/school-year/${req.params.schoolYear}`; + const data = await getData(url); + return res.status(200).json(data); + } catch (e) { + logApiError(e, 'getSessions', 'Error occurred while attempting to GET sessions.'); + return handleExceptionResponse(e, res); + } +} + async function updateAssessmentSession(req, res) { if (req.params.sessionID !== req.body.sessionID) { return res.status(HttpStatus.BAD_REQUEST).json({ @@ -37,7 +50,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.assessmentCenter); + let district = cacheService.getDistrictJSONByDistrictId(school.districtID); + value.schoolNumber = school.mincode; + value.schoolName = getSchoolName(school); + value.districtName = getDistrictName(district); + value.districtNumber = district.districtNumber; + value.districtID = school.districtID; + value.mincode = cacheService.getSchoolBySchoolID(value.schoolID)?.mincode; + 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 }; diff --git a/backend/src/components/eas/studentFilters.js b/backend/src/components/eas/studentFilters.js new file mode 100644 index 00000000..863e7325 --- /dev/null +++ b/backend/src/components/eas/studentFilters.js @@ -0,0 +1,32 @@ +'use strict'; +const { FILTER_OPERATION, VALUE_TYPE, CONDITION} = require('../../util/constants'); + + +function createMoreFiltersSearchCriteria(searchFilter = []) { + let searchCriteriaList = []; + for (const [key, filter] of Object.entries(searchFilter)) { + let pValue = filter ? filter.map(filter => filter.value) : null; + if (key === 'specialCaseCode' && pValue) { + searchCriteriaList.push({ key: 'provincialSpecialCaseCode', value: pValue.toString(), operation: FILTER_OPERATION.IN, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND }); + } + if (key === 'sessionID' && pValue) { + searchCriteriaList.push({ key: 'assessmentEntity.sessionEntity.sessionID', value: pValue[0], operation: FILTER_OPERATION.IN, valueType: VALUE_TYPE.UUID, condition: CONDITION.AND }); + } + + 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 }); + } + } + const search = []; + if (searchCriteriaList.length > 0) { + search.push({ + condition: CONDITION.AND, + searchCriteriaList: searchCriteriaList + }); + } + return search; +} + +module.exports = { + createMoreFiltersSearchCriteria +}; diff --git a/backend/src/config/index.js b/backend/src/config/index.js index cfbbe0a8..4042f7da 100644 --- a/backend/src/config/index.js +++ b/backend/src/config/index.js @@ -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: { diff --git a/backend/src/routes/eas.js b/backend/src/routes/eas.js index 11db8ee8..ee082794 100644 --- a/backend/src/routes/eas.js +++ b/backend/src/routes/eas.js @@ -1,7 +1,7 @@ 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'); @@ -9,7 +9,12 @@ 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; diff --git a/backend/src/server.js b/backend/src/server.js index f3bd4200..9dca9d41 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -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) => { diff --git a/frontend/src/components/assessments/AssessmentSessions.vue b/frontend/src/components/assessments/AssessmentSessions.vue index c21a8440..b5fc801e 100644 --- a/frontend/src/components/assessments/AssessmentSessions.vue +++ b/frontend/src/components/assessments/AssessmentSessions.vue @@ -2,7 +2,25 @@ -

Open Assessment Sessions

+
+

School Year: {{ schoolYear }}

+ + Continue + + +
new Date(a.activeUntilDate) - new Date(b.activeUntilDate)); + this.schoolYear = allsessions[0]?.schoolYear; for (let i = 0; i < allsessions.length; i += 2) { orderedSessions.push(allsessions.slice(i, i + 2)); } @@ -176,6 +196,9 @@ export default { }, formatMonth(month) { return moment(month, 'MM').format('MMMM'); + }, + goToSchoolYearRegistrations() { + this.$router.push({name: 'assessment-session-detail', params: {schoolYear: this.schoolYear.replace(/\//g, '-'), sessionID: null}}); } }, }; diff --git a/frontend/src/components/assessments/AssessmentSessionsDetail.vue b/frontend/src/components/assessments/AssessmentSessionsDetail.vue new file mode 100644 index 00000000..43faeb7d --- /dev/null +++ b/frontend/src/components/assessments/AssessmentSessionsDetail.vue @@ -0,0 +1,164 @@ + + + diff --git a/frontend/src/components/assessments/registrations/StudentRegistrations.vue b/frontend/src/components/assessments/registrations/StudentRegistrations.vue new file mode 100644 index 00000000..550b95aa --- /dev/null +++ b/frontend/src/components/assessments/registrations/StudentRegistrations.vue @@ -0,0 +1,220 @@ + + + + + diff --git a/frontend/src/components/assessments/registrations/StudentRegistrationsCustomTable.vue b/frontend/src/components/assessments/registrations/StudentRegistrationsCustomTable.vue new file mode 100644 index 00000000..95c01761 --- /dev/null +++ b/frontend/src/components/assessments/registrations/StudentRegistrationsCustomTable.vue @@ -0,0 +1,278 @@ + + + + + diff --git a/frontend/src/components/assessments/registrations/StudentRegistrationsFilter.vue b/frontend/src/components/assessments/registrations/StudentRegistrationsFilter.vue new file mode 100644 index 00000000..e5c250d0 --- /dev/null +++ b/frontend/src/components/assessments/registrations/StudentRegistrationsFilter.vue @@ -0,0 +1,430 @@ + + + + + diff --git a/frontend/src/components/assessments/sessions/SessionCard.vue b/frontend/src/components/assessments/sessions/SessionCard.vue index 9ccf51b9..629e0877 100644 --- a/frontend/src/components/assessments/sessions/SessionCard.vue +++ b/frontend/src/components/assessments/sessions/SessionCard.vue @@ -5,12 +5,14 @@ class="d-flex flex-column mt-4" height="100%" > - + - {{ session.courseMonth }} {{ session.courseYear }} Session - - + + {{ session.courseMonth }} {{ session.courseYear }} Session + + + - + @@ -29,7 +31,7 @@ mdi-calendar Registration Open Date: - + {{ formattoDate(session.activeFromDate) }} @@ -42,7 +44,7 @@ mdi-calendar Registration Close Date: - + {{ formattoDate(session.activeUntilDate) }} @@ -53,6 +55,20 @@ + + + + Continue + + + + @@ -75,6 +91,9 @@ export default { formattoDate(date) { return moment(JSON.stringify(date), 'YYYY-MM-DDTHH:mm:ss').format('YYYY/MM/DD'); }, + goToSessionRegistrations() { + this.$router.push({name: 'assessment-session-detail', params: {schoolYear: this.session.schoolYear.replace(/\//g, '-'), sessionID: this.session.sessionID}}); + } }, }; diff --git a/frontend/src/components/util/NavBar.vue b/frontend/src/components/util/NavBar.vue index ee9cbb51..98ed2e76 100644 --- a/frontend/src/components/util/NavBar.vue +++ b/frontend/src/components/util/NavBar.vue @@ -331,7 +331,7 @@ export default { items: [ { title: 'Sessions', - link: 'assessmentsessions', + link: 'assessment-sessions', authorized: this.hasRequiredPermission(this.userInfo, PERMISSION.MANAGE_EAS_SESSIONS_PERMISSION) } ], diff --git a/frontend/src/router.js b/frontend/src/router.js index 4b7d5d0d..4d2b35dc 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -53,6 +53,7 @@ import EDXInvitations from '@/components/secure-message/EDXInvitations.vue'; import CollectionView from '@/components/data-collection/CollectionView.vue'; import PenMatchStudentDetails from '@/components/data-collection/PenMatchStudentDetails.vue'; import AssessmentSessions from '@/components/assessments/AssessmentSessions.vue'; +import AssessmentSessionDetail from '@/components/assessments/AssessmentSessionsDetail.vue'; const router = createRouter({ history: createWebHistory(), @@ -498,8 +499,8 @@ const router = createRouter({ ] }, { - path: '/assessmentsessions', - name: 'assessmentsessions', + path: '/assessment-sessions', + name: 'assessment-sessions', component: AssessmentSessions, meta: { pageTitle: PAGE_TITLES.ASSESSMENT_SESSIONS_MANAGEMENT, @@ -507,6 +508,17 @@ const router = createRouter({ permission: PERMISSION.MANAGE_EAS_SESSIONS_PERMISSION }, }, + { + path: '/assessment-sessions/details/:schoolYear/:sessionID?', + name: 'assessment-session-detail', + component: AssessmentSessionDetail, + props: true, + meta: { + pageTitle: PAGE_TITLES.ASSESSMENT_SESSIONS_MANAGEMENT, + requiresAuth: true, + permission: PERMISSION.MANAGE_EAS_SESSIONS_PERMISSION + }, + }, { path: '/authority/:authorityID', name: 'authorityDetails', diff --git a/frontend/src/utils/constants.js b/frontend/src/utils/constants.js index dfee4990..eec1d899 100644 --- a/frontend/src/utils/constants.js +++ b/frontend/src/utils/constants.js @@ -207,7 +207,9 @@ let object = { }, eas: { BASE_URL: easRoot, - GET_ASSESSMENT_SESSIONS: easRoot + '/assessment-sessions' + GET_ASSESSMENT_SESSIONS: easRoot + '/assessment-sessions', + GET_ASSESSMENT_TYPES: easRoot + '/assessment-types', + GET_ASSESSMENT_STUDENTS_PAGINATED: easRoot + '/assessment-registrations/paginated', } }; diff --git a/frontend/src/utils/eas/StudentRegistrationTableConfiguration.js b/frontend/src/utils/eas/StudentRegistrationTableConfiguration.js new file mode 100644 index 00000000..ee879511 --- /dev/null +++ b/frontend/src/utils/eas/StudentRegistrationTableConfiguration.js @@ -0,0 +1,95 @@ +/** + * Filters + */ + + +export const ASSESSMENT_TYPE_CODE_FILTER = Object.freeze( + { + heading: 'Assessment / Course', + id: 'assessmentTypeCode', + multiple: true, + key: 'assessmentTypeCode', + filterOptions: [ + ] + } +); + +export const SPECIAL_CASE_FILTER = Object.freeze( + { + heading: 'Special Case', + id: 'specialCaseCode', + multiple: true, + key: 'specialCaseCode', + filterOptions: [ + { + title: 'Aegrotat', + id: 'aegrotat', + value: 'A' + }, + { + title: 'Exemption', + id: 'exemption', + value: 'E' + }, + { + title: 'Disqualified', + id: 'disqualified', + value: 'D' + } + ] + } +); + +export const PROFICIENCY_SCORE_FILTER = Object.freeze( + { + heading: 'Proficiency Score', + id: 'proficiencyScore', + multiple: true, + key: 'proficiencyScore', + filterOptions: [ + { + title: 'Have Results', + id: 'results', + value: 'true' + }, + { + title: 'No Results Received', + id: 'noResults', + value: 'false' + } + ] + } +); + +export const REGISTRATIONS = Object.freeze( + { + schoolTableHeaders: [ + { title: 'Session', key: 'sessionName'}, + { title: 'District', key: 'districtName' }, + { title: 'School', key: 'schoolName' }, + { title: 'Assessment Center', key: 'assessmentCenterName' }, + { title: 'PEN', key: 'pen' }, + { title: 'Local ID', key: 'localID' }, + { title: 'Surname', key: 'surName' }, + { title: 'Course Name (Code)', key: 'assessmentTypeName' }, + { title: 'Special Case', key: 'provincialSpecialCaseName' }, + { title: 'Proficiency Score', key: 'finalPercentage' }, + ], + sessionTableHeaders: [ + { title: 'District', key: 'districtName' }, + { title: 'School', key: 'schoolName' }, + { title: 'Assessment Center', key: 'assessmentCenterName' }, + { title: 'PEN', key: 'pen' }, + { title: 'Local ID', key: 'localID' }, + { title: 'Surname', key: 'surName' }, + { title: 'Course Name (Code)', key: 'assessmentTypeName' }, + { title: 'Special Case', key: 'provincialSpecialCaseName' }, + { title: 'Proficiency Score', key: 'finalPercentage' }, + ], + allowedFilters: { + assessmentTypeCode: ASSESSMENT_TYPE_CODE_FILTER, + specialCaseCode: SPECIAL_CASE_FILTER, + proficienyScore: PROFICIENCY_SCORE_FILTER + } + }); + \ No newline at end of file From e78387246d1a398284de661f9a69df3e86e060ef Mon Sep 17 00:00:00 2001 From: "QSL\\SumathiT" Date: Tue, 5 Nov 2024 17:58:10 -0800 Subject: [PATCH 2/5] EAC-22 & EAC-36. --- backend/src/components/eas/eas.js | 21 +- backend/src/components/eas/studentFilters.js | 147 +++++++++- .../assessments/AssessmentSessions.vue | 72 ++--- .../assessments/AssessmentSessionsDetail.vue | 52 ++-- .../registrations/StudentRegistrations.vue | 23 +- .../StudentRegistrationsFilter.vue | 258 +++++++++++++----- .../StudentRegistrationTableConfiguration.js | 34 ++- tools/config/update-configmap.sh | 5 +- 8 files changed, 444 insertions(+), 168 deletions(-) diff --git a/backend/src/components/eas/eas.js b/backend/src/components/eas/eas.js index 75c9d513..bd3b49c8 100644 --- a/backend/src/components/eas/eas.js +++ b/backend/src/components/eas/eas.js @@ -21,10 +21,15 @@ async function getAssessmentSessions(req, res) { async function getAssessmentSessionsBySchoolYear(req, res) { try { const url = `${config.get('server:eas:assessmentSessionsURL')}/school-year/${req.params.schoolYear}`; - const data = await getData(url); + 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.'); + logApiError(e, 'getSessions', 'Error occurred while attempting to GET sessions by school year.'); return handleExceptionResponse(e, res); } } @@ -71,29 +76,29 @@ async function getAssessmentStudentsPaginated(req, res) { } }; - 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.assessmentCenter); + let assessmentCenter = cacheService.getSchoolBySchoolID(value.assessmentCenterID); let district = cacheService.getDistrictJSONByDistrictId(school.districtID); + value.schoolNumber = school.mincode; value.schoolName = getSchoolName(school); - value.districtName = getDistrictName(district); - value.districtNumber = district.districtNumber; value.districtID = school.districtID; - value.mincode = cacheService.getSchoolBySchoolID(value.schoolID)?.mincode; + 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) { diff --git a/backend/src/components/eas/studentFilters.js b/backend/src/components/eas/studentFilters.js index 863e7325..7d583a82 100644 --- a/backend/src/components/eas/studentFilters.js +++ b/backend/src/components/eas/studentFilters.js @@ -1,23 +1,105 @@ 'use strict'; const { FILTER_OPERATION, VALUE_TYPE, CONDITION} = require('../../util/constants'); - function createMoreFiltersSearchCriteria(searchFilter = []) { let searchCriteriaList = []; + + let districtNameNumberFilter = []; + let schoolNameNumberFilter = []; + let assessmentCenterNameNumberFilter = []; + let scoreRangeList = []; + for (const [key, filter] of Object.entries(searchFilter)) { let pValue = filter ? filter.map(filter => filter.value) : null; - if (key === 'specialCaseCode' && pValue) { - searchCriteriaList.push({ key: 'provincialSpecialCaseCode', value: pValue.toString(), operation: FILTER_OPERATION.IN, valueType: VALUE_TYPE.STRING, condition: CONDITION.AND }); + + //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 }); } + if (key === 'sessionID' && pValue) { searchCriteriaList.push({ key: 'assessmentEntity.sessionEntity.sessionID', value: pValue[0], operation: FILTER_OPERATION.IN, valueType: VALUE_TYPE.UUID, condition: CONDITION.AND }); } - 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 === 'sessions' && 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.GREATER_THAN, valueType: VALUE_TYPE.INTEGER, condition: CONDITION.AND }); + } else { + searchCriteriaList.push({ key: 'proficiencyScore', value:0, operation: FILTER_OPERATION.LESS_THAN_OR_EQUAL_TO, valueType: VALUE_TYPE.INTEGER, condition: CONDITION.AND }); + } + } + + if (key === 'proficienyScoreRange' && pValue) { + scoreRangeList = createScoreRangeFilter(pValue); } + + } + 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(scoreRangeList.length > 0) { + search.push({ + condition: CONDITION.AND, + searchCriteriaList: scoreRangeList + }); } - const search = []; if (searchCriteriaList.length > 0) { search.push({ condition: CONDITION.AND, @@ -27,6 +109,59 @@ function createMoreFiltersSearchCriteria(searchFilter = []) { 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; +} + +function createScoreRangeFilter(pValue) { + let scoreRangeList = []; + + scoreRangeList.push({key:'proficiencyScore', value: pValue[0][1], operation: FILTER_OPERATION.LESS_THAN_OR_EQUAL_TO, valueType: VALUE_TYPE.INTEGER, condition: CONDITION.AND}); + scoreRangeList.push({key:'proficiencyScore', value: pValue[0][0], operation: FILTER_OPERATION.GREATER_THAN_OR_EQUAL_TO, valueType: VALUE_TYPE.INTEGER, condition: CONDITION.AND}); + if(pValue[0][0] === '0'){ + scoreRangeList.push({key:'proficiencyScore', value: null, operation: FILTER_OPERATION.EQUAL, valueType: VALUE_TYPE.STRING, condition: CONDITION.OR}); + } + return scoreRangeList; +} + module.exports = { createMoreFiltersSearchCriteria }; diff --git a/frontend/src/components/assessments/AssessmentSessions.vue b/frontend/src/components/assessments/AssessmentSessions.vue index b5fc801e..7779ae2c 100644 --- a/frontend/src/components/assessments/AssessmentSessions.vue +++ b/frontend/src/components/assessments/AssessmentSessions.vue @@ -5,21 +5,21 @@

School Year: {{ schoolYear }}

- Continue - - + variant="text" + @click="goToSchoolYearRegistrations()" + > + View all Open Sessions in the current school year + +
@@ -58,11 +58,11 @@ { value: 25, title: '25' }, { value: 50, title: '50' }, { value: 100, title: '100' }, - { value: -1, title: 'All' } ]" :hover="true" class="fill-height" style="border-radius: 0" + @click:row="goToSessionRegistrations" >