Skip to content

Commit

Permalink
Handle cases where a student has multiple citizenships
Browse files Browse the repository at this point in the history
  • Loading branch information
valtterikantanen committed Dec 16, 2024
1 parent 83d4bd2 commit ae60a38
Show file tree
Hide file tree
Showing 14 changed files with 53 additions and 58 deletions.
9 changes: 0 additions & 9 deletions services/backend/src/models/student.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,6 @@ export class Student extends Model<InferAttributes<Student>> {
@Column(DataType.JSONB)
citizenships!: Name[]

@Column(DataType.STRING)
home_country_fi!: string

@Column(DataType.STRING)
home_country_sv!: string

@Column(DataType.STRING)
home_country_en!: string

@Column(DataType.STRING)
gender_code!: GenderCode

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,7 @@ const getStudents = async (studentNumbers: string[]) => {
'firstnames',
'lastname',
'studentnumber',
'home_country_en',
'home_country_fi',
'home_country_sv',
'citizenships',
'dateofuniversityenrollment',
'creditcount',
'abbreviatedname',
Expand Down
8 changes: 2 additions & 6 deletions services/backend/src/services/populations/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,7 @@ const formatStudentForPopulationStatistics = (
tags,
birthdate,
sis_person_id,
home_country_fi,
home_country_sv,
home_country_en,
citizenships,
} = student

const criteriaCoursesBySubstitutions = criteria?.allCourses
Expand Down Expand Up @@ -271,9 +269,7 @@ const formatStudentForPopulationStatistics = (
birthdate,
studyplans,
sis_person_id,
home_country_en,
home_country_fi,
home_country_sv,
citizenships,
criteriaProgress: toProgressCriteria(),
curriculumVersion: getCurriculumVersion(correctStudyplan[0]?.curriculum_period_id),
transferredStudyright,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const getStudyRightsInProgramme = async (
if (includeStudentsAndCredits) {
include.push({
model: Student,
attributes: ['gender_code', 'home_country_en'],
attributes: ['gender_code', 'citizenships'],
include: [
{
model: Credit,
Expand Down
20 changes: 12 additions & 8 deletions services/backend/src/services/studyProgramme/studyTrackStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,16 +267,20 @@ const getMainStatsByTrackAndYear = async (
}
}

const studentHomeCountry = studyRight.student.home_country_en
const studentCitizenships = studyRight.student.citizenships

if (studentHomeCountry === 'Finland') {
yearlyStats[year][programmeOrStudyTrack].finnish += 1
} else {
yearlyStats[year][programmeOrStudyTrack].otherCountries += 1
if (!yearlyStats[year][programmeOrStudyTrack].otherCountriesCounts[studentHomeCountry]) {
yearlyStats[year][programmeOrStudyTrack].otherCountriesCounts[studentHomeCountry] = 0
for (const citizenship of studentCitizenships) {
const country = citizenship.en
if (!country) {
continue
}
if (country === 'Finland') {
yearlyStats[year][programmeOrStudyTrack].finnish += 1
} else {
yearlyStats[year][programmeOrStudyTrack].otherCountries += 1
yearlyStats[year][programmeOrStudyTrack].otherCountriesCounts[country] ??= 0
yearlyStats[year][programmeOrStudyTrack].otherCountriesCounts[country] += 1
}
yearlyStats[year][programmeOrStudyTrack].otherCountriesCounts[studentHomeCountry] += 1
}

if (!hasGraduated) return
Expand Down
5 changes: 5 additions & 0 deletions services/frontend/src/common/InfoToolTips/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ export const filterToolTips = {
Valitse opiskelijoita sen mukaan, minä vuonna heidän ensimmäinen opinto-oikeutensa yliopistolla alkoi (ei siis ainoastaan tarkasteltavan tutkinnon oikeus). Avoimia opinto-oikeuksia ei oteta huomioon.
`,
},
citizenship: {
label: null,
short:
'Rajaa opiskelijoita kansalaisuuden perusteella. Tulokseen sisältyvät opiskelijat, joilla on valitun valtion kansalaisuus, riippumatta siitä, onko heillä myös muita kansalaisuuksia.',
},
}
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export const studyProgrammeToolTips: Record<string, string> = {
Lukukausi-ilmoittautumisissa huomioidaan vain se opiskeluoikeus, joka liittyy tarkasteltavaan koulutusohjelmaan. Vaikka opiskelija olisi ilmoittautunut toiseen opiskeluoikeuteen läsnäolevaksi, mutta hän on laiminlyönyt ilmoittautumisen tarkasteltavaan koulutusohjelmaan liittyvään opiskeluoikeuteen, hänet lasketaan ryhmään ”Inactive”.
Paksummilla pystyviivoilla eroteltujen kategorioiden (**Current status**, **Gender**, **Countries**) sarakkeet tuottavat yhteenlaskettuna kentän **All** arvon.
Paksummilla pystyviivoilla eroteltujen kategorioiden (**Current status**, **Gender**) sarakkeet tuottavat yhteenlaskettuna kentän **All** arvon. **Citizenships**-kategoriat (**Finland** ja **Other**) voivat tuottaa yhteenlaskettuna suuremman tuloksen, koska opiskelijoilla voi olla useampi kuin yksi kansalaisuus.
Jos sivun yläosassa on valittuna ”All study rights” (oletus), mukana ovat myös ohjelmaan siirtyneet ja ohjelmasta pois siirtyneet opiskelijat.
Expand Down
31 changes: 19 additions & 12 deletions services/frontend/src/components/FilterView/filters/citizenship.jsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
import { orderBy } from 'lodash'
import { Form, Dropdown } from 'semantic-ui-react'

import { filterToolTips } from '@/common/InfoToolTips'
import { useLanguage } from '@/components/LanguagePicker/useLanguage'
import { createFilter } from './createFilter'

const CitizenshipFilterCard = ({ options, onOptionsChange, withoutSelf }) => {
const { getTextIn } = useLanguage()
const { selected } = options

const dropdownOptions = withoutSelf().reduce((citizenships, student) => {
const { home_country_en: homeCountryEn, home_country_fi: homeCountryFi, home_country_sv: homeCountrySv } = student
const dropdownOptions = withoutSelf().reduce((options, student) => {
for (const citizenship of student.citizenships) {
const countryName = citizenship.en
if (options.some(option => option.value === countryName)) {
continue
}
const count = withoutSelf().filter(student =>
student.citizenships.some(citizenship => citizenship.en === countryName)
).length
const country = getTextIn(citizenship)

if (citizenships.every(option => option.value !== homeCountryEn)) {
const count = withoutSelf().filter(student => student.home_country_en === homeCountryEn).length
const homeCountry = getTextIn({ fi: homeCountryFi, en: homeCountryEn, sv: homeCountrySv })

citizenships.push({
key: homeCountryEn,
value: homeCountryEn,
text: `${homeCountry} (${count})`,
options.push({
key: countryName,
value: countryName,
text: `${country} (${count})`,
count,
})
}

return citizenships
return options
}, [])

const sortedDropdownOptions = orderBy(dropdownOptions, ['count', 'text'], ['desc', 'asc'])
Expand Down Expand Up @@ -56,10 +61,12 @@ export const citizenshipFilter = createFilter({
selected: '',
},

info: filterToolTips.citizenship,

isActive: ({ selected }) => selected !== '',

filter(student, { selected }) {
return selected === student.home_country_en
return student.citizenships.some(citizenship => citizenship.en === selected)
},

component: CitizenshipFilterCard,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,11 +534,12 @@ export const GeneralTab = ({
title: 'Gender',
getRowVal: student => getGender(student.gender_code),
},
citizenship: {
key: 'citizenship',
title: 'Citizenship',
getRowVal: student =>
getTextIn({ fi: student.home_country_fi, en: student.home_country_en, sv: student.home_country_sv }),
citizenships: {
key: 'citizenships',
title: 'Citizenships',
getRowVal: student => student.citizenships.map(getTextIn).sort(),
formatValue: value => value.join(', '),
filterType: 'multi',
},
option: (isBachelorsProgramme || isMastersProgramme) && {
key: 'option',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const GeneralTabContainer = ({ studyGuidanceGroup, variant, ...props }) =
const columns = ['credits.since', 'programme', 'startYear']
if (studyGuidanceGroup?.tags?.studyProgramme)
columns.push(
'citizenship',
'citizenships',
'credits.hops',
'curriculumPeriod',
'endDate',
Expand Down Expand Up @@ -81,7 +81,7 @@ export const GeneralTabContainer = ({ studyGuidanceGroup, variant, ...props }) =
coursePopulation: ['enrollmentDate', 'gradeForSingleCourse', 'language', 'passDate', 'programme', 'startYear'],
population: [
'admissionType',
'citizenship',
'citizenships',
'credits.hops',
'credits.studyright',
'curriculumPeriod',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,10 +336,10 @@ export const StudyTrackDataTable = ({
</Table.HeaderCell>
<Table.HeaderCell colSpan={!showPercentages ? 2 : 4} style={{ borderLeftWidth: 'thick' }}>
<Popup
content="Hover over 'Other' cell to see from which countries students are coming."
content="Hover over 'Other' cell to see which citizenships (other than Finland) students have."
trigger={
<div>
Countries <Icon name="question circle" />
Citizenships <Icon name="question circle" />
</div>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export const FacultyStudentDataTable = ({
setVisible(arrayToModify)
}
const infoText =
"Hover over 'Other' cell to see from which countries students are coming. Shown only for study programmes."
"Hover over 'Other' cell to see which citizenships (other than Finland) students have. Shown only for study programmes."

return (
<Section>
Expand All @@ -133,7 +133,7 @@ export const FacultyStudentDataTable = ({
<TableCell colSpan={!showPercentages ? 3 : 6}>Gender</TableCell>
<TableCell colSpan={!showPercentages ? 2 : 4}>
<Stack direction="row" gap={1}>
Countries
Citizenships
<InfoBox content={infoText} mini />
</Stack>
</TableCell>
Expand Down
3 changes: 0 additions & 3 deletions updater/sis-updater-worker/src/db/models/student.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@ Student.init(
secondary_email: { type: STRING },
national_student_number: { type: STRING },
citizenships: { type: JSONB },
home_country_fi: { type: STRING },
home_country_sv: { type: STRING },
home_country_en: { type: STRING },
gender_code: { type: STRING },
sis_person_id: { type: STRING },
hasPersonalIdentityCode: { type: BOOLEAN },
Expand Down
4 changes: 0 additions & 4 deletions updater/sis-updater-worker/src/updater/mapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ const studentMapper = (attainments, studyRights, attainmentsToBeExluced) => stud
const gender_code = parseGender(gender_urn)

const citizenships = (student.citizenships ?? []).map(countryUrn => getCountry(countryUrn).name)
const home_country = student.citizenships ? getCountry(student.citizenships[0]) : null

const studyRightsOfStudent = studyRights.filter(SR => SR.person_id === id)

Expand Down Expand Up @@ -120,9 +119,6 @@ const studentMapper = (attainments, studyRights, attainmentsToBeExluced) => stud
creditcount: calculateTotalCreditsFromAttainments(attainmentsOfStudent),
dateofuniversityenrollment,
citizenships,
home_country_fi: home_country ? home_country.name.fi : null,
home_country_sv: home_country ? home_country.name.sv : null,
home_country_en: home_country ? home_country.name.en : null,
sis_person_id: id,
hasPersonalIdentityCode: has_personal_identity_code,
}
Expand Down

0 comments on commit ae60a38

Please sign in to comment.