From 1ebf21f14bf03ac466b490437d6e2b35611dcc1a Mon Sep 17 00:00:00 2001
From: Tom Zhao <tom.zhao@dsv.su.se>
Date: Wed, 2 Apr 2025 09:41:27 +0200
Subject: [PATCH] 87: Refactor SplittableStatusRecord using Java record

---
 .../java/se/su/dsv/scipro/CoreConfig.java     |  5 ++-
 .../split/SplitOrRestartProjectService.java   | 11 ++++-
 .../SplitOrRestartProjectServiceImpl.java     | 41 +++++++++++++------
 .../admin/pages/AdminSplitProjectPanel.java   |  6 +--
 .../admin/pages/AdminEditProjectPageTest.java |  8 +++-
 5 files changed, 51 insertions(+), 20 deletions(-)

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 6de4da3244..b0f924f458 100644
--- a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
+++ b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
@@ -816,9 +816,10 @@ public class CoreConfig {
     @Bean
     public SplitOrRestartProjectServiceImpl SplitOrRestartProjectService(
         ProjectService projectService,
-        FinalSeminarService finalSeminarService
+        FinalSeminarService finalSeminarService,
+        RoughDraftApprovalService roughDraftApprovalService
     ) {
-        return new SplitOrRestartProjectServiceImpl(projectService, finalSeminarService);
+        return new SplitOrRestartProjectServiceImpl(projectService, finalSeminarService, roughDraftApprovalService);
     }
 
     @Bean
diff --git a/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectService.java b/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectService.java
index d11626a0a0..0ae111bc44 100644
--- a/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectService.java
+++ b/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectService.java
@@ -2,13 +2,14 @@ package se.su.dsv.scipro.project.split;
 
 import java.util.List;
 import se.su.dsv.scipro.project.Project;
-import se.su.dsv.scipro.util.Pair;
+import se.su.dsv.scipro.reviewing.RoughDraftApproval;
 
 public interface SplitOrRestartProjectService {
     enum SplittableStatus {
         NOT_EXIST("Project does not exist."),
         NOT_ACTIVE("Only active project can be split."),
         NOT_TWO_PARTICIPANTS("To be able to split a project, it needs to have 2 participants."),
+        PHASE_TWO_STARTED("Phase 2 (Review) is already started, can't split right now."),
         FINAL_SEMINAR_PHASE_STARTED("Final seminar phase has been started, too late to split."),
         OK("Ok to split.");
 
@@ -23,7 +24,13 @@ public interface SplitOrRestartProjectService {
         }
     }
 
-    Pair<SplittableStatus, Project> getSplittableStatus(long projectId);
+    record SplittableStatusRecord(
+        SplittableStatus splittableStatus,
+        Project project,
+        RoughDraftApproval roughDraftApproval
+    ) {}
+
+    SplittableStatusRecord getSplittableStatus(long projectId);
 
     void splitProject(long projectId);
 
diff --git a/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectServiceImpl.java
index 0b5bc53f82..5f52b113c3 100644
--- a/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectServiceImpl.java
+++ b/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectServiceImpl.java
@@ -4,11 +4,14 @@ import com.querydsl.core.types.dsl.BooleanExpression;
 import jakarta.inject.Inject;
 import jakarta.transaction.Transactional;
 import java.util.List;
+import java.util.Optional;
 import se.su.dsv.scipro.finalseminar.FinalSeminarService;
 import se.su.dsv.scipro.project.Project;
 import se.su.dsv.scipro.project.ProjectService;
 import se.su.dsv.scipro.project.ProjectStatus;
 import se.su.dsv.scipro.project.QProject;
+import se.su.dsv.scipro.reviewing.RoughDraftApproval;
+import se.su.dsv.scipro.reviewing.RoughDraftApprovalService;
 import se.su.dsv.scipro.system.User;
 import se.su.dsv.scipro.util.Pair;
 
@@ -16,47 +19,60 @@ public class SplitOrRestartProjectServiceImpl implements SplitOrRestartProjectSe
 
     private final ProjectService projectService;
     private final FinalSeminarService finalSeminarService;
+    private final RoughDraftApprovalService roughDraftApprovalService;
 
     @Inject
-    public SplitOrRestartProjectServiceImpl(ProjectService projectService, FinalSeminarService finalSeminarService) {
+    public SplitOrRestartProjectServiceImpl(
+        ProjectService projectService,
+        FinalSeminarService finalSeminarService,
+        RoughDraftApprovalService roughDraftApprovalService
+    ) {
         this.projectService = projectService;
         this.finalSeminarService = finalSeminarService;
+        this.roughDraftApprovalService = roughDraftApprovalService;
     }
 
     @Override
     @Transactional
-    public Pair<SplittableStatus, Project> getSplittableStatus(long projectId) {
+    public SplittableStatusRecord getSplittableStatus(long projectId) {
         Project project = projectService.findOne(projectId);
-        if (project == null) return new Pair<>(SplittableStatus.NOT_EXIST, null);
+        if (project == null) return new SplittableStatusRecord(SplittableStatus.NOT_EXIST, null, null);
 
         if (project.getProjectStatus() != ProjectStatus.ACTIVE) {
-            return new Pair<>(SplittableStatus.NOT_ACTIVE, project);
+            return new SplittableStatusRecord(SplittableStatus.NOT_ACTIVE, project, null);
         }
 
         if (project.getProjectParticipants().size() != 2) {
-            return new Pair<>(SplittableStatus.NOT_TWO_PARTICIPANTS, project);
+            return new SplittableStatusRecord(SplittableStatus.NOT_TWO_PARTICIPANTS, project, null);
         }
 
         if (finalSeminarService.findByProject(project) != null) {
-            return new Pair<>(SplittableStatus.FINAL_SEMINAR_PHASE_STARTED, project);
+            return new SplittableStatusRecord(SplittableStatus.FINAL_SEMINAR_PHASE_STARTED, project, null);
+        }
+
+        Optional<RoughDraftApproval> o = roughDraftApprovalService.findBy(project);
+        if (o.isPresent() && !o.get().isDecided()) {
+            return new SplittableStatusRecord(SplittableStatus.PHASE_TWO_STARTED, project, null);
+        }
+
+        if (o.isPresent() && o.get().isApproved()) {
+            return new SplittableStatusRecord(SplittableStatus.OK, project, o.get());
         } else {
-            return new Pair<>(SplittableStatus.OK, project);
+            return new SplittableStatusRecord(SplittableStatus.OK, project, null);
         }
     }
 
     @Override
     @Transactional
     public void splitProject(long projectId) {
-        Pair<SplittableStatus, Project> result = getSplittableStatus(projectId);
-        if (result.getHead() != SplittableStatus.OK) {
+        SplittableStatusRecord result = getSplittableStatus(projectId);
+        if (result.splittableStatus() != SplittableStatus.OK) {
             throw new IllegalStateException(
                 "Project must to be verified to be able to split " + "before this method can be called."
             );
         }
 
-        Project project = result.getTail();
-
-        // Todo: Get ev. Phase Two Approval
+        Project project = result.project();
 
         for (User author : project.getProjectParticipants()) {
             Project childProject = new Project();
@@ -81,6 +97,7 @@ public class SplitOrRestartProjectServiceImpl implements SplitOrRestartProjectSe
             );
 
             // Todo: add RoughDraftApproval if it's 'APPROVED'
+            if (result.roughDraftApproval() != null) {}
 
             childProject = projectService.save(childProject);
             // Todo: Send event to eventBus to synchronize eventual Phase Two Approval with MileStone
diff --git a/view/src/main/java/se/su/dsv/scipro/admin/pages/AdminSplitProjectPanel.java b/view/src/main/java/se/su/dsv/scipro/admin/pages/AdminSplitProjectPanel.java
index 2585786797..9d4a095e41 100644
--- a/view/src/main/java/se/su/dsv/scipro/admin/pages/AdminSplitProjectPanel.java
+++ b/view/src/main/java/se/su/dsv/scipro/admin/pages/AdminSplitProjectPanel.java
@@ -17,7 +17,6 @@ import se.su.dsv.scipro.project.split.SplitOrRestartProjectService;
 import se.su.dsv.scipro.security.auth.roles.Roles;
 import se.su.dsv.scipro.session.SciProSession;
 import se.su.dsv.scipro.util.PageParameterKeys;
-import se.su.dsv.scipro.util.Pair;
 
 public class AdminSplitProjectPanel extends Panel {
 
@@ -29,8 +28,9 @@ public class AdminSplitProjectPanel extends Panel {
         Project project = projectModel.getObject();
 
         LoadableDetachableModel<SplittableStatus> ldModel = LoadableDetachableModel.of(() -> {
-            Pair<SplittableStatus, Project> pair = splitOrRestartProjectService.getSplittableStatus(project.getId());
-            return pair.getHead();
+            SplitOrRestartProjectService.SplittableStatusRecord status =
+                splitOrRestartProjectService.getSplittableStatus(project.getId());
+            return status.splittableStatus();
         });
 
         final PageParameters pp = new PageParameters();
diff --git a/view/src/test/java/se/su/dsv/scipro/admin/pages/AdminEditProjectPageTest.java b/view/src/test/java/se/su/dsv/scipro/admin/pages/AdminEditProjectPageTest.java
index 65ceb1bb27..f9fb3c2bc8 100644
--- a/view/src/test/java/se/su/dsv/scipro/admin/pages/AdminEditProjectPageTest.java
+++ b/view/src/test/java/se/su/dsv/scipro/admin/pages/AdminEditProjectPageTest.java
@@ -273,7 +273,13 @@ public class AdminEditProjectPageTest extends SciProTest {
         if (project.getId() != null) when(projectService.findOne(project.getId())).thenReturn(project);
         lenient()
             .when(splitOrRestartProjectService.getSplittableStatus(project.getId() != null ? project.getId() : 0L))
-            .thenReturn(new Pair<>(SplitOrRestartProjectService.SplittableStatus.OK, project));
+            .thenReturn(
+                new SplitOrRestartProjectService.SplittableStatusRecord(
+                    SplitOrRestartProjectService.SplittableStatus.OK,
+                    project,
+                    null
+                )
+            );
 
         PageParameters pp = new PageParameters();
         pp.set(PageParameterKeys.MAP.get(Project.class), project.getId());