Skip to content

Commit

Permalink
Merge pull request #890 from UniversityOfHelsinkiCS/trunk
Browse files Browse the repository at this point in the history
Enable 'show oodikone as this user' button + remove legacy columns from user db
  • Loading branch information
ikuisma authored May 14, 2019
2 parents 8a8d3eb + 071c1ea commit 02745c8
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class PopulationStudents extends Component {
.reduce((acc, elemArr) => {
elemArr.filter(el => el.element_detail.type === 30).forEach(el =>
acc.push(el.element_detail.name.fi))
return acc.join(', ')
return acc
}, []))

const columns = []
Expand Down Expand Up @@ -360,7 +360,7 @@ class PopulationStudents extends Component {
'transferred from': (s.transferredStudyright ? transferFrom(s) : ''),
priority: priorityText(s.studyrights),
extent: extentCodes(s.studyrights),
studytrack: studytrack(s.studyrights),
studytrack: studytrack(s.studyrights).join(', '),
'updated at': reformatDate(s.updatedAt, 'YYYY-MM-DD hh:mm:ss'),
'mandatory total passed': totalMandatoryPassed(s.studentNumber),
...sortedMandatory.reduce((acc, m) => {
Expand Down
23 changes: 15 additions & 8 deletions services/oodikone2-frontend/src/components/UserPage/index.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import React, { Component } from 'react'
import { Button, Card, Divider, List, Icon } from 'semantic-ui-react'
import { Button, Card, Divider, List, Icon, Popup } from 'semantic-ui-react'
import { connect } from 'react-redux'
import _ from 'lodash'
import { withRouter } from 'react-router'
import { string, number, shape, bool, arrayOf, func, object } from 'prop-types'
import { getTextIn } from '../../common'
import { getTextIn, getRolesWithoutRefreshToken } from '../../common'
import { removeUserUnits, getAccessGroups } from '../../redux/users'

import { getDegreesAndProgrammesUnfiltered } from '../../redux/populationDegreesAndProgrammesUnfiltered'
import { superLogin } from '../../apiConnection'
import AccessRights from './AccessRights'
Expand Down Expand Up @@ -143,15 +142,22 @@ class UserPage extends Component {
return e
})
}

return this.props.accessGroups ?
<div>
<Button icon="arrow circle left" content="Back" onClick={this.props.goBack} />
<Divider />
<Card.Group>
<Card fluid>
<Card.Content>
<Card.Header content={user.full_name} />
<Card.Header>
{ this.props.isAdmin && user.is_enabled && (
<Popup
content="Show Oodikone as this user"
trigger={<Button floated="right" circular size="tiny" basic icon="spy" onClick={this.superLogin} />}
/>
)}
{user.full_name}
</Card.Header>
<Divider />
<Card.Meta content={user.username} />
<Card.Meta content={user.email} />
Expand Down Expand Up @@ -219,15 +225,16 @@ UserPage.propTypes = {
push: func.isRequired
}).isRequired,
getAccessGroups: func.isRequired,
accessGroups: arrayOf(object).isRequired
accessGroups: arrayOf(object).isRequired,
isAdmin: bool.isRequired
}

const mapStateToProps = state => ({
language: state.settings.language,
units: state.units.data,
associations: state.populationDegreesAndProgrammesUnfiltered.data,
pending: !!state.populationDegreesAndProgrammesUnfiltered.pending,
accessGroups: state.users.accessGroupsData || []
accessGroups: state.users.accessGroupsData || [],
isAdmin: getRolesWithoutRefreshToken().includes('admin')
})

export default connect(mapStateToProps, {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
up: async (queryInterface) => {
await queryInterface.removeColumn('users', 'is_enabled')
},
down: async () => {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
up: async (queryInterface) => {
await queryInterface.removeColumn('users', 'czar')
await queryInterface.removeColumn('users', 'admin')
},
down: async () => {
}
}
4 changes: 1 addition & 3 deletions services/oodikone2-userservice/src/models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,7 @@ const User = sequelize.define('users',
unique: true
},
email: { type: Sequelize.STRING },
language: { type: Sequelize.STRING },
admin: { type: Sequelize.BOOLEAN },
czar: { type: Sequelize.BOOLEAN }
language: { type: Sequelize.STRING }
},
{
tableName: 'users',
Expand Down
1 change: 0 additions & 1 deletion services/oodikone2-userservice/src/services/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ const createUser = async (username, fullname, email) => {
return User.create({
username: username,
full_name: fullname,
czar: false,
email
})
}
Expand Down
12 changes: 3 additions & 9 deletions services/oodikone2-userservice/src/tests/users.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,21 @@ const default_users = [
full_name: 'Pekka Pouta',
username: 'poutaukko',
email: '[email protected]',
language: 'finnish',
admin: false,
czar: false
language: 'finnish'
},
{
id: 666,
full_name: 'Sylvester Stallone',
username: 'rambo666',
email: '[email protected]',
language: 'americano',
admin: false,
czar: true
language: 'americano'
},
{
id: 665,
full_name: 'Morgan Freeman',
username: 'freeman',
email: '[email protected]',
language: 'americano',
admin: false,
czar: false
language: 'americano'
}
]

Expand Down
64 changes: 46 additions & 18 deletions services/updater_writer/updater/database_updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,58 @@ const {
} = require('../models/index')
const { updateAttainmentDates } = require('./update_attainment_dates')

const deleteStudentStudyrights = async (studentnumber, transaction) => {
console.log(studentnumber)
await Studyright.destroy({
where: {
student_studentnumber: studentnumber
}
}, { transaction })
await StudyrightElement.destroy({
where: {
studentnumber
}
}, { transaction })
}

const updateAttainments = (studyAttainments, transaction) => studyAttainments.map(async ({ credit, creditTeachers, teachers, course }) => {
await Promise.all([
await Course.upsert(course, { transaction }),
await Credit.upsert(credit, { transaction }),
])
await Promise.all([
Promise.all(course.disciplines.map(courseDiscipline => { CourseDisciplines.upsert(courseDiscipline, { transaction }) })),
Promise.all(course.providers.map(provider => Provider.upsert(provider, { transaction }))),
Promise.all(course.courseproviders.map(courseProvider => CourseProvider.upsert(courseProvider, { transaction }))),
teachers && Promise.all(teachers.map(teacher => Teacher.upsert(teacher, { transaction }))),
Promise.all(creditTeachers.map(cT => CreditTeacher.upsert(cT, { transaction })))
])
})

const updateStudyRights = (studyRights, transaction) => studyRights.map(async ({ studyRightExtent, studyright, elementDetails, studyRightElements, transfers }) => {
await Promise.all([
StudyrightExtent.upsert(studyRightExtent, { transaction }),
Studyright.create(studyright, { transaction })
])
await Promise.all([
Promise.all(elementDetails.map(elementdetails => ElementDetails.upsert(elementdetails, { transaction }))),
Promise.all(studyRightElements.map(StudyRightElement => StudyrightElement.create(StudyRightElement, { transaction }))),
Promise.all(transfers.map(transfer => Transfers.upsert(transfer, { transaction })))
])
})

const updateStudent = async (student) => {
const { studentInfo, studyAttainments, semesterEnrollments, studyRights } = student
const transaction = await sequelize.transaction()
try {
await deleteStudentStudyrights(studentInfo.studentnumber, transaction) // this needs to be done because Oodi just deletes deprecated studyrights from students ( big yikes )

await Student.upsert(studentInfo, { transaction })
await Promise.all(semesterEnrollments.map(SE => SemesterEnrollment.upsert(SE, { transaction })))
await Promise.all(studyAttainments.map(async ({ credit, creditTeachers, teachers, course }) => Promise.all([
Course.upsert(course, { transaction }),
course.disciplines && Promise.all(course.disciplines.map(async courseDiscipline => { CourseDisciplines.upsert(courseDiscipline, { transaction }) })),
course.providers && Promise.all(course.providers.map(provider => Provider.upsert(provider, { transaction }))),
course.courseproviders && Promise.all(course.courseproviders.map(courseProvider => CourseProvider.upsert(courseProvider, { transaction }))),
Credit.upsert(credit, { transaction }),
teachers && Promise.all(teachers.map(teacher => Teacher.upsert(teacher, { transaction }))),
creditTeachers && Promise.all(creditTeachers.map(cT => CreditTeacher.upsert(cT, { transaction })))
])))
if (studyRights) {
await Promise.all(studyRights.map(async ({ studyRightExtent, studyright, elementDetails, studyRightElements,transfers }) => Promise.all([
StudyrightExtent.upsert(studyRightExtent, { transaction }),
Studyright.upsert(studyright, { transaction }),
Promise.all(elementDetails.map(elementdetails => ElementDetails.upsert(elementdetails, { transaction }))),
Promise.all(studyRightElements.map(StudyRightElement => StudyrightElement.upsert(StudyRightElement, { transaction }))),
Promise.all(transfers.map(transfer => Transfers.upsert(transfer, { transaction })))
])))
}
await Promise.all(updateAttainments(studyAttainments, transaction))

if (studyRights) await Promise.all(updateStudyRights(studyRights, transaction))

await transaction.commit()
} catch (err) {
console.log(err)
Expand Down
98 changes: 86 additions & 12 deletions services/updater_writer/updater/database_updater.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ describe('Updater works', () => {

})
describe('Updater writes students the right way', () => {
test('Student info is written to database', async () => {

test('Student info is written to database', async () => {
const students = await Student.findAll({
order: [
['studentnumber', 'DESC']]
Expand Down Expand Up @@ -289,14 +289,77 @@ describe('Updater works', () => {
})
describe('Updater updates existing students correctly', () => {
beforeAll(async () => {
const { studentInfo, studyRights, studyAttainments, semesterEnrollments } = students[0]
students[0].studentInfo = { ...studentInfo, email: 'Calgary.Flames@NHLonJätettä.fi', mobile: '0400521981', address: 'Yliopistonkatu 4', creditcount: 322, age: 41, lastname: 'Tauriainen', gender_code: 1, abbreviatedname: 'Tauriainen Maria Helena' }
const newCredit = { id: 'ayyyyylmao', grade: '5', credits: 5, ordering: '2019.05.04', credittypecode: 1, student_studentnumber: '011120775', attainment_date: new Date(), course_code: '420_666', semestercode: 138, isStudyModule: false }
const newCourse = { code: '420_666', name: { fi: 'Kaljan juonti', en: 'Beer drinking', sv: 'dryckade öl' }, latest_instance_date: new Date(), is_study_module: false, coursetypecode: 1, disciplines: [], startdate: new Date(), enddate: new Date(), providers: [], courseproviders: [] }
const newCreditTeachers = [{ credit_id: 'ayyyyylmao', teacher_id: '9016417' }]
const newAttainment = { credit: newCredit, creditTeachers: newCreditTeachers, course: newCourse }
students[0].studyAttainments = [...studyAttainments, newAttainment, { ...students[1].studyAttainments[2], credit: { ...students[1].studyAttainments[2].credit, id:'Kvas', student_studentnumber: '011120775' }}]
students[0].studyAttainments[2] = { ...students[0].studyAttainments[2], credit:{ ...students[0].studyAttainments[2].credit , grade: '0' } }
const { studentInfo, studyRights, studyAttainments } = students[0]
students[0].studentInfo = {
...studentInfo,
email: 'Calgary.Flames@NHLonJätettä.fi',
mobile: '0400521981',
address: 'Yliopistonkatu 4',
creditcount: 322,
age: 41,
lastname: 'Tauriainen',
gender_code: 1,
abbreviatedname: 'Tauriainen Maria Helena'
}
const newCredit = {
id: 'ayyyyylmao',
grade: '5',
credits: 5,
ordering: '2019.05.04',
credittypecode: 1,
student_studentnumber: '011120775',
attainment_date: new Date(),
course_code: '420_666',
semestercode: 138,
isStudyModule: false
}
const newCourse = {
code: '420_666',
name: {
fi: 'Kaljan juonti',
en: 'Beer drinking',
sv: 'dryckade öl'
},
latest_instance_date: new Date(),
is_study_module: false,
coursetypecode: 1,
disciplines: [],
startdate: new Date(),
enddate: new Date(),
providers: [],
courseproviders: []
}

const newCreditTeachers = [
{
credit_id: 'ayyyyylmao',
teacher_id: '9016417'
}
]
const newAttainment = { credit: newCredit, creditTeachers: newCreditTeachers, course: newCourse }
students[0].studyAttainments = [
...studyAttainments,
newAttainment,
{
...students[1].studyAttainments[2],
creditTeachers: [],
credit: {
...students[1].studyAttainments[2].credit,
id: 'Kvas',
student_studentnumber: '011120775'
}
}
]
students[0].studyAttainments[2] = {
...students[0].studyAttainments[2],
credit: {
...students[0].studyAttainments[2].credit,
grade: '0'
}
}
const newStudyRight = { ...studyRights[0], studyright: { ...studyRights[0].studyright, highlevelname: 'Kaljatiede' } }
students[0].studyRights = [newStudyRight]

await updateStudent(students[0])

})
Expand All @@ -319,15 +382,15 @@ describe('Updater works', () => {
expect(age).toBe(41)
expect(address).toBe('Yliopistonkatu 4')
expect(mobile).toBe('0400521981')

})
test('Existing courses are updated (not duplicated) in database', async () => {
const courses = await Course.findAll({ order: [['code', 'ASC']] })
const newCourse = courses.find(_ => _.code === '420_666')
expect(courses.length).toBe(148)

expect(newCourse).not.toBe(undefined)

})

test('Updating credits works', async () => {
Expand All @@ -337,6 +400,17 @@ describe('Updater works', () => {
expect(updatedCredit.grade).toBe('0')
})

test('Studyrights are rewritten', async () => {
const updatedStudyRights = await Studyright.findAll({
where: {
student_studentnumber: '011120775'
}
})
expect(updatedStudyRights.length).toBe(1)
expect(updatedStudyRights[0].highlevelname).toBe('Kaljatiede')
// theres really not a lot to test here since everything related to studyrights are just rewritten
})


})

Expand Down

0 comments on commit 02745c8

Please sign in to comment.