Skip to content
Open
Show file tree
Hide file tree
Changes from 216 commits
Commits
Show all changes
223 commits
Select commit Hold shift + click to select a range
eb54ed9
Fixed minor spelling mistake in comment
SamuelRoettgermann Jun 16, 2025
e3437d6
renamed warning and tooltip
SamuelRoettgermann Jun 16, 2025
d60eb17
changed the minimum valid value from 0 to 1
SamuelRoettgermann Jun 16, 2025
da3b4c8
deprecated an outdated validator
SamuelRoettgermann Jun 22, 2025
6732bf0
added tooltip for the number of exercises in exam
SamuelRoettgermann Jun 22, 2025
0bfaf7e
improved the deprecation message
SamuelRoettgermann Jun 22, 2025
8f1a3a6
add test for the min adjustment
SamuelRoettgermann Jun 22, 2025
f2efca0
initial setup
SamuelRoettgermann Jun 23, 2025
f021a56
URL is openable and calls correct REST endpoint, however not yet navi…
SamuelRoettgermann Jun 23, 2025
5a1cafb
added exam room button to admin dropdown
SamuelRoettgermann Jul 5, 2025
dca8ba1
created domain objects and liquibase changelog
SamuelRoettgermann Jul 7, 2025
a86f864
implemented the domain objects, defined the DB changes, and added two…
SamuelRoettgermann Jul 7, 2025
d8a6a90
added documentation for the entities
SamuelRoettgermann Jul 7, 2025
fa8356d
init setup of the exam room repository
SamuelRoettgermann Jul 7, 2025
d6a952c
added JSON include only non-empty for entities
SamuelRoettgermann Jul 7, 2025
7076ed7
changed coordinate types to float and added exam-room-id column to th…
SamuelRoettgermann Jul 7, 2025
2ec994b
follow up update on the liquibase column addition
SamuelRoettgermann Jul 7, 2025
da24105
added 2 more columns to ExamRoom to be able to store all possible nam…
SamuelRoettgermann Jul 7, 2025
b28dc45
added a few fields to the tables, and unfinished version of room parsing
SamuelRoettgermann Jul 11, 2025
cda2bb1
JSON serialization issue fixed -> Uploading rooms works, however room…
SamuelRoettgermann Jul 14, 2025
fdf6dc4
several logger limitations to make it more readable
SamuelRoettgermann Jul 19, 2025
f4988ca
fixed serialization issues, was more verbose in Java code
SamuelRoettgermann Jul 19, 2025
b64f67b
room parsing with capacity per layout instead of per room works, stil…
SamuelRoettgermann Jul 19, 2025
5ef3e88
liquibase changes according to the domain changes
SamuelRoettgermann Jul 19, 2025
7ec543c
parsing works, old & unused entries still need to be deleted, backend…
SamuelRoettgermann Jul 20, 2025
d067a1d
display the update information returned from the backend
SamuelRoettgermann Jul 20, 2025
efcecd3
added a new table exam_room_assignment, added planned seat entity to …
SamuelRoettgermann Jul 20, 2025
7491679
fixed auto-generated queries
SamuelRoettgermann Jul 21, 2025
a05b723
added a query to find all outdated exam rooms
SamuelRoettgermann Jul 21, 2025
915ae79
added backend code to return an exam room admin overview, aswell as f…
SamuelRoettgermann Jul 21, 2025
124a2ab
more of less logging
SamuelRoettgermann Jul 21, 2025
76c20f2
added exam room overview information and deletion button to admin ove…
SamuelRoettgermann Jul 21, 2025
3edb5bc
made the ExamSeat a JSON field in ExamRoom, rewrote a bunch of stuff …
SamuelRoettgermann Jul 21, 2025
720441f
converted ExamSeat from an entity to a DTO, added backend functionali…
SamuelRoettgermann Jul 27, 2025
03de792
removed examSeatEntity and examRoomEntity from ExamUser cause it's ju…
SamuelRoettgermann Jul 27, 2025
0d7eda1
fixed bugs arised from removing the examRoom reference from ExamUser,…
SamuelRoettgermann Jul 27, 2025
44f0e2e
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Jul 27, 2025
2c8a0a3
added capacity calculations, various cleanups, mental breakdown over …
SamuelRoettgermann Jul 28, 2025
6ec0c1f
various beautifications, now uses actual jhi-translate strings, still…
SamuelRoettgermann Jul 28, 2025
656116b
removed unrequired routing file
SamuelRoettgermann Aug 1, 2025
dc00bd4
added translations for English and German
SamuelRoettgermann Aug 1, 2025
a363397
added sorting functionality, moved functionality from template to com…
SamuelRoettgermann Aug 1, 2025
889a328
irrelevant
SamuelRoettgermann Aug 1, 2025
b6c9ab7
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Aug 2, 2025
8ed8f44
updated Liquibase changes to new date
SamuelRoettgermann Aug 2, 2025
7003ad3
removed custom Sass file
SamuelRoettgermann Aug 2, 2025
e2f3476
removed outdated client tests
SamuelRoettgermann Aug 3, 2025
3736c70
massively reduced the number of WriteableSignals, simplified logic to…
SamuelRoettgermann Aug 3, 2025
cf22303
added missing translations
SamuelRoettgermann Aug 3, 2025
85e2ed2
documented the backend code
SamuelRoettgermann Aug 3, 2025
44f715e
fixed client errors
SamuelRoettgermann Aug 3, 2025
9fa408b
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Aug 3, 2025
9392878
improved type-hint for string
SamuelRoettgermann Aug 3, 2025
a9c207a
added JSDoc to the TS code
SamuelRoettgermann Aug 3, 2025
16c4886
moved logic out of the template
SamuelRoettgermann Aug 3, 2025
28cb949
massively reduced DB calls
SamuelRoettgermann Aug 3, 2025
466afc6
moved a DTO-related enum from domain into DTO folder
SamuelRoettgermann Aug 3, 2025
a27a5e2
added a bit more documentation to the liquibase changelog
SamuelRoettgermann Aug 3, 2025
4cb0821
delete broken testing file
SamuelRoettgermann Aug 3, 2025
1d80bfc
clarified a comment
SamuelRoettgermann Aug 3, 2025
cab4585
fixed a wrong JavaDoc
SamuelRoettgermann Aug 3, 2025
8b8bf1b
fixed a display issue
SamuelRoettgermann Aug 3, 2025
25c587e
implemented all review suggestions from Lukas and CodeRabbit, and all…
SamuelRoettgermann Aug 8, 2025
7b2e245
prevent parallel uploads
SamuelRoettgermann Aug 8, 2025
5a40386
implemented Lukas suggestion to use Jackson for help with parsing the…
SamuelRoettgermann Aug 8, 2025
30ac592
reduced number of DB calls, added filename to the file-upload-button,…
SamuelRoettgermann Aug 9, 2025
ff90af4
fixed more coderabbit suggestions
SamuelRoettgermann Aug 9, 2025
c5cd592
fixed an error from a newly added test, that my code violated
SamuelRoettgermann Aug 9, 2025
d510ccc
fixed 2 more points of Lukas
SamuelRoettgermann Aug 9, 2025
0fd9652
one more coderabbit suggestion for protecting against foreign user input
SamuelRoettgermann Aug 9, 2025
9731204
fixed another issue because I used the wrong @NotNull annotation
SamuelRoettgermann Aug 9, 2025
a229956
changed translation for the safe delete button
SamuelRoettgermann Aug 10, 2025
0ffdb2a
made function names more intuitive, improved & fixed some JavaDoc
SamuelRoettgermann Aug 10, 2025
786a311
adapted recommended liquibase changes
SamuelRoettgermann Aug 11, 2025
b28ecd0
removed accidental changes, presumably from a develop merge
SamuelRoettgermann Aug 12, 2025
1f5299d
removed Getters and Setters markers
SamuelRoettgermann Aug 12, 2025
5c54d33
removed dangling JavaDoc comments, renamed fields to be more descript…
SamuelRoettgermann Aug 12, 2025
b4327fc
removed redundant code
SamuelRoettgermann Aug 12, 2025
5a1e408
removed redundant data sent via DTO, moved the calculations to the cl…
SamuelRoettgermann Aug 12, 2025
70969d1
made the delete not delete as a batch anymore to prevent potential da…
SamuelRoettgermann Aug 12, 2025
32ffad1
renamed idx to index
SamuelRoettgermann Aug 12, 2025
bb5f9d3
parsing seats and layouts now more often raise an exception rather th…
SamuelRoettgermann Aug 13, 2025
e2cfd5d
moved HTTP calls in a .service.ts file
SamuelRoettgermann Aug 13, 2025
54653f8
added NotNull to all DTOs; made capacity non-nullable
SamuelRoettgermann Aug 13, 2025
135c3f8
made ExamSeatDTOs coordinates double instead of float
SamuelRoettgermann Aug 14, 2025
f20e8e3
made examRoom load lazy in LayoutStrategy
SamuelRoettgermann Aug 14, 2025
d6a6e15
added Bean JSON validation to LayoutStrategy#parametersJson
SamuelRoettgermann Aug 14, 2025
2d30981
removed impossible to hit exception from catch clause
SamuelRoettgermann Aug 14, 2025
08f459b
pedantic import error
SamuelRoettgermann Aug 14, 2025
709b274
unified some duplicated duration formatting code
SamuelRoettgermann Aug 15, 2025
11e289a
removed the conirm/alert calls and instead use DeleteDialogService fo…
SamuelRoettgermann Aug 15, 2025
121fbee
code cleanup, using regular artemis alerts now instead of custom erro…
SamuelRoettgermann Aug 15, 2025
436474c
remove code nesting by using guard clauses
SamuelRoettgermann Aug 15, 2025
a819759
added text to empty error message for getting an error while getting …
SamuelRoettgermann Aug 15, 2025
3233321
now TS also uses the correct translation key
SamuelRoettgermann Aug 15, 2025
b821ba6
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Aug 15, 2025
f8c24a9
some CodeRabbit nitpicks
SamuelRoettgermann Aug 15, 2025
f790aae
partial recovery of test code, lost about 3 days worth of work due to…
SamuelRoettgermann Aug 24, 2025
3b9d5fd
Merge remote-tracking branch 'refs/remotes/origin/feature/exam-mode/a…
SamuelRoettgermann Aug 24, 2025
ae67da4
re-finished the service tests
SamuelRoettgermann Aug 24, 2025
3cf548f
integration tests
SamuelRoettgermann Aug 25, 2025
ff44bd5
fixed integration tests
SamuelRoettgermann Aug 25, 2025
1fb6e40
added a few more integration tests
SamuelRoettgermann Aug 25, 2025
6a402ca
finished backend tests, except for minor bugs
SamuelRoettgermann Aug 28, 2025
30d24c2
fixed all integration tests
SamuelRoettgermann Aug 28, 2025
6355bac
fixed code structural tests, code rabbit suggestion for using Void.cl…
SamuelRoettgermann Aug 28, 2025
49dbbf1
resolved merge conflict
SamuelRoettgermann Aug 29, 2025
efed2bc
added frontend tests
SamuelRoettgermann Aug 30, 2025
de448f4
added more frontend tests to increase coverage
SamuelRoettgermann Aug 30, 2025
681e033
fixed compilation failures due to new checkstyles
SamuelRoettgermann Aug 30, 2025
b9c7729
fixed client compilation issues, hopefully I didn
SamuelRoettgermann Aug 30, 2025
8fe63e7
of course I missed one case
SamuelRoettgermann Aug 30, 2025
c77c5b7
bunch of CodeRabbit suggestions
SamuelRoettgermann Aug 30, 2025
065f8ed
added file too big error in backend
SamuelRoettgermann Aug 30, 2025
1b3e19f
fixed chronological order in master.xml
SamuelRoettgermann Aug 30, 2025
d09220b
fixed typo in master.xml
SamuelRoettgermann Aug 30, 2025
6f98903
applied CodeRabbit suggestion
SamuelRoettgermann Aug 30, 2025
85a3465
applied CodeRabbit nitpick comment to get rid off an injected, but ne…
SamuelRoettgermann Aug 30, 2025
172d3d3
talked with CodeRabbit and now use a more specific, albeit sometimes …
SamuelRoettgermann Aug 30, 2025
9c3a39c
applied more CodeRabbit suggestions
SamuelRoettgermann Aug 30, 2025
b5caf15
applied some CodeRabbit nitpick comments
SamuelRoettgermann Aug 30, 2025
142cf31
more CodeRabbit fixes
SamuelRoettgermann Aug 30, 2025
4cc239a
fixed wrong reading of seat condition flags, and IO exception
SamuelRoettgermann Aug 31, 2025
8d004b1
first round of Tobias change requests
SamuelRoettgermann Sep 6, 2025
b0d15d0
rest of Tobi's change requests + CodeRabbit change requests
SamuelRoettgermann Sep 6, 2025
571cd49
fixed a few last compilation errors and finally found and fixed a nas…
SamuelRoettgermann Sep 6, 2025
1ac17d7
CodeRabbit suggestions
SamuelRoettgermann Sep 6, 2025
67a160a
Merge branch 'develop' into feature/exam-mode/add-room-data-insertion…
SamuelRoettgermann Sep 6, 2025
327a7a3
improved comment clarity even more
SamuelRoettgermann Sep 6, 2025
87aa963
improved documentation and usability
SamuelRoettgermann Sep 6, 2025
4baac6e
added tests for new pipe to meet coverage threshold
SamuelRoettgermann Sep 6, 2025
052b774
removed a test that worked locally but failed for type safety things …
SamuelRoettgermann Sep 6, 2025
32c2ef3
initial commit
SamuelRoettgermann Sep 8, 2025
771647f
applied Tobi's last fixes
SamuelRoettgermann Sep 8, 2025
0fa2580
still missing 2 german and all english translations, added transient …
SamuelRoettgermann Sep 9, 2025
28b0627
removed some unnecessary String.valueOf wrappers
SamuelRoettgermann Sep 10, 2025
fd6b28a
removed formatting disabled blocks
SamuelRoettgermann Sep 10, 2025
24ee19f
removed all <p></p> instances for spacing from the template
SamuelRoettgermann Sep 10, 2025
2e0aac8
code rabbit language fix, and also removed unused translation strings
SamuelRoettgermann Sep 10, 2025
1459597
fixed a bug Marlon found on Chrome and Safari; fixed a bug with displ…
SamuelRoettgermann Sep 10, 2025
2c51429
added padding to the upload and deletion card titles
SamuelRoettgermann Sep 10, 2025
404b792
Merge branch 'feature/exam-mode/add-room-data-insertion-admin-panel' …
SamuelRoettgermann Sep 11, 2025
aa0f040
added REST endpoint for simple distributions, only to the default dis…
SamuelRoettgermann Sep 11, 2025
be6f573
Merge branch 'develop' into feature/exam-mode/seating-distribution-al…
SamuelRoettgermann Sep 12, 2025
6d2dbd9
minor code beautification
SamuelRoettgermann Sep 12, 2025
9de7f05
added fixed selection support; made the fixed selection fail-early i.…
SamuelRoettgermann Sep 12, 2025
ff5c4b9
re-added accidently deleted repository function
SamuelRoettgermann Sep 12, 2025
b84ba36
improved error message a bit; still need to add translation keys
SamuelRoettgermann Sep 12, 2025
8d9ac66
added the room ID to the admin overview page
SamuelRoettgermann Sep 12, 2025
76eb651
simplified & optimized a query
SamuelRoettgermann Sep 12, 2025
8c10817
fixed bug showing all exam rooms rather than just the newest one
SamuelRoettgermann Sep 12, 2025
916933c
minor formatting fix
SamuelRoettgermann Sep 12, 2025
0bc9f62
added i18n translations, and removed some unnecessary logging
SamuelRoettgermann Sep 12, 2025
180a86b
reset the planned room and seat fields on exam room deletion
SamuelRoettgermann Sep 12, 2025
3fb7858
code cleanup, and fixed a bug where it deleted old exam room assignme…
SamuelRoettgermann Sep 12, 2025
6175031
removed transient fields that were not yet used, but a good chunk of …
SamuelRoettgermann Sep 12, 2025
8afac7d
minor code cleanup and performance optimization; also made the JavaDo…
SamuelRoettgermann Sep 12, 2025
362b56e
added default capacity display to the admin overview
SamuelRoettgermann Sep 12, 2025
11236a7
fixed tests related to the realistic exam room zip file scenario
SamuelRoettgermann Sep 12, 2025
0e2021d
fixed some examRepositoryArchitectureTests
SamuelRoettgermann Sep 13, 2025
d884e13
this PR fixes the examRepositoryArchitectureTest; the previous commit…
SamuelRoettgermann Sep 13, 2025
484ad2c
a lot of code rabbit suggestions and nitpicks
SamuelRoettgermann Sep 13, 2025
69bf6f2
one additional coderabbit suggestion to make a query more in-line wit…
SamuelRoettgermann Sep 13, 2025
342b6a0
batch save instead of individual saves
SamuelRoettgermann Sep 14, 2025
edabd3e
more CodeRabbit nitpicks
SamuelRoettgermann Sep 14, 2025
2dee634
Tobi's fixes
SamuelRoettgermann Sep 15, 2025
5efcd60
CodeRabbit query re-reversal
SamuelRoettgermann Sep 15, 2025
c7ff242
last of Tobi's suggestion to move code into new service & resource
SamuelRoettgermann Sep 15, 2025
9e36dfc
more CodeRabbit suggestions
SamuelRoettgermann Sep 15, 2025
4704f32
Merge branch 'develop' into feature/exam-mode/seating-distribution-al…
SamuelRoettgermann Sep 15, 2025
c01bc32
fixed query for Postgres (json type doesnt have a comparison and DIST…
SamuelRoettgermann Sep 15, 2025
c593a6b
Review suggestions
SamuelRoettgermann Sep 17, 2025
3ce8a0c
one code rabbit suggestion and minor spelling changes
SamuelRoettgermann Sep 21, 2025
e2067cc
code rabbit suggestion for a key-bug fiX
SamuelRoettgermann Sep 22, 2025
c8a4988
Merge branch 'develop' into feature/exam-mode/seating-distribution-al…
SamuelRoettgermann Sep 22, 2025
250e897
fixed a JavaDoc
SamuelRoettgermann Sep 22, 2025
79e252b
applied Tobi's change
SamuelRoettgermann Sep 24, 2025
203fa00
Merge remote-tracking branch 'refs/remotes/origin/feature/exam-mode/s…
SamuelRoettgermann Sep 24, 2025
e5b93bc
initial setup
SamuelRoettgermann Sep 25, 2025
8d68124
added endpoint for simple exam user verification, also added endpoint…
SamuelRoettgermann Sep 25, 2025
c481e49
code rabbit suggestions
SamuelRoettgermann Sep 25, 2025
fb451cc
satisfy server style tests
SamuelRoettgermann Sep 25, 2025
2d7d687
renmade resource method to avoid naming confusion
SamuelRoettgermann Sep 25, 2025
5cf68f2
removed unnecessary actual vs planned room and seat overwrites
SamuelRoettgermann Sep 25, 2025
0a6feb0
fixed lazy initialization issue
SamuelRoettgermann Sep 25, 2025
271d242
updated the attendance checker information endpoint
SamuelRoettgermann Sep 29, 2025
75da874
added transient actual rooms and seats to ExamUser and included them …
SamuelRoettgermann Sep 29, 2025
356d3ba
fixed a NPE for when the actual room/seat wasn't set
SamuelRoettgermann Oct 1, 2025
c0449af
more debuggy errors
SamuelRoettgermann Oct 14, 2025
c26df83
Merge branch 'develop' into feature/exam-mode/iPad-attendance-checker…
SamuelRoettgermann Oct 14, 2025
0ef7f2c
removed line that shouldve been removed in the merge
SamuelRoettgermann Oct 14, 2025
2c01f5e
added JavaDoc
SamuelRoettgermann Oct 14, 2025
1e92dd5
one more JavaDoc comment
SamuelRoettgermann Oct 14, 2025
9178a8d
Merge branch 'develop' into feature/exam-mode/iPad-attendance-checker…
SamuelRoettgermann Oct 19, 2025
2acbf10
coderabbit and Anian suggestions
SamuelRoettgermann Oct 19, 2025
68ab794
removed unused PUT endpoint
SamuelRoettgermann Oct 20, 2025
733bcfc
improved DTO's jakarte validation
SamuelRoettgermann Oct 20, 2025
c551482
removed outdated artifact from a different branch
SamuelRoettgermann Oct 20, 2025
49436e4
remove unrelated change
SamuelRoettgermann Oct 20, 2025
2e014b0
revert change for testing
SamuelRoettgermann Oct 20, 2025
8b48f21
fixed a bug that would cause a 400 error if the legacy distribution w…
SamuelRoettgermann Oct 20, 2025
14378dc
more fixes that have to do with the legacy mode
SamuelRoettgermann Oct 20, 2025
92a3042
fixed wrong translation key
SamuelRoettgermann Oct 20, 2025
ab7534c
added integration tests
SamuelRoettgermann Oct 20, 2025
685ad29
satisfy CoreArchitectureTest
SamuelRoettgermann Oct 20, 2025
5cd45b6
Merge branch 'develop' into feature/exam-mode/iPad-attendance-checker…
SamuelRoettgermann Oct 25, 2025
961b064
moved tests
SamuelRoettgermann Oct 25, 2025
7d3bd91
bugfix where it sent an empty actualLocation
SamuelRoettgermann Oct 25, 2025
125d756
auto-format move
SamuelRoettgermann Oct 25, 2025
ccd0311
revert silly one line removal
SamuelRoettgermann Oct 25, 2025
c87f04c
another one line removal artifact
SamuelRoettgermann Oct 25, 2025
065770c
code cleanup including a bugfix for when manually changing the locati…
SamuelRoettgermann Oct 26, 2025
4c38903
Revert a simple accidental change that caused a huge (+142/-144) git …
SamuelRoettgermann Oct 26, 2025
25264fa
applied two of Anian's changes
SamuelRoettgermann Oct 26, 2025
4ceb407
removed unused translation keys
SamuelRoettgermann Oct 26, 2025
926855f
remove outdated JavaDoc
SamuelRoettgermann Oct 26, 2025
a334adf
removed a few unnecessary @NotNull s
SamuelRoettgermann Oct 28, 2025
665a35b
Merge branch 'develop' into feature/exam-mode/iPad-attendance-checker…
SamuelRoettgermann Nov 4, 2025
30d17fb
fix test that got broken in merge
SamuelRoettgermann Nov 4, 2025
4b45e49
Merge branch 'develop' into feature/exam-mode/iPad-attendance-checker…
SamuelRoettgermann Nov 18, 2025
74b871d
Merge branch 'develop' into feature/exam-mode/iPad-attendance-checker…
SamuelRoettgermann Nov 18, 2025
c0d9c53
change attendance checker endpoint to tutor in course
SamuelRoettgermann Nov 18, 2025
1cf5750
changed endpoints to tutor only
SamuelRoettgermann Nov 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/main/java/de/tum/cit/aet/artemis/exam/domain/ExamUser.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import jakarta.persistence.Transient;
import jakarta.validation.constraints.Size;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;

import de.tum.cit.aet.artemis.core.domain.AbstractAuditingEntity;
import de.tum.cit.aet.artemis.core.domain.User;
import de.tum.cit.aet.artemis.exam.domain.room.ExamRoom;
import de.tum.cit.aet.artemis.exam.dto.room.ExamSeatDTO;

@Entity
@Table(name = "exam_user")
Expand All @@ -29,6 +33,22 @@ public class ExamUser extends AbstractAuditingEntity {
@Column(name = "planned_seat")
private String plannedSeat;

@JsonIgnore
@Transient
private ExamRoom plannedRoomTransient;

@JsonIgnore
@Transient
private ExamSeatDTO plannedSeatTransient;

@JsonIgnore
@Transient
private ExamRoom actualRoomTransient;

@JsonIgnore
@Transient
private ExamSeatDTO actualSeatTransient;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if i'm a fan of mixing DTOs and domain objects

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already do it in my ExamRoom.java domain class where I have a

/**
 * All seats of this exam room.
 */
@JdbcTypeCode(SqlTypes.JSON)
@Column(name = "exam_seats", columnDefinition = "json", nullable = false)
private List<ExamSeatDTO> seats = new ArrayList<>();

and since in this case the fields are @Transient and @JsonIgnore there is virtually no chance of it leaking anywhere.

I did it like this because it (greatly) simplifies the rest of the logic and improves readability.

If you insist on it being bad then I can change it, but please do share your opinion considering these things.


@Column(name = "did_check_image")
private boolean didCheckImage = false;

Expand Down Expand Up @@ -89,6 +109,32 @@ public void setPlannedSeat(String plannedSeat) {
this.plannedSeat = plannedSeat;
}

public ExamRoom getPlannedRoomTransient() {
return plannedRoomTransient;
}

public ExamSeatDTO getPlannedSeatTransient() {
return plannedSeatTransient;
}

public void setTransientPlannedRoomAndSeat(ExamRoom plannedRoom, ExamSeatDTO plannedSeat) {
this.plannedRoomTransient = plannedRoom;
this.plannedSeatTransient = plannedSeat;
}

public ExamRoom getActualRoomTransient() {
return actualRoomTransient;
}

public ExamSeatDTO getActualSeatTransient() {
return actualSeatTransient;
}

public void setTransientActualRoomAndSeat(ExamRoom actualRoom, ExamSeatDTO actualSeat) {
this.actualRoomTransient = actualRoom;
this.actualSeatTransient = actualSeat;
}

public boolean getDidCheckRegistrationNumber() {
return didCheckRegistrationNumber;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package de.tum.cit.aet.artemis.exam.dto.room;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import jakarta.annotation.Nullable;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

import org.springframework.util.StringUtils;

import com.fasterxml.jackson.annotation.JsonInclude;

import de.tum.cit.aet.artemis.exam.domain.Exam;
import de.tum.cit.aet.artemis.exam.domain.ExamUser;
import de.tum.cit.aet.artemis.exam.domain.room.ExamRoom;

// @formatter:off
@JsonInclude(JsonInclude.Include.NON_EMPTY)
record ExamRoomForAttendanceCheckerDTO(
@NotNull long id,
@NotBlank String roomNumber,
@Nullable String alternativeRoomNumber,
@NotBlank String name,
@Nullable String alternativeName,
@NotBlank String building,
@NotNull List<ExamSeatDTO> seats
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could @NotEmpty be used here instead of @NotNull?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As of right now it's TECHNICALLY still possible for a room to have zero seats, so I wouldn't want to exchange that just yet, but it's definitely something that can be adjusted in the future when the room parser rejects rooms without seats.

) {
static ExamRoomForAttendanceCheckerDTO from(ExamRoom examRoom) {
return new ExamRoomForAttendanceCheckerDTO(
examRoom.getId(),
examRoom.getRoomNumber(),
examRoom.getAlternativeRoomNumber(),
examRoom.getName(),
examRoom.getAlternativeName(),
examRoom.getBuilding(),
examRoom.getSeats()
);
}
}

@JsonInclude(JsonInclude.Include.NON_EMPTY)
record ExamUserLocationDTO(
@Nullable Long roomId, // null if legacy version
@NotBlank String roomNumber, // examUser.plannedRoom if legacy version
@NotBlank String seatName // examUser.plannedSeat if legacy version
) {
static ExamUserLocationDTO plannedFrom(ExamUser examUser) {
final boolean isLegacy = examUser.getPlannedRoomTransient() == null || examUser.getPlannedSeatTransient() == null;

return new ExamUserLocationDTO(
isLegacy ? null : examUser.getPlannedRoomTransient().getId(),
isLegacy ? examUser.getPlannedRoom() : examUser.getPlannedRoomTransient().getRoomNumber(),
isLegacy ? examUser.getPlannedSeat() : examUser.getPlannedSeatTransient().name()
);
}

static ExamUserLocationDTO actualFrom(ExamUser examUser) {
if (examUser.getActualRoom() == null || examUser.getActualSeat() == null) {
// examUser has not been moved
return null;
}

final boolean useLegacyFields = examUser.getActualRoomTransient() == null || examUser.getActualSeatTransient() == null;

return new ExamUserLocationDTO(
useLegacyFields ? null : examUser.getActualRoomTransient().getId(),
useLegacyFields ? examUser.getActualRoom() : examUser.getActualRoomTransient().getRoomNumber(),
useLegacyFields ? examUser.getActualSeat() : examUser.getActualSeatTransient().name()
);
}
}

@JsonInclude(JsonInclude.Include.NON_EMPTY)
record ExamUserWithExamRoomAndSeatDTO (
@NotBlank @Size(max = 50) String login,
// Names are nullable because not everyone has a first and/or last name
@Nullable @Size(max = 50) String firstName,
@Nullable @Size(max = 50) String lastName,
@NotBlank @Size(max = 10) String registrationNumber,
@Nullable @Email @Size(max = 100) String email,
@Nullable String imageUrl,
@NotNull boolean didCheckImage,
@NotNull boolean didCheckName,
@NotNull boolean didCheckRegistrationNumber,
@NotNull boolean didCheckLogin,
@Nullable String signingImagePath,
@NotNull ExamUserLocationDTO plannedLocation,
@Nullable ExamUserLocationDTO actualLocation
) {
static ExamUserWithExamRoomAndSeatDTO from(ExamUser examUser) {
return new ExamUserWithExamRoomAndSeatDTO(
examUser.getUser().getLogin(),
examUser.getUser().getFirstName(),
examUser.getUser().getLastName(),
examUser.getUser().getRegistrationNumber(),
examUser.getUser().getEmail(),
examUser.getUser().getImageUrl(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just as a note so we don't forget, we will need to add the actual exam user image here as this would show the profile picture the user has set

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very simple fix, just exchanged the examUser.getUser().getImagePath() to this examUser.getStudentImagePath()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding it as a TODO here, so we don't forget: When we have tested everything and it all works, we need to replace this with the image from TUMonline instead of the profile picture, otherwise students can "fake" their image

examUser.getDidCheckImage(),
examUser.getDidCheckName(),
examUser.getDidCheckRegistrationNumber(),
examUser.getDidCheckLogin(),
examUser.getSigningImagePath(),
ExamUserLocationDTO.plannedFrom(examUser),
ExamUserLocationDTO.actualFrom(examUser)
);
}
}

/**
* DTO containing all relevant information for the attendance checker app
*/
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public record AttendanceCheckerAppExamInformationDTO(
@NotNull long examId,
@NotBlank String examTitle,
@NotNull ZonedDateTime startDate,
@NotNull ZonedDateTime endDate,
@NotNull boolean isTestExam,
@NotNull long courseId,
@NotBlank String courseTitle,
@NotNull Set<ExamRoomForAttendanceCheckerDTO> examRoomsUsedInExam, // empty if legacy version
@NotEmpty Set<ExamUserWithExamRoomAndSeatDTO> examUsersWithExamRoomAndSeat
) {
/**
* Create an AttendanceCheckerAppExamInformationDTO from the given exam and its rooms
*
* @param exam the exam
* @param examRooms the rooms used in the exam
* @return information for the attendance checker app
*/
public static AttendanceCheckerAppExamInformationDTO from(Exam exam, Set<ExamRoom> examRooms) {
Set<ExamUser> examUsersWhoHaveBeenDistributed = exam.getExamUsers().stream()
.filter(examUser -> StringUtils.hasText(examUser.getPlannedRoom()) && StringUtils.hasText(examUser.getPlannedSeat()))
.collect(Collectors.toSet());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can just use .toSet() here (Java 16+)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you're using a different Java than me, but that should not be possible: https://bugs.openjdk.org/browse/JDK-8306888


return new AttendanceCheckerAppExamInformationDTO(
exam.getId(),
exam.getTitle(),
exam.getStartDate(),
exam.getEndDate(),
exam.isTestExam(),
exam.getCourse().getId(),
exam.getCourse().getTitle(),
examRooms.stream().map(ExamRoomForAttendanceCheckerDTO::from).collect(Collectors.toSet()),
examUsersWhoHaveBeenDistributed.stream().map(ExamUserWithExamRoomAndSeatDTO::from).collect(Collectors.toSet())
Comment on lines +151 to +152
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here we can also just use toSet()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

);
}
}
// @formatter:on
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
import org.springframework.context.annotation.Lazy;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import de.tum.cit.aet.artemis.core.repository.base.ArtemisJpaRepository;
import de.tum.cit.aet.artemis.exam.config.ExamEnabled;
import de.tum.cit.aet.artemis.exam.domain.room.ExamRoom;

/**
* Spring Data JPA repository for the {@link de.tum.cit.aet.artemis.exam.domain.room.ExamRoom} entity.
* Spring Data JPA repository for the {@link ExamRoom} entity.
*/
@Conditional(ExamEnabled.class)
@Lazy
Expand Down Expand Up @@ -108,4 +109,13 @@ SELECT er.id AS id, er.roomNumber AS roomNumber, er.name AS name, er.createdDate

@EntityGraph(type = EntityGraph.EntityGraphType.LOAD, attributePaths = { "layoutStrategies" })
Set<ExamRoom> findAllWithEagerLayoutStrategiesByIdIn(Set<Long> ids);

@Query("""
SELECT er
FROM ExamRoom er
JOIN ExamRoomExamAssignment erea
ON er.id = erea.examRoom.id
WHERE erea.exam.id = :examId
""")
Set<ExamRoom> findAllByExamId(@Param("examId") long examId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException;
import de.tum.cit.aet.artemis.exam.config.ExamEnabled;
Expand All @@ -23,6 +24,7 @@
import de.tum.cit.aet.artemis.exam.domain.room.ExamRoom;
import de.tum.cit.aet.artemis.exam.domain.room.ExamRoomExamAssignment;
import de.tum.cit.aet.artemis.exam.domain.room.LayoutStrategy;
import de.tum.cit.aet.artemis.exam.dto.room.AttendanceCheckerAppExamInformationDTO;
import de.tum.cit.aet.artemis.exam.dto.room.ExamSeatDTO;
import de.tum.cit.aet.artemis.exam.repository.ExamRepository;
import de.tum.cit.aet.artemis.exam.repository.ExamRoomExamAssignmentRepository;
Expand Down Expand Up @@ -51,13 +53,16 @@ public class ExamRoomDistributionService {

private final ExamUserRepository examUserRepository;

private final ExamUserService examUserService;

public ExamRoomDistributionService(ExamRepository examRepository, ExamRoomRepository examRoomRepository, ExamRoomService examRoomService,
ExamRoomExamAssignmentRepository examRoomExamAssignmentRepository, ExamUserRepository examUserRepository) {
ExamRoomExamAssignmentRepository examRoomExamAssignmentRepository, ExamUserRepository examUserRepository, ExamUserService examUserService) {
this.examRepository = examRepository;
this.examRoomRepository = examRoomRepository;
this.examRoomService = examRoomService;
this.examRoomExamAssignmentRepository = examRoomExamAssignmentRepository;
this.examUserRepository = examUserRepository;
this.examUserService = examUserService;
}

/**
Expand Down Expand Up @@ -247,4 +252,26 @@ private void setPlannedRoomAndPlannedSeatForExamUsersRandomly(Exam exam, Map<Str
examUserRepository.saveAll(exam.getExamUsers());
examRepository.save(exam);
}

/**
* Generates information relevant for displaying rooms and students in the attendance checker app
*
* @param examId The exam id
* @return the generated information
*/
public AttendanceCheckerAppExamInformationDTO getAttendanceCheckerAppInformation(long examId) {
Exam exam = examRepository.findByIdWithExamUsersElseThrow(examId);
Set<ExamUser> examUsers = exam.getExamUsers();

if (examUsers.stream().noneMatch(examUser -> StringUtils.hasText(examUser.getPlannedRoom()) && StringUtils.hasText(examUser.getPlannedSeat()))) {
throw new BadRequestAlertException("No distribution has happened, yet", ENTITY_NAME, "noStudentDistributed");
}

examUserService.setPlannedRoomAndSeatTransientForExamUsers(examUsers);
examUserService.setActualRoomAndSeatTransientForExamUsers(examUsers);

Set<ExamRoom> examRooms = examRoomRepository.findAllByExamId(examId);

return AttendanceCheckerAppExamInformationDTO.from(exam, examRooms);
}
}
Loading
Loading