Skip to content

Commit 3d1f2ef

Browse files
HITGIFharrynull
andauthored
Create or update student profile (#27)
* create or update profile * add todo * syntax & add test * fixes Co-authored-by: Harry Yu <[email protected]>
1 parent bdccd4e commit 3d1f2ef

File tree

7 files changed

+381
-45
lines changed

7 files changed

+381
-45
lines changed

src/main/kotlin/com/watcourses/wat_courses/api/StudentProfileApi.kt

+41-5
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@ import com.watcourses.wat_courses.persistence.DbStudentProfileRepo
66
import com.watcourses.wat_courses.persistence.DbStudentProfileSchedule
77
import com.watcourses.wat_courses.persistence.DbStudentProfileScheduleRepo
88
import com.watcourses.wat_courses.persistence.DbTermScheduleRepo
9+
import com.watcourses.wat_courses.persistence.DbUserRepo
910
import com.watcourses.wat_courses.proto.*
1011
import com.watcourses.wat_courses.rules.Checker
1112
import com.watcourses.wat_courses.rules.DegreeRequirementLoader
13+
import com.watcourses.wat_courses.utils.SessionManager
1214
import com.watcourses.wat_courses.utils.create
1315
import com.watcourses.wat_courses.utils.unionFlatten
16+
import org.springframework.http.HttpStatus
1417
import org.springframework.web.bind.annotation.*
18+
import org.springframework.web.server.ResponseStatusException
19+
import javax.servlet.http.HttpServletRequest
1520
import javax.transaction.Transactional
1621

1722
@Transactional
@@ -22,7 +27,9 @@ class StudentProfileApi(
2227
private val dbStudentProfileRepo: DbStudentProfileRepo,
2328
private val dbTermScheduleRepo: DbTermScheduleRepo,
2429
private val dbCourseRepo: DbCourseRepo,
25-
private val checker: Checker
30+
private val dbUserRepo: DbUserRepo,
31+
private val checker: Checker,
32+
private val sessionManager: SessionManager,
2633
) {
2734
@GetMapping("/profile/default")
2835
fun getDefaultStudentProfile(program: String): StudentProfile {
@@ -35,29 +42,58 @@ class StudentProfileApi(
3542
}
3643

3744
@PostMapping("/profile/create")
38-
fun createStudentProfile(@RequestBody request: CreateStudentProfileRequest): StudentProfile {
45+
fun createDefaultStudentProfile(
46+
@RequestBody request: CreateDefaultStudentProfileRequest,
47+
httpRequest: HttpServletRequest
48+
): StudentProfile {
49+
val owner = sessionManager.getCurrentUser(httpRequest)
50+
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Not logged in")
3951
val degrees = request.degrees
4052
val degreeRequirements = degrees.map { degreeRequirementLoader.getDegreeRequirement(it)!! }
4153
val startingYear = request.startingYear!!
4254
val stream = request.coopStream!!
43-
val defaultSchedule = degreeRequirements.single { it.defaultSchedule?.terms?.isNotEmpty() == true }
55+
val defaultSchedule = degreeRequirements
56+
.single { it.defaultSchedule?.terms?.isNotEmpty() == true }
4457
.defaultSchedule!!
4558
val importedSchedule = request.schedule
4659
val mergedSchedule = importedSchedule?.let { mergeSchedule(it, defaultSchedule) } ?: defaultSchedule
4760

4861
val dbStudentProfile = DbStudentProfile.create(
4962
dbStudentProfileRepo = dbStudentProfileRepo,
50-
schedule = DbStudentProfileSchedule.create(
63+
schedule = DbStudentProfileSchedule.createOrUpdate(
5164
dbStudentProfileScheduleRepo = dbStudentProfileScheduleRepo,
5265
dbTermScheduleRepo = dbTermScheduleRepo,
5366
dbCourseRepo = dbCourseRepo,
5467
schedule = Schedule.create(mergedSchedule, startingYear, stream),
68+
existingDbStudentProfileSchedule = null,
5569
),
5670
degrees = degrees.toMutableList(),
5771
labels = degreeRequirements.map { it.labels.toSet() }.unionFlatten().toMutableList(),
58-
owner = null,
72+
owner = owner,
5973
)
74+
owner.studentProfile = dbStudentProfile
75+
dbUserRepo.save(owner)
76+
return dbStudentProfile.toProto()
77+
}
78+
79+
@PostMapping("/profile/create-or-update")
80+
fun createOrUpdateStudentProfile(
81+
@RequestBody studentProfile: StudentProfile,
82+
httpRequest: HttpServletRequest
83+
): StudentProfile {
84+
val owner = sessionManager.getCurrentUser(httpRequest)
85+
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "Not logged in")
6086

87+
val dbStudentProfile = DbStudentProfile.createOrUpdate(
88+
dbStudentProfileScheduleRepo = dbStudentProfileScheduleRepo,
89+
dbTermScheduleRepo = dbTermScheduleRepo,
90+
dbStudentProfileRepo = dbStudentProfileRepo,
91+
dbCourseRepo = dbCourseRepo,
92+
studentProfile = studentProfile,
93+
owner = owner,
94+
)
95+
owner.studentProfile = dbStudentProfile
96+
dbUserRepo.save(owner)
6197
return dbStudentProfile.toProto()
6298
}
6399

src/main/kotlin/com/watcourses/wat_courses/persistence/DbStudentProfile.kt

+46-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.watcourses.wat_courses.persistence
22

33
import com.watcourses.wat_courses.proto.StudentProfile
4+
import org.springframework.data.repository.findByIdOrNull
45
import javax.persistence.*
56

67
@Entity(name = "student_profile")
@@ -28,9 +29,9 @@ data class DbStudentProfile(
2829
)
2930
var shortListCourses: MutableList<DbCourse> = mutableListOf(),
3031

32+
@Column
3133
@OneToOne(fetch = FetchType.LAZY)
32-
@JoinColumn
33-
var owner: DbUser? = null,
34+
var owner: DbUser,
3435

3536
@Id @GeneratedValue
3637
var id: Long? = null
@@ -41,7 +42,7 @@ data class DbStudentProfile(
4142
labels = labels.toList(),
4243
degrees = degrees.toList(),
4344
shortList = shortListCourses.map { it.code },
44-
ownerEmail = owner?.email,
45+
ownerEmail = owner.email,
4546
)
4647
}
4748

@@ -52,7 +53,7 @@ data class DbStudentProfile(
5253
labels: MutableList<String>,
5354
degrees: MutableList<String>,
5455
shortList: MutableList<DbCourse> = mutableListOf(),
55-
owner: DbUser?,
56+
owner: DbUser,
5657
): DbStudentProfile {
5758
val dbStudentProfile = DbStudentProfile(
5859
schedule = schedule,
@@ -64,5 +65,46 @@ data class DbStudentProfile(
6465
dbStudentProfileRepo.save(dbStudentProfile)
6566
return dbStudentProfile
6667
}
68+
69+
fun createOrUpdate(
70+
dbStudentProfileScheduleRepo: DbStudentProfileScheduleRepo,
71+
dbTermScheduleRepo: DbTermScheduleRepo,
72+
dbStudentProfileRepo: DbStudentProfileRepo,
73+
dbCourseRepo: DbCourseRepo,
74+
studentProfile: StudentProfile,
75+
owner: DbUser,
76+
): DbStudentProfile {
77+
val existingDbStudentProfile = owner.studentProfile
78+
79+
val dbSchedule = DbStudentProfileSchedule.createOrUpdate(
80+
dbStudentProfileScheduleRepo = dbStudentProfileScheduleRepo,
81+
dbTermScheduleRepo = dbTermScheduleRepo,
82+
dbCourseRepo = dbCourseRepo,
83+
schedule = studentProfile.schedule!!,
84+
existingDbStudentProfileSchedule = existingDbStudentProfile?.schedule,
85+
)
86+
val labels = studentProfile.labels.toMutableList()
87+
val degrees = studentProfile.degrees.toMutableList()
88+
val shortList = studentProfile.shortList.mapNotNull { dbCourseRepo.findByCode(it) }.toMutableList()
89+
90+
if (existingDbStudentProfile == null) {
91+
return create(
92+
dbStudentProfileRepo = dbStudentProfileRepo,
93+
schedule = dbSchedule,
94+
labels = labels,
95+
degrees = degrees,
96+
shortList = shortList,
97+
owner = owner,
98+
)
99+
}
100+
101+
existingDbStudentProfile.schedule = dbSchedule
102+
existingDbStudentProfile.labels = labels
103+
existingDbStudentProfile.degrees = degrees
104+
existingDbStudentProfile.shortListCourses = shortList
105+
existingDbStudentProfile.owner = owner
106+
107+
return dbStudentProfileRepo.save(existingDbStudentProfile)
108+
}
67109
}
68110
}

src/main/kotlin/com/watcourses/wat_courses/persistence/DbStudentProfileSchedule.kt

+21-23
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.watcourses.wat_courses.persistence
33
import com.watcourses.wat_courses.proto.Schedule
44
import com.watcourses.wat_courses.proto.Term
55
import org.springframework.beans.factory.annotation.Autowired
6+
import org.springframework.data.repository.findByIdOrNull
67
import javax.persistence.*
78

89
@Entity(name = "student_profile_schedule")
@@ -22,34 +23,31 @@ data class DbStudentProfileSchedule(
2223
}
2324

2425
companion object {
25-
fun create(
26-
dbStudentProfileScheduleRepo: DbStudentProfileScheduleRepo,
27-
terms: MutableList<DbTermSchedule>,
28-
): DbStudentProfileSchedule {
29-
val dbStudentProfileSchedule = DbStudentProfileSchedule(
30-
terms = terms,
31-
)
32-
dbStudentProfileScheduleRepo.save(dbStudentProfileSchedule)
33-
return dbStudentProfileSchedule
34-
}
35-
36-
fun create(
26+
fun createOrUpdate(
3727
dbStudentProfileScheduleRepo: DbStudentProfileScheduleRepo,
3828
dbTermScheduleRepo: DbTermScheduleRepo,
3929
dbCourseRepo: DbCourseRepo,
4030
schedule: Schedule,
31+
existingDbStudentProfileSchedule: DbStudentProfileSchedule?,
4132
): DbStudentProfileSchedule {
42-
val dbStudentProfileSchedule = DbStudentProfileSchedule(
43-
terms = schedule.terms.map {
44-
DbTermSchedule.create(
45-
dbTermScheduleRepo = dbTermScheduleRepo,
46-
dbCourseRepo = dbCourseRepo,
47-
termSchedule = it,
48-
)
49-
}.toMutableList(),
50-
)
51-
dbStudentProfileScheduleRepo.save(dbStudentProfileSchedule)
52-
return dbStudentProfileSchedule
33+
val dbStudentProfileSchedule = existingDbStudentProfileSchedule ?: DbStudentProfileSchedule()
34+
val newTerms = schedule.terms.map { termSchedule ->
35+
DbTermSchedule.createOrUpdate(
36+
dbTermScheduleRepo = dbTermScheduleRepo,
37+
dbCourseRepo = dbCourseRepo,
38+
termSchedule = termSchedule,
39+
existingDbTermSchedule = dbStudentProfileSchedule.terms
40+
.singleOrNull { it.name == termSchedule.termName },
41+
)
42+
}.toMutableList()
43+
44+
val newTermNames = newTerms.map { it.name }.toSet()
45+
dbStudentProfileSchedule.terms
46+
.filter { it.name !in newTermNames }
47+
.forEach { dbTermScheduleRepo.delete(it) }
48+
49+
dbStudentProfileSchedule.terms = newTerms
50+
return dbStudentProfileScheduleRepo.save(dbStudentProfileSchedule)
5351
}
5452
}
5553
}

src/main/kotlin/com/watcourses/wat_courses/persistence/DbTermSchedule.kt

+11-9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.watcourses.wat_courses.persistence
22

33
import com.watcourses.wat_courses.proto.Schedule
44
import com.watcourses.wat_courses.proto.Term
5+
import org.springframework.data.repository.findByIdOrNull
56
import javax.persistence.*
67

78
@Entity(name = "term_schedule")
@@ -51,21 +52,22 @@ data class DbTermSchedule(
5152
return dbTermSchedule
5253
}
5354

54-
fun create(
55+
fun createOrUpdate(
5556
dbTermScheduleRepo: DbTermScheduleRepo,
5657
dbCourseRepo: DbCourseRepo,
5758
termSchedule: Schedule.TermSchedule,
59+
existingDbTermSchedule: DbTermSchedule?,
5860
): DbTermSchedule {
5961
val orderOf = termSchedule.courseCodes.mapIndexed { index, code -> code to index }.toMap()
6062
val dbCourses = dbCourseRepo.findAllByCodeIn(termSchedule.courseCodes).sortedBy { orderOf[it.code] }
61-
val dbTermSchedule = DbTermSchedule(
62-
courses = dbCourses.toMutableList(),
63-
name = termSchedule.termName,
64-
year = termSchedule.year,
65-
term = termSchedule.term,
66-
)
67-
dbTermScheduleRepo.save(dbTermSchedule)
68-
return dbTermSchedule
63+
val dbTermSchedule = existingDbTermSchedule ?: DbTermSchedule()
64+
65+
dbTermSchedule.courses = dbCourses.toMutableList()
66+
dbTermSchedule.name = termSchedule.termName
67+
dbTermSchedule.year = termSchedule.year
68+
dbTermSchedule.term = termSchedule.term
69+
70+
return dbTermScheduleRepo.save(dbTermSchedule)
6971
}
7072
}
7173
}

0 commit comments

Comments
 (0)