Skip to content

Commit

Permalink
[Close to graduation] Add earliest HOPS attainment and number of abse…
Browse files Browse the repository at this point in the history
…nt semesters
  • Loading branch information
valtterikantanen committed Nov 14, 2024
1 parent 3219764 commit 71f3abc
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 20 deletions.
48 changes: 30 additions & 18 deletions services/backend/src/services/populations/closeToGraduation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import { col, Op, where } from 'sequelize'

import { Course, Credit, Student, Studyplan, SISStudyRight, SISStudyRightElement } from '../../models'
import { Name } from '../../shared/types'
import { CreditTypeCode, DegreeProgrammeType, ExtentCode, SemesterEnrollment } from '../../types'
import { CreditTypeCode, DegreeProgrammeType, EnrollmentType, ExtentCode, SemesterEnrollment } from '../../types'
import { redisClient } from '../redis'
import { getCurriculumVersion } from './shared'

export const CLOSE_TO_GRADUATION_REDIS_KEY = 'CLOSE_TO_GRADUATION_DATA'

type LatestAttainmentDates = {
total?: Date
hops?: Date
type AttainmentDates = {
latestTotal?: Date
latestHops?: Date
earliestHops?: Date
}

type AccumulatorType = {
Expand Down Expand Up @@ -39,22 +40,23 @@ type AccumulatorType = {
startedAt: Date
degreeProgrammeType: DegreeProgrammeType
}
latestAttainmentDates: LatestAttainmentDates
attainmentDates: AttainmentDates
numberOfAbsentSemesters: number
curriculumPeriod: string | null
credits: {
hops: number
all: number
}
}

const findThesisAndLatestAttainments = (
const findThesisAndLatestAndEarliestAttainments = (
studyPlan: Studyplan,
attainments: Credit[],
degreeProgrammeType: DegreeProgrammeType,
studyRightId: string
) => {
let thesisData: Credit | undefined
const latestAttainmentDates: LatestAttainmentDates = {}
const attainmentDates: AttainmentDates = {}
const thesisCodes = {
[DegreeProgrammeType.BACHELOR]: 'urn:code:course-unit-type:bachelors-thesis',
[DegreeProgrammeType.MASTER]: 'urn:code:course-unit-type:masters-thesis',
Expand All @@ -67,25 +69,29 @@ const findThesisAndLatestAttainments = (
) {
thesisData = attainment
}
if (!latestAttainmentDates.total) {
latestAttainmentDates.total = attainment.attainment_date
if (!attainmentDates.latestTotal) {
attainmentDates.latestTotal = attainment.attainment_date
}
if (!latestAttainmentDates.hops && studyPlan.included_courses.includes(attainment.course?.code)) {
latestAttainmentDates.hops = attainment.attainment_date
}
if (thesisData && latestAttainmentDates.total && latestAttainmentDates.hops) {
break
if (studyPlan.included_courses.includes(attainment.course?.code)) {
if (!attainmentDates.latestHops) {
attainmentDates.latestHops = attainment.attainment_date
}
if (
!attainmentDates.earliestHops ||
attainment.attainment_date.getTime() < attainmentDates.earliestHops.getTime()
) {
attainmentDates.earliestHops = attainment.attainment_date
}
}
}

return { latestAttainmentDates, thesisData }
return { attainmentDates, thesisData }
}

const formatStudent = (student: Student) => {
const {
studentnumber: studentNumber,
abbreviatedname: name,

sis_person_id,
email,
phone_number: phoneNumber,
Expand All @@ -101,14 +107,19 @@ const formatStudent = (student: Student) => {
semesterEnrollments,
} = studyRight

const numberOfAbsentSemesters = (semesterEnrollments ?? []).reduce(
(acc, enrollment) => (enrollment.type === EnrollmentType.ABSENT ? acc + 1 : acc),
0
)

const {
code: programmeCode,
name: programmeName,
studyTrack,
startDate: programmeStartDate,
degreeProgrammeType,
} = studyRightElements[0]
const { latestAttainmentDates, thesisData } = findThesisAndLatestAttainments(
const { attainmentDates, thesisData } = findThesisAndLatestAndEarliestAttainments(
studyPlan,
student.credits,
degreeProgrammeType,
Expand Down Expand Up @@ -136,7 +147,8 @@ const formatStudent = (student: Student) => {
startedAt: programmeStartDate,
degreeProgrammeType,
},
latestAttainmentDates,
attainmentDates,
numberOfAbsentSemesters,
curriculumPeriod: getCurriculumVersion(studyPlan.curriculum_period_id),
credits: {
hops: studyPlan.completed_credits,
Expand Down
24 changes: 22 additions & 2 deletions services/frontend/src/components/CloseToGraduation/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,13 @@ const getColumns = (
getRowContent: row => getSemesterEnrollmentsContent(row.student, row.studyright),
getRowVal: row => getSemesterEnrollmentsVal(row.student, row.studyright),
},
{
key: 'semestersAbsent',
title: 'Semesters\nabsent',
getRowVal: row => row.numberOfAbsentSemesters,
helpText:
'The number of semesters the student has been absent (both statutory and non-statutory absences) during their study right',
},
{
key: 'semesterEnrollmentsForExcel',
title: 'Enrollment status',
Expand Down Expand Up @@ -188,19 +195,32 @@ const getColumns = (
{
key: 'latestAttainmentHops',
title: 'HOPS',
getRowVal: row => reformatDate(row.latestAttainmentDates.hops, ISO_DATE_FORMAT),
getRowVal: row => reformatDate(row.attainmentDates.latestHops, ISO_DATE_FORMAT),
filterType: 'date',
helpText: 'The date when the student last completed a course in their primary study plan',
},
{
key: 'latestAttainmentTotal',
title: 'Total',
getRowVal: row => reformatDate(row.latestAttainmentDates.total, ISO_DATE_FORMAT),
getRowVal: row => reformatDate(row.attainmentDates.latestTotal, ISO_DATE_FORMAT),
filterType: 'date',
helpText: 'The date when the student last completed any course at the university',
},
],
},
{
key: 'earliestAttainmentDates',
title: 'Earliest\nattainment date',
children: [
{
key: 'earliestAttainmentHops',
title: 'HOPS',
getRowVal: row => reformatDate(row.attainmentDates.earliestHops, ISO_DATE_FORMAT),
filterType: 'date',
helpText: 'The date when the student first completed a course in their primary study plan',
},
],
},
]
}

Expand Down

0 comments on commit 71f3abc

Please sign in to comment.