From 8e503e1e9aed97f81733eac9415995f9754c6841 Mon Sep 17 00:00:00 2001 From: "P.D.Kaumadi" <136589603+Kaumadi2k@users.noreply.github.com> Date: Mon, 2 Dec 2024 18:33:26 +0530 Subject: [PATCH 1/4] conflict resolved --- .../testify/Testify_Backend/repository/CandidateRepository.java | 2 +- .../com/testify/Testify_Backend/service/CandidateService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/testify/Testify_Backend/repository/CandidateRepository.java b/src/main/java/com/testify/Testify_Backend/repository/CandidateRepository.java index a2108b5..960ca2b 100644 --- a/src/main/java/com/testify/Testify_Backend/repository/CandidateRepository.java +++ b/src/main/java/com/testify/Testify_Backend/repository/CandidateRepository.java @@ -22,6 +22,6 @@ public interface CandidateRepository extends JpaRepository { List findCandidatesAssignedToExamWithConflictingExams(Long examId, LocalDateTime startDatetime, LocalDateTime endDatetime); boolean existsByEmail(String currentUserEmail); - Set findAllByEmailIn(List emails); +// Set findAllByEmailIn(List emails); } diff --git a/src/main/java/com/testify/Testify_Backend/service/CandidateService.java b/src/main/java/com/testify/Testify_Backend/service/CandidateService.java index 05381bd..3f9710a 100644 --- a/src/main/java/com/testify/Testify_Backend/service/CandidateService.java +++ b/src/main/java/com/testify/Testify_Backend/service/CandidateService.java @@ -10,7 +10,7 @@ import java.util.List; public interface CandidateService { - List getCandidateExams(); +// List getCandidateExams(); List getAllCandidatesForSearch(); From 3ceee477878815209e8d19743abc9b1dc789b1c9 Mon Sep 17 00:00:00 2001 From: "P.D.Kaumadi" <136589603+Kaumadi2k@users.noreply.github.com> Date: Tue, 3 Dec 2024 08:07:31 +0530 Subject: [PATCH 2/4] examsetter proctoring modified --- .../controller/ExamSetterController.java | 17 +++++++++ .../repository/CandidateRepository.java | 4 ++ .../repository/ExamRepository.java | 5 +++ .../exam_management/ExamResponse.java | 4 ++ .../service/ExamSetterService.java | 7 ++++ .../service/ExamSetterServiceImpl.java | 38 ++++++++++++++----- 6 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java b/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java index 36c0e89..4bd6f12 100644 --- a/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java +++ b/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java @@ -1,7 +1,10 @@ package com.testify.Testify_Backend.controller; import com.testify.Testify_Backend.responses.GenericAddOrUpdateResponse; +import com.testify.Testify_Backend.responses.exam_management.CandidateResponse; +import com.testify.Testify_Backend.responses.exam_management.ExamResponse; import com.testify.Testify_Backend.responses.exam_management.OrganizationResponse; +import com.testify.Testify_Backend.service.ExamManagementService; import com.testify.Testify_Backend.service.ExamSetterService; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; @@ -9,6 +12,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.List; import java.util.Set; @RestController @@ -17,6 +21,7 @@ public class ExamSetterController { private static final Logger log = LoggerFactory.getLogger(ExamSetterController.class); private final ExamSetterService examSetterService; + private final ExamManagementService examManagementService; @GetMapping("/{setterId}/getOrganizations") public ResponseEntity> getOrganizations(@PathVariable("setterId") long setterId) { @@ -36,4 +41,16 @@ public ResponseEntity addSetterToOrganization(@PathV GenericAddOrUpdateResponse response = examSetterService.addSetterToOrganization(token); return ResponseEntity.ok(response); } + + @GetMapping("/proctor/{proctorId}/{organizationId}") + public ResponseEntity> getExamsForProctor(@PathVariable Long proctorId, @PathVariable Long organizationId) { + Set exams = examSetterService.getExamsForProctor(proctorId, organizationId); + return ResponseEntity.ok(exams); + } + + @GetMapping("/{examId}/candidates") + public ResponseEntity> getCandidatesForExam(@PathVariable Long examId) { + Set candidates = examSetterService.getCandidatesForExam(examId); + return ResponseEntity.ok(candidates); + } } diff --git a/src/main/java/com/testify/Testify_Backend/repository/CandidateRepository.java b/src/main/java/com/testify/Testify_Backend/repository/CandidateRepository.java index 2c59e61..e96dc14 100644 --- a/src/main/java/com/testify/Testify_Backend/repository/CandidateRepository.java +++ b/src/main/java/com/testify/Testify_Backend/repository/CandidateRepository.java @@ -3,6 +3,7 @@ import com.testify.Testify_Backend.model.Candidate; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.time.LocalDateTime; @@ -22,5 +23,8 @@ public interface CandidateRepository extends JpaRepository { List findCandidatesAssignedToExamWithConflictingExams(Long examId, LocalDateTime startDatetime, LocalDateTime endDatetime); boolean existsByEmail(String currentUserEmail); + + @Query("SELECT c FROM Candidate c JOIN c.exams e WHERE e.id = :examId") + Set findByExamId(@Param("examId") Long examId); } diff --git a/src/main/java/com/testify/Testify_Backend/repository/ExamRepository.java b/src/main/java/com/testify/Testify_Backend/repository/ExamRepository.java index 046653f..3467f69 100644 --- a/src/main/java/com/testify/Testify_Backend/repository/ExamRepository.java +++ b/src/main/java/com/testify/Testify_Backend/repository/ExamRepository.java @@ -31,5 +31,10 @@ public interface ExamRepository extends JpaRepository { // Fetch all public (non-private) exams @Query("SELECT e FROM Exam e WHERE e.isPrivate = false") List findAllPublicExams(); + + @Query("SELECT e FROM Exam e JOIN e.proctors p WHERE p.id = :proctorId AND e.organization.id = :organizationId") + Set findByProctorIdAndOrganizationId(@Param("proctorId") Long proctorId, @Param("organizationId") Long organizationId); + + } diff --git a/src/main/java/com/testify/Testify_Backend/responses/exam_management/ExamResponse.java b/src/main/java/com/testify/Testify_Backend/responses/exam_management/ExamResponse.java index 1ea95f9..5bc9a76 100644 --- a/src/main/java/com/testify/Testify_Backend/responses/exam_management/ExamResponse.java +++ b/src/main/java/com/testify/Testify_Backend/responses/exam_management/ExamResponse.java @@ -31,4 +31,8 @@ public class ExamResponse { private OrderType orderType; private FixedOrderResponse fixedOrder; private RandomOrderResponse randomOrder; + private boolean realTimeMonitoring; + private String zoomLink; + private boolean browserLockdown; + private boolean hosted; } diff --git a/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java b/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java index 1e06c7f..e05b67f 100644 --- a/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java +++ b/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java @@ -1,8 +1,11 @@ package com.testify.Testify_Backend.service; import com.testify.Testify_Backend.responses.GenericAddOrUpdateResponse; +import com.testify.Testify_Backend.responses.exam_management.CandidateResponse; +import com.testify.Testify_Backend.responses.exam_management.ExamResponse; import com.testify.Testify_Backend.responses.exam_management.OrganizationResponse; +import java.util.List; import java.util.Set; public interface ExamSetterService { @@ -11,4 +14,8 @@ public interface ExamSetterService { long checkSetterRegistration(String token); GenericAddOrUpdateResponse addSetterToOrganization(String token); + + Set getExamsForProctor(Long proctorId, Long organizationId); + + Set getCandidatesForExam(Long examId); } diff --git a/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java b/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java index 7239611..159fb38 100644 --- a/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java +++ b/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java @@ -1,22 +1,19 @@ package com.testify.Testify_Backend.service; -import com.testify.Testify_Backend.model.ExamSetter; -import com.testify.Testify_Backend.model.ExamSetterInvitation; -import com.testify.Testify_Backend.model.Organization; -import com.testify.Testify_Backend.repository.ExamSetterInvitationRepository; -import com.testify.Testify_Backend.repository.ExamSetterRepository; -import com.testify.Testify_Backend.repository.OrganizationRepository; +import com.testify.Testify_Backend.model.*; +import com.testify.Testify_Backend.repository.*; import com.testify.Testify_Backend.responses.GenericAddOrUpdateResponse; +import com.testify.Testify_Backend.responses.exam_management.CandidateResponse; +import com.testify.Testify_Backend.responses.exam_management.ExamResponse; import com.testify.Testify_Backend.responses.exam_management.OrganizationResponse; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; +import java.util.*; @Service @RequiredArgsConstructor @@ -24,6 +21,8 @@ public class ExamSetterServiceImpl implements ExamSetterService { private final ExamSetterRepository examSetterRepository; private final ExamSetterInvitationRepository examSetterInvitationRepository; private final OrganizationRepository organizationRepository; + private final ExamRepository examRepository; + private final CandidateRepository candidateRepository; @Autowired private ModelMapper modelMapper; @@ -70,4 +69,25 @@ public GenericAddOrUpdateResponse addSetterToOrganization(String token) { response.setMessage("Successfully added an organization"); return response; } + + @Override + @Transactional + public Set getExamsForProctor(Long proctorId, Long organizationId) { + Set exams = examRepository.findByProctorIdAndOrganizationId(proctorId, organizationId); + Set examResponses = new HashSet<>(); + for (Exam exam : exams) { + examResponses.add(modelMapper.map(exam, ExamResponse.class)); + } + return examResponses; + } + + @Override + public Set getCandidatesForExam(Long examId) { + Set candidates = candidateRepository.findByExamId(examId); + Set candidateResponses = new HashSet<>(); + for (Candidate candidate : candidates) { + candidateResponses.add(modelMapper.map(candidate, CandidateResponse.class)); + } + return candidateResponses; + } } From 620390077fe2a877717ca8f3f9178bdb87b666e7 Mon Sep 17 00:00:00 2001 From: "P.D.Kaumadi" <136589603+Kaumadi2k@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:44:34 +0530 Subject: [PATCH 3/4] exam setter proctoring modified --- .../Testify_Backend/controller/ExamSetterController.java | 4 ++-- .../Testify_Backend/repository/ExamRepository.java | 2 +- .../Testify_Backend/service/ExamSetterService.java | 2 +- .../Testify_Backend/service/ExamSetterServiceImpl.java | 9 ++++++--- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java b/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java index 6985b07..d869b18 100644 --- a/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java +++ b/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java @@ -46,8 +46,8 @@ public ResponseEntity addSetterToOrganization(@PathV } @GetMapping("/proctor/{proctorId}/{organizationId}") - public ResponseEntity> getExamsForProctor(@PathVariable Long proctorId, @PathVariable Long organizationId) { - Set exams = examSetterService.getExamsForProctor(proctorId, organizationId); + public ResponseEntity> getExamsForProctor(@PathVariable Long proctorId, @PathVariable Long organizationId) { + List exams = examSetterService.getExamsForProctor(proctorId, organizationId); return ResponseEntity.ok(exams); } diff --git a/src/main/java/com/testify/Testify_Backend/repository/ExamRepository.java b/src/main/java/com/testify/Testify_Backend/repository/ExamRepository.java index 964be3c..d8139f6 100644 --- a/src/main/java/com/testify/Testify_Backend/repository/ExamRepository.java +++ b/src/main/java/com/testify/Testify_Backend/repository/ExamRepository.java @@ -33,7 +33,7 @@ public interface ExamRepository extends JpaRepository { List findAllPublicExams(); @Query("SELECT e FROM Exam e JOIN e.proctors p WHERE p.id = :proctorId AND e.organization.id = :organizationId") - Set findByProctorIdAndOrganizationId(@Param("proctorId") Long proctorId, @Param("organizationId") Long organizationId); + List findByProctorIdAndOrganizationId(@Param("proctorId") Long proctorId, @Param("organizationId") Long organizationId); List findByModeratorId(long moderatorId); diff --git a/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java b/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java index ca50bd6..1bd3c71 100644 --- a/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java +++ b/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java @@ -16,7 +16,7 @@ public interface ExamSetterService { GenericAddOrUpdateResponse addSetterToOrganization(String token); - Set getExamsForProctor(Long proctorId, Long organizationId); + List getExamsForProctor(Long proctorId, Long organizationId); Set getCandidatesForExam(Long examId); List getModeratingExams(long examSetterId); diff --git a/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java b/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java index f493bf7..f8480d4 100644 --- a/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java +++ b/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java @@ -88,15 +88,16 @@ public GenericAddOrUpdateResponse addSetterToOrganization(String token) { @Override @Transactional - public Set getExamsForProctor(Long proctorId, Long organizationId) { - Set exams = examRepository.findByProctorIdAndOrganizationId(proctorId, organizationId); - Set examResponses = new HashSet<>(); + public List getExamsForProctor(Long proctorId, Long organizationId) { + List exams = examRepository.findByProctorIdAndOrganizationId(proctorId, organizationId); // Ensure repository method returns a List + List examResponses = new ArrayList<>(); for (Exam exam : exams) { examResponses.add(modelMapper.map(exam, ExamResponse.class)); } return examResponses; } + @Override public Set getCandidatesForExam(Long examId) { Set candidates = candidateRepository.findByExamId(examId); @@ -104,7 +105,9 @@ public Set getCandidatesForExam(Long examId) { for (Candidate candidate : candidates) { candidateResponses.add(modelMapper.map(candidate, CandidateResponse.class)); } + return candidateResponses; + } public List getModeratingExams(long examSetterId) { return examRepository.findByModeratorId(examSetterId).stream() .map(exam -> new ModerateExamResponse( From f084cf2c46d4a8521657e5952d20702135de4f6a Mon Sep 17 00:00:00 2001 From: "P.D.Kaumadi" <136589603+Kaumadi2k@users.noreply.github.com> Date: Tue, 3 Dec 2024 17:41:20 +0530 Subject: [PATCH 4/4] setter proctoring done --- .../controller/ExamSetterController.java | 6 ++++ .../Testify_Backend/model/Candidate.java | 4 +++ .../testify/Testify_Backend/model/Exam.java | 3 ++ .../Testify_Backend/model/ProctorComment.java | 32 +++++++++++++++++++ .../repository/ProctorCommentRepository.java | 8 +++++ .../service/ExamSetterService.java | 2 ++ .../service/ExamSetterServiceImpl.java | 17 ++++++++++ 7 files changed, 72 insertions(+) create mode 100644 src/main/java/com/testify/Testify_Backend/model/ProctorComment.java create mode 100644 src/main/java/com/testify/Testify_Backend/repository/ProctorCommentRepository.java diff --git a/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java b/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java index d869b18..676feea 100644 --- a/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java +++ b/src/main/java/com/testify/Testify_Backend/controller/ExamSetterController.java @@ -68,4 +68,10 @@ public ResponseEntity> getModeratingExams(@PathVariab return ResponseEntity.ok(responses); } + @PostMapping("/{candidateId}/{examId}/proctorComments") + public ResponseEntity addComment(@PathVariable Long candidateId, @PathVariable Long examId, @RequestBody String content) { + examSetterService.addCommentToCandidate(candidateId, examId, content); + return ResponseEntity.ok("Comment added successfully"); + } + } diff --git a/src/main/java/com/testify/Testify_Backend/model/Candidate.java b/src/main/java/com/testify/Testify_Backend/model/Candidate.java index d0fe041..e8f73f1 100644 --- a/src/main/java/com/testify/Testify_Backend/model/Candidate.java +++ b/src/main/java/com/testify/Testify_Backend/model/Candidate.java @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; import lombok.experimental.SuperBuilder; +import java.util.List; import java.util.Set; @Entity @@ -26,4 +27,7 @@ public class Candidate extends User{ @ManyToMany(mappedBy = "candidates") private Set exams; + @OneToMany(mappedBy = "candidate", cascade = CascadeType.ALL, orphanRemoval = true) + private List comments; + } diff --git a/src/main/java/com/testify/Testify_Backend/model/Exam.java b/src/main/java/com/testify/Testify_Backend/model/Exam.java index 5a8c71e..5f55f4e 100644 --- a/src/main/java/com/testify/Testify_Backend/model/Exam.java +++ b/src/main/java/com/testify/Testify_Backend/model/Exam.java @@ -116,4 +116,7 @@ public class Exam { @Column(nullable = false) private boolean hosted = false; + @OneToMany(mappedBy = "exam", cascade = CascadeType.ALL, orphanRemoval = true) + private List proctorComments; + } diff --git a/src/main/java/com/testify/Testify_Backend/model/ProctorComment.java b/src/main/java/com/testify/Testify_Backend/model/ProctorComment.java new file mode 100644 index 0000000..487eddd --- /dev/null +++ b/src/main/java/com/testify/Testify_Backend/model/ProctorComment.java @@ -0,0 +1,32 @@ +package com.testify.Testify_Backend.model; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.time.LocalDateTime; + +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class ProctorComment { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne + @JoinColumn(name = "candidate_id", nullable = false) + private Candidate candidate; + + @ManyToOne + @JoinColumn(name = "exam_id", nullable = false) + private Exam exam; + + private String content; + + private LocalDateTime createdAt; +} diff --git a/src/main/java/com/testify/Testify_Backend/repository/ProctorCommentRepository.java b/src/main/java/com/testify/Testify_Backend/repository/ProctorCommentRepository.java new file mode 100644 index 0000000..1c9b174 --- /dev/null +++ b/src/main/java/com/testify/Testify_Backend/repository/ProctorCommentRepository.java @@ -0,0 +1,8 @@ +package com.testify.Testify_Backend.repository; + +import com.testify.Testify_Backend.model.ProctorComment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ProctorCommentRepository extends JpaRepository { + +} diff --git a/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java b/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java index 1bd3c71..343963f 100644 --- a/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java +++ b/src/main/java/com/testify/Testify_Backend/service/ExamSetterService.java @@ -20,4 +20,6 @@ public interface ExamSetterService { Set getCandidatesForExam(Long examId); List getModeratingExams(long examSetterId); + + void addCommentToCandidate(Long candidateId, Long examId, String content); } diff --git a/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java b/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java index f8480d4..090c8b1 100644 --- a/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java +++ b/src/main/java/com/testify/Testify_Backend/service/ExamSetterServiceImpl.java @@ -24,6 +24,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; import java.util.*; import java.util.HashSet; import java.util.List; @@ -39,6 +40,7 @@ public class ExamSetterServiceImpl implements ExamSetterService { private final OrganizationRepository organizationRepository; private final ExamRepository examRepository; private final CandidateRepository candidateRepository; + private final ProctorCommentRepository proctorCommentRepository; @Autowired private ModelMapper modelMapper; @@ -118,4 +120,19 @@ public List getModeratingExams(long examSetterId) { )) .collect(Collectors.toList()); } + + @Override + public void addCommentToCandidate(Long candidateId, Long examId, String content) { + Candidate candidate = candidateRepository.findById(candidateId) + .orElseThrow(() -> new RuntimeException("Candidate not found")); + Exam exam = examRepository.findById(examId).orElseThrow(() -> new RuntimeException("Exam not found")); + + ProctorComment comment = new ProctorComment(); + comment.setCandidate(candidate); + comment.setExam(exam); + comment.setContent(content); + comment.setCreatedAt(LocalDateTime.now()); + + proctorCommentRepository.save(comment); + } }