From 275402e682bf0797f3cf3c81570e41b146a86693 Mon Sep 17 00:00:00 2001 From: mp-dg <57503145+MP-DG@users.noreply.github.com> Date: Thu, 15 Jan 2026 21:14:48 +0100 Subject: [PATCH] moved proactive feedback logic out of user question workflow --- .../controller/TutorController.java | 14 +++++++++++ .../tutor_service/service/TutorService.java | 24 +++++++++---------- .../resources/graphql/service/query.graphqls | 7 ++++++ .../controller/TutorControllerTest.java | 22 +++++++++++++++++ .../service/TutorServiceTest.java | 15 +++++++----- 5 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/main/java/de/unistuttgart/iste/meitrex/tutor_service/controller/TutorController.java b/src/main/java/de/unistuttgart/iste/meitrex/tutor_service/controller/TutorController.java index 7288c6a..7ff5d86 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/tutor_service/controller/TutorController.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/tutor_service/controller/TutorController.java @@ -78,6 +78,20 @@ public List allProactiveFeedback( .toList(); } + /** + * Retrieves the latest proactive feedback for the current user. + * The feedback is deleted after retrieval and must be less than 30 minutes old. + * + * @param currentUser the currently logged-in user + * @return feedback text if available, otherwise null + */ + @QueryMapping + public String latestProactiveFeedback( + @ContextValue final LoggedInUser currentUser + ) { + return tutorService.getLatestProactiveFeedback(currentUser).orElse(null); + } + /** * GraphQL subscription for real-time proactive feedback. * Frontend subscribes to this and receives feedback automatically when generated. diff --git a/src/main/java/de/unistuttgart/iste/meitrex/tutor_service/service/TutorService.java b/src/main/java/de/unistuttgart/iste/meitrex/tutor_service/service/TutorService.java index 258a35b..81f264b 100644 --- a/src/main/java/de/unistuttgart/iste/meitrex/tutor_service/service/TutorService.java +++ b/src/main/java/de/unistuttgart/iste/meitrex/tutor_service/service/TutorService.java @@ -69,7 +69,7 @@ public class TutorService { /** * Handles a user’s question by categorizing it and returning an appropriate response. * Lecture questions are further processed, while other categories currently return default answers. - * Special handling: if the user input is "proactivefeedback", retrieves and deletes the latest saved feedback for the user. + * * @param userQuestion the question asked by the user * @param courseId the ID of the course, required for lecture-related questions @@ -77,17 +77,6 @@ public class TutorService { * @return a response object containing the answer or a default message */ public LectureQuestionResponse handleUserQuestion(String userQuestion, UUID courseId, LoggedInUser currentUser){ - - // Special handling for proactive feedback retrieval. Will be removed once proactive feedback is integrated into the main flow and graphql works correctly. - if ("proactivefeedback".equalsIgnoreCase(userQuestion.trim())) { - Optional feedback = proactiveFeedbackService.getAndDeleteLatestFeedback(currentUser.getId()); - if (feedback.isPresent()) { - return new LectureQuestionResponse(feedback.get(), List.of()); - } else { - return new LectureQuestionResponse("No proactive feedback available at the moment.", List.of()); - } - } - log.info("[TUTOR] User {} asked question: {}", currentUser.getId(), userQuestion); CategorizedQuestion categorizedQuestion = preprocessQuestion(userQuestion); @@ -124,6 +113,17 @@ public LectureQuestionResponse handleUserQuestion(String userQuestion, UUID cour return new LectureQuestionResponse(ERROR_MESSAGE, List.of()); } + /** + * Retrieves the latest proactive feedback for the given user. + * The feedback is deleted after retrieval and must be less than 30 minutes old. + * + * @param currentUser the currently logged-in user + * @return optional containing feedback text if available, otherwise empty + */ + public Optional getLatestProactiveFeedback(LoggedInUser currentUser) { + return proactiveFeedbackService.getAndDeleteLatestFeedback(currentUser.getId()); + } + private LectureQuestionResponse answerLectureQuestion(String question, UUID courseId, LoggedInUser currentUser){ Optional playerType = userPlayerTypeService.getPrimaryPlayerType(currentUser.getId()); diff --git a/src/main/resources/graphql/service/query.graphqls b/src/main/resources/graphql/service/query.graphqls index 1be6f33..fd637c1 100644 --- a/src/main/resources/graphql/service/query.graphqls +++ b/src/main/resources/graphql/service/query.graphqls @@ -10,4 +10,11 @@ type Query { Retrieves all proactive feedback for the current user, ordered by most recent first. """ allProactiveFeedback: [ProactiveFeedback!]! + + """ + Retrieves the latest proactive feedback for the current user (any assessment). + The feedback is deleted after retrieval and must be less than 30 minutes old. + Returns the feedback text or null if no feedback is available. + """ + latestProactiveFeedback: String } \ No newline at end of file diff --git a/src/test/java/de/unistuttgart/iste/meitrex/tutor_service/controller/TutorControllerTest.java b/src/test/java/de/unistuttgart/iste/meitrex/tutor_service/controller/TutorControllerTest.java index 181eb1b..d1c32ca 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/tutor_service/controller/TutorControllerTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/tutor_service/controller/TutorControllerTest.java @@ -208,6 +208,28 @@ void testAllProactiveFeedback_empty() { assertTrue(result.isEmpty()); } + @Test + void testLatestProactiveFeedback_withFeedback() { + String feedback = "Great job on your assignment!"; + when(tutorService.getLatestProactiveFeedback(loggedInUser)) + .thenReturn(Optional.of(feedback)); + + String result = tutorController.latestProactiveFeedback(loggedInUser); + + assertEquals(feedback, result); + verify(tutorService).getLatestProactiveFeedback(loggedInUser); + } + + @Test + void testLatestProactiveFeedback_noFeedback() { + when(tutorService.getLatestProactiveFeedback(loggedInUser)) + .thenReturn(Optional.empty()); + + String result = tutorController.latestProactiveFeedback(loggedInUser); + + assertNull(result); + } + @Test void testProactiveFeedbackAdded_subscription() { UUID userId = UUID.randomUUID(); diff --git a/src/test/java/de/unistuttgart/iste/meitrex/tutor_service/service/TutorServiceTest.java b/src/test/java/de/unistuttgart/iste/meitrex/tutor_service/service/TutorServiceTest.java index 2ba81ba..f89e201 100644 --- a/src/test/java/de/unistuttgart/iste/meitrex/tutor_service/service/TutorServiceTest.java +++ b/src/test/java/de/unistuttgart/iste/meitrex/tutor_service/service/TutorServiceTest.java @@ -19,6 +19,8 @@ import static de.unistuttgart.iste.meitrex.common.testutil.TestUsers.userWithMembershipInCourseWithId; import static org.mockito.Mockito.when; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; public class TutorServiceTest { @@ -209,23 +211,24 @@ void testHandleUserQuestion_withCodeFeedbackNoSubmissions() { } @Test - void testHandleUserQuestion_withProactiveFeedbackKeyword() { + void testGetLatestProactiveFeedback_withFeedback() { String feedback = "Great job on your assignment!"; when(proactiveFeedbackService.getAndDeleteLatestFeedback(loggedInUser.getId())) .thenReturn(Optional.of(feedback)); - LectureQuestionResponse response = tutorService.handleUserQuestion("proactivefeedback", courseId, loggedInUser); - assertEquals(feedback, response.getAnswer()); + Optional response = tutorService.getLatestProactiveFeedback(loggedInUser); + assertTrue(response.isPresent()); + assertEquals(feedback, response.get()); Mockito.verify(proactiveFeedbackService).getAndDeleteLatestFeedback(loggedInUser.getId()); } @Test - void testHandleUserQuestion_withProactiveFeedbackKeywordNoFeedback() { + void testGetLatestProactiveFeedback_withNoFeedback() { when(proactiveFeedbackService.getAndDeleteLatestFeedback(loggedInUser.getId())) .thenReturn(Optional.empty()); - LectureQuestionResponse response = tutorService.handleUserQuestion("proactivefeedback", courseId, loggedInUser); - assertEquals("No proactive feedback available at the moment.", response.getAnswer()); + Optional response = tutorService.getLatestProactiveFeedback(loggedInUser); + assertFalse(response.isPresent()); } @Test