From ffb571fd234ef54b544d529c97bc3e03c39203f4 Mon Sep 17 00:00:00 2001
From: Andreas Svanberg <andreass@dsv.su.se>
Date: Wed, 25 Sep 2024 13:57:57 +0200
Subject: [PATCH] Notify the author when reflection improvements are needed

Can not send the notification from the Notifications class since that class is registered in the test-context and for some reason HSQLDB fails with some unknown check constraint violation with absolutely no information about why.

For some reason it is not possible to debug HSQLDB with breakpoints to step through and see exactly why it fails, so registering a new single purpose class in the cross-cutting module (that's not available in test) is used as a work-around.
---
 .../dataobject/ProjectEvent.java              |  2 +-
 .../notifications/notifications.properties    |  4 +++
 .../ReflectionImprovementsRequestedEvent.java |  7 ++++
 .../reflection/ReflectionServiceImpl.java     | 10 +++++-
 .../crosscutting/CrosscuttingModule.java      |  1 +
 .../crosscutting/NotifyFailedReflection.java  | 33 +++++++++++++++++++
 .../dsv/scipro/wicket-package.utf8.properties |  1 +
 7 files changed, 56 insertions(+), 2 deletions(-)
 create mode 100644 core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsRequestedEvent.java
 create mode 100644 view/src/main/java/se/su/dsv/scipro/crosscutting/NotifyFailedReflection.java

diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java
index c8c3e51032..db38cb81e1 100755
--- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java
+++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/ProjectEvent.java
@@ -20,7 +20,7 @@ public class ProjectEvent extends NotificationEvent {
         ROUGH_DRAFT_APPROVAL_APPROVED, ROUGH_DRAFT_APPROVAL_REJECTED, REVIEWER_GRADING_REPORT_SUBMITTED,
         ONE_YEAR_PASSED_FROM_LATEST_ANNUAL_REVIEW, SUPERVISOR_GRADING_INITIAL_ASSESSMENT_DONE,
         EXPORTED_SUCCESS, REVIEWER_GRADING_INITIAL_ASSESSMENT_DONE, FIRST_MEETING, OPPOSITION_FAILED, PARTICIPATION_APPROVED, COMPLETED,
-        PARTICIPATION_FAILED
+        REFLECTION_IMPROVEMENTS_REQUESTED, PARTICIPATION_FAILED
     }
 
     @ManyToOne
diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/notifications.properties b/core/src/main/java/se/su/dsv/scipro/notifications/notifications.properties
index a972eac30e..513d92cbd5 100755
--- a/core/src/main/java/se/su/dsv/scipro/notifications/notifications.properties
+++ b/core/src/main/java/se/su/dsv/scipro/notifications/notifications.properties
@@ -85,6 +85,10 @@ PROJECT.PARTICIPATION_APPROVED.body = Your active participation on {0} has been
 PROJECT.PARTICIPATION_FAILED.title = Your active participation on {1} did not meet the minimum requirements.
 PROJECT.PARTICIPATION_FAILED.body = Your active participation did not meet the minimum requirements set, and you will \
   have to be an active participant on a different final seminar to pass this step.
+PROJECT.REFLECTION_IMPROVEMENTS_REQUESTED.title = Reflection improvements requested
+PROJECT.REFLECTION_IMPROVEMENTS_REQUESTED.body = The supervisor has deemed that the reflection submitted does not meet \
+  the minimum requirements and has requested improvements. Please log into SciPro and submit a new reflection. \
+  Their comments can be seen below:\n\n{0}
 
 FORUM.NEW_FORUM_POST.title = Forum post: {2}
 FORUM.NEW_FORUM_POST.body = New forum post submitted:<br /><br />{0}
diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsRequestedEvent.java b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsRequestedEvent.java
new file mode 100644
index 0000000000..07d8811f99
--- /dev/null
+++ b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionImprovementsRequestedEvent.java
@@ -0,0 +1,7 @@
+package se.su.dsv.scipro.reflection;
+
+import se.su.dsv.scipro.project.Project;
+import se.su.dsv.scipro.system.User;
+
+public record ReflectionImprovementsRequestedEvent(Project project, User author, String supervisorComment) {
+}
diff --git a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java
index c61cfd9893..6b08ec3ea6 100644
--- a/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/reflection/ReflectionServiceImpl.java
@@ -1,5 +1,6 @@
 package se.su.dsv.scipro.reflection;
 
+import com.google.common.eventbus.EventBus;
 import com.google.inject.persist.Transactional;
 import se.su.dsv.scipro.finalseminar.AuthorRepository;
 import se.su.dsv.scipro.finalseminar.FinalSeminarService;
@@ -15,11 +16,17 @@ import java.util.Optional;
 class ReflectionServiceImpl implements ReflectionService {
     private final AuthorRepository authorRepository;
     private final FinalSeminarService finalSeminarService;
+    private final EventBus eventBus;
 
     @Inject
-    ReflectionServiceImpl(AuthorRepository authorRepository, FinalSeminarService finalSeminarService) {
+    ReflectionServiceImpl(
+            AuthorRepository authorRepository,
+            FinalSeminarService finalSeminarService,
+            EventBus eventBus)
+    {
         this.authorRepository = authorRepository;
         this.finalSeminarService = finalSeminarService;
+        this.eventBus = eventBus;
     }
 
     @Override
@@ -63,6 +70,7 @@ class ReflectionServiceImpl implements ReflectionService {
                     author.setReflectionStatus(ReflectionStatus.IMPROVEMENTS_NEEDED);
                     author.setReflectionSupervisorComment(supervisorComment);
                 });
+        eventBus.post(new ReflectionImprovementsRequestedEvent(project, user, supervisorComment));
     }
 
     @Override
diff --git a/view/src/main/java/se/su/dsv/scipro/crosscutting/CrosscuttingModule.java b/view/src/main/java/se/su/dsv/scipro/crosscutting/CrosscuttingModule.java
index fc50e7ff37..745812b613 100644
--- a/view/src/main/java/se/su/dsv/scipro/crosscutting/CrosscuttingModule.java
+++ b/view/src/main/java/se/su/dsv/scipro/crosscutting/CrosscuttingModule.java
@@ -13,5 +13,6 @@ public class CrosscuttingModule extends AbstractModule {
         bind(ReviewerAssignedNotifications.class).asEagerSingleton();
         bind(ReviewerAssignedDeadline.class).asEagerSingleton();
         bind(ForwardPhase2Feedback.class).asEagerSingleton();
+        bind(NotifyFailedReflection.class).asEagerSingleton();
     }
 }
diff --git a/view/src/main/java/se/su/dsv/scipro/crosscutting/NotifyFailedReflection.java b/view/src/main/java/se/su/dsv/scipro/crosscutting/NotifyFailedReflection.java
new file mode 100644
index 0000000000..e626522bec
--- /dev/null
+++ b/view/src/main/java/se/su/dsv/scipro/crosscutting/NotifyFailedReflection.java
@@ -0,0 +1,33 @@
+package se.su.dsv.scipro.crosscutting;
+
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+import jakarta.inject.Inject;
+import se.su.dsv.scipro.data.dataobjects.Member;
+import se.su.dsv.scipro.notifications.NotificationController;
+import se.su.dsv.scipro.notifications.dataobject.NotificationSource;
+import se.su.dsv.scipro.notifications.dataobject.ProjectEvent;
+import se.su.dsv.scipro.reflection.ReflectionImprovementsRequestedEvent;
+
+import java.util.Set;
+
+public class NotifyFailedReflection {
+    private final NotificationController notificationController;
+
+    @Inject
+    public NotifyFailedReflection(NotificationController notificationController, EventBus eventBus) {
+        this.notificationController = notificationController;
+        eventBus.register(this);
+    }
+
+    @Subscribe
+    public void reflectionImprovementsRequested(ReflectionImprovementsRequestedEvent event) {
+        NotificationSource source = new NotificationSource();
+        source.setMessage(event.supervisorComment());
+        notificationController.notifyCustomProject(
+                event.project(),
+                ProjectEvent.Event.REFLECTION_IMPROVEMENTS_REQUESTED,
+                source,
+                Set.of(new Member(event.author(), Member.Type.AUTHOR)));
+    }
+}
diff --git a/view/src/main/java/se/su/dsv/scipro/wicket-package.utf8.properties b/view/src/main/java/se/su/dsv/scipro/wicket-package.utf8.properties
index 74aa56c867..dd8b4c1895 100644
--- a/view/src/main/java/se/su/dsv/scipro/wicket-package.utf8.properties
+++ b/view/src/main/java/se/su/dsv/scipro/wicket-package.utf8.properties
@@ -65,6 +65,7 @@ ProjectEvent.FIRST_MEETING = First meeting created. (with date, time, place/room
 ProjectEvent.OPPOSITION_FAILED = An author fails their opposition.
 ProjectEvent.PARTICIPATION_APPROVED = An author's active participation is approved.
 ProjectEvent.PARTICIPATION_FAILED = An author fails their active participation.
+ProjectEvent.REFLECTION_IMPROVEMENTS_REQUESTED = Reflection improvements requested.
 
 ProjectForumEvent.NEW_FORUM_POST = Forum thread created.
 ProjectForumEvent.NEW_FORUM_POST_COMMENT = Comment posted in forum thread.