From 06c1e81978a6d3089dfaeee99b7ce6e2d231604f Mon Sep 17 00:00:00 2001
From: Andreas Svanberg <andreass@dsv.su.se>
Date: Mon, 10 Feb 2025 10:48:20 +0100
Subject: [PATCH] Send out notification when an opponent submits a report

---
 .../main/java/se/su/dsv/scipro/CoreConfig.java  |  6 ++++--
 .../java/se/su/dsv/scipro/DataInitializer.java  | 17 +++++++++++++++++
 .../dsv/scipro/notifications/Notifications.java | 12 ++++++++++++
 .../notifications/dataobject/SeminarEvent.java  |  1 +
 .../notifications/notifications.properties      |  2 ++
 .../report/OppositionReportServiceImpl.java     | 10 ++++++++--
 .../report/OppositionReportSubmittedEvent.java  |  9 +++++++++
 .../dsv/scipro/wicket-package.utf8.properties   |  1 +
 8 files changed, 54 insertions(+), 4 deletions(-)
 create mode 100644 core/src/main/java/se/su/dsv/scipro/report/OppositionReportSubmittedEvent.java

diff --git a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
index a8736d4f05..d401e5b276 100644
--- a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
+++ b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
@@ -688,13 +688,15 @@ public class CoreConfig {
         OppositionReportRepo oppositionReportRepository,
         GradingReportTemplateRepo gradingReportTemplateRepository,
         FileService fileService,
-        FinalSeminarOppositionRepo finalSeminarOppositionRepository
+        FinalSeminarOppositionRepo finalSeminarOppositionRepository,
+        EventBus eventBus
     ) {
         return new OppositionReportServiceImpl(
             oppositionReportRepository,
             gradingReportTemplateRepository,
             fileService,
-            finalSeminarOppositionRepository
+            finalSeminarOppositionRepository,
+            eventBus
         );
     }
 
diff --git a/core/src/main/java/se/su/dsv/scipro/DataInitializer.java b/core/src/main/java/se/su/dsv/scipro/DataInitializer.java
index 98ebc08e63..95569ba439 100644
--- a/core/src/main/java/se/su/dsv/scipro/DataInitializer.java
+++ b/core/src/main/java/se/su/dsv/scipro/DataInitializer.java
@@ -13,6 +13,7 @@ import java.time.ZonedDateTime;
 import java.util.*;
 import java.util.function.Function;
 import se.su.dsv.scipro.checklist.ChecklistCategory;
+import se.su.dsv.scipro.data.dataobjects.Member;
 import se.su.dsv.scipro.file.FileReference;
 import se.su.dsv.scipro.file.FileService;
 import se.su.dsv.scipro.file.FileUpload;
@@ -23,6 +24,9 @@ import se.su.dsv.scipro.match.Keyword;
 import se.su.dsv.scipro.milestones.dataobjects.MilestoneActivityTemplate;
 import se.su.dsv.scipro.milestones.dataobjects.MilestonePhaseTemplate;
 import se.su.dsv.scipro.milestones.service.MilestoneActivityTemplateService;
+import se.su.dsv.scipro.notifications.dataobject.Notification;
+import se.su.dsv.scipro.notifications.dataobject.SeminarEvent;
+import se.su.dsv.scipro.notifications.settings.service.ReceiverConfigurationService;
 import se.su.dsv.scipro.profiles.CurrentProfile;
 import se.su.dsv.scipro.profiles.Profiles;
 import se.su.dsv.scipro.project.Project;
@@ -57,6 +61,9 @@ public class DataInitializer implements Lifecycle {
     @Inject
     private Provider<EntityManager> em;
 
+    @Inject
+    private ReceiverConfigurationService receiverConfigurationService;
+
     private static final String MAIL = "@example.com";
 
     private static final String ADMIN = "admin";
@@ -104,12 +111,22 @@ public class DataInitializer implements Lifecycle {
             createUsers();
             createProjects();
             createPastFinalSeminar();
+            setUpNotifications();
         }
         if (profile.getCurrentProfile() == Profiles.DEV && noAdminUser()) {
             createAdmin();
         }
     }
 
+    private void setUpNotifications() {
+        receiverConfigurationService.setReceiving(
+            Notification.Type.FINAL_SEMINAR,
+            SeminarEvent.Event.OPPOSITION_REPORT_SUBMITTED,
+            Member.Type.SUPERVISOR,
+            true
+        );
+    }
+
     private void createPastFinalSeminar() {
         FileReference document = fileService.storeFile(
             new SimpleTextFile(sture_student, "document.txt", "Hello World")
diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/Notifications.java b/core/src/main/java/se/su/dsv/scipro/notifications/Notifications.java
index abf4fcb159..cea9c4e28a 100644
--- a/core/src/main/java/se/su/dsv/scipro/notifications/Notifications.java
+++ b/core/src/main/java/se/su/dsv/scipro/notifications/Notifications.java
@@ -24,6 +24,7 @@ import se.su.dsv.scipro.project.ProjectActivatedEvent;
 import se.su.dsv.scipro.project.ProjectCompletedEvent;
 import se.su.dsv.scipro.project.ProjectDeactivatedEvent;
 import se.su.dsv.scipro.project.ReviewerAssignedEvent;
+import se.su.dsv.scipro.report.OppositionReportSubmittedEvent;
 
 @Singleton
 public class Notifications {
@@ -183,6 +184,17 @@ public class Notifications {
         );
     }
 
+    @Subscribe
+    public void oppositionReportSubmitted(OppositionReportSubmittedEvent event) {
+        NotificationSource source = new NotificationSource();
+        source.setMessage(event.report().getAuthorName());
+        notificationController.notifySeminar(
+            event.finalSeminar(),
+            SeminarEvent.Event.OPPOSITION_REPORT_SUBMITTED,
+            source
+        );
+    }
+
     @Subscribe
     public void reviewersChanged(ReviewerAssignedEvent event) {
         notificationController.notifyProject(
diff --git a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/SeminarEvent.java b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/SeminarEvent.java
index e2a6484ed6..5656e9f5c8 100755
--- a/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/SeminarEvent.java
+++ b/core/src/main/java/se/su/dsv/scipro/notifications/dataobject/SeminarEvent.java
@@ -26,6 +26,7 @@ public class SeminarEvent extends NotificationEvent {
         THESIS_DELETED,
         THESIS_UPLOAD_REMIND,
         CANCELLED,
+        OPPOSITION_REPORT_SUBMITTED,
     }
 
     @Basic
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 9019703177..fd1eb01598 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
@@ -144,6 +144,8 @@ FINAL_SEMINAR.THESIS_UPLOAD_REMIND.body = No final seminar thesis has been uploa
   If no final thesis has been uploaded by {0}, the final seminar will be automatically cancelled.
 FINAL_SEMINAR.CANCELLED.title = Final seminar for project {1} was cancelled
 FINAL_SEMINAR.CANCELLED.body = The final seminar for project {0} was cancelled, supervisor must select a new date for the final seminar.
+FINAL_SEMINAR.OPPOSITION_REPORT_SUBMITTED.title=Opposition report submitted by {1} for the seminar on project {0}
+FINAL_SEMINAR.OPPOSITION_REPORT_SUBMITTED.body=The opposition report from {0} has been submitted.
 FINAL_SEMINAR.compilationSuffix = , project: {0}
 
 PEER.REVIEW_COMPLETED.title = Peer review completed
diff --git a/core/src/main/java/se/su/dsv/scipro/report/OppositionReportServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/report/OppositionReportServiceImpl.java
index c4ecfedfcc..65a35aae78 100644
--- a/core/src/main/java/se/su/dsv/scipro/report/OppositionReportServiceImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/report/OppositionReportServiceImpl.java
@@ -1,5 +1,6 @@
 package se.su.dsv.scipro.report;
 
+import com.google.common.eventbus.EventBus;
 import jakarta.inject.Inject;
 import jakarta.inject.Named;
 import jakarta.transaction.Transactional;
@@ -17,18 +18,21 @@ public class OppositionReportServiceImpl implements OppositionReportService {
     private GradingReportTemplateRepo gradingReportTemplateRepo;
     private FileService fileService;
     private FinalSeminarOppositionRepo finalSeminarOppositionRepo;
+    private final EventBus eventBus;
 
     @Inject
     public OppositionReportServiceImpl(
         OppositionReportRepo oppositionReportRepo,
         GradingReportTemplateRepo gradingReportTemplateRepo,
         FileService fileService,
-        FinalSeminarOppositionRepo finalSeminarOppositionRepo
+        FinalSeminarOppositionRepo finalSeminarOppositionRepo,
+        EventBus eventBus
     ) {
         this.oppositionReportRepo = oppositionReportRepo;
         this.gradingReportTemplateRepo = gradingReportTemplateRepo;
         this.fileService = fileService;
         this.finalSeminarOppositionRepo = finalSeminarOppositionRepo;
+        this.eventBus = eventBus;
     }
 
     @Override
@@ -81,7 +85,9 @@ public class OppositionReportServiceImpl implements OppositionReportService {
     @Transactional
     public OppositionReport submit(OppositionReport report) {
         report.submit();
-        return oppositionReportRepo.save(report);
+        OppositionReport submitted = oppositionReportRepo.save(report);
+        eventBus.post(new OppositionReportSubmittedEvent(submitted));
+        return submitted;
     }
 
     @Override
diff --git a/core/src/main/java/se/su/dsv/scipro/report/OppositionReportSubmittedEvent.java b/core/src/main/java/se/su/dsv/scipro/report/OppositionReportSubmittedEvent.java
new file mode 100644
index 0000000000..e479091fd7
--- /dev/null
+++ b/core/src/main/java/se/su/dsv/scipro/report/OppositionReportSubmittedEvent.java
@@ -0,0 +1,9 @@
+package se.su.dsv.scipro.report;
+
+import se.su.dsv.scipro.finalseminar.FinalSeminar;
+
+public record OppositionReportSubmittedEvent(OppositionReport report) {
+    public FinalSeminar finalSeminar() {
+        return report().getFinalSeminarOpposition().getFinalSeminar();
+    }
+}
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 077b636977..f1a83aa464 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
@@ -84,6 +84,7 @@ SeminarEvent.OPPOSITION_REPORT_UPLOADED = Opposition report created.
 SeminarEvent.THESIS_DELETED = Final seminar thesis deleted.
 SeminarEvent.THESIS_UPLOAD_REMIND = Authors reminded to upload final seminar thesis.
 SeminarEvent.CANCELLED = Final seminar cancelled.
+SeminarEvent.OPPOSITION_REPORT_SUBMITTED = Opposition report submitted.
 
 IdeaEvent.STATUS_CHANGE = Idea status changed.
 IdeaEvent.PARTNER_ACCEPT = Partner (author) accepted partnering idea.