From e59178a54049b6cfc4927bdea00140f634c45ae0 Mon Sep 17 00:00:00 2001
From: Tom Zhao <tom.zhao@dsv.su.se>
Date: Wed, 26 Mar 2025 09:10:31 +0100
Subject: [PATCH] 87: Add initial version of SplitOrRestartProjectService

---
 .../java/se/su/dsv/scipro/CoreConfig.java     |  9 ++
 .../split/SplitOrRestartProjectService.java   | 29 +++++++
 .../SplitOrRestartProjectServiceImpl.java     | 86 +++++++++++++++++++
 3 files changed, 124 insertions(+)
 create mode 100644 core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectService.java
 create mode 100644 core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectServiceImpl.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 352c43456a..30bd0bd214 100644
--- a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
+++ b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java
@@ -145,6 +145,7 @@ import se.su.dsv.scipro.project.ProjectPeopleStatisticsServiceImpl;
 import se.su.dsv.scipro.project.ProjectRepo;
 import se.su.dsv.scipro.project.ProjectService;
 import se.su.dsv.scipro.project.ProjectServiceImpl;
+import se.su.dsv.scipro.project.split.SplitOrRestartProjectServiceImpl;
 import se.su.dsv.scipro.projectpartner.ProjectPartnerServiceImpl;
 import se.su.dsv.scipro.reflection.ReflectionService;
 import se.su.dsv.scipro.reflection.ReflectionServiceImpl;
@@ -812,6 +813,14 @@ public class CoreConfig {
         return new ProjectServiceImpl(projectRepo, clock, eventBus, em);
     }
 
+    @Bean
+    public SplitOrRestartProjectServiceImpl SplitOrRestartProjectService(
+            ProjectService projectService,
+            FinalSeminarService finalSeminarService
+    ) {
+        return new SplitOrRestartProjectServiceImpl(projectService, finalSeminarService);
+    }
+
     @Bean
     public ProjectTypeServiceImpl projectTypeService(Provider<EntityManager> em) {
         return new ProjectTypeServiceImpl(em);
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
new file mode 100644
index 0000000000..42c0a74b65
--- /dev/null
+++ b/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectService.java
@@ -0,0 +1,29 @@
+package se.su.dsv.scipro.project.split;
+
+import se.su.dsv.scipro.project.Project;
+import se.su.dsv.scipro.util.Pair;
+
+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."),
+        FINAL_SEMINAR_PHASE_STARTED("Final seminar phase has been started, too late to split."),
+        OK("Ok to split.");
+
+        private final String message;
+
+        SplittableStatus(String message) {
+            this.message = message;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+    }
+
+    Pair<SplittableStatus, Project> getSplittableStatus(int projectId);
+
+    void splitProject(int 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
new file mode 100644
index 0000000000..f750faa778
--- /dev/null
+++ b/core/src/main/java/se/su/dsv/scipro/project/split/SplitOrRestartProjectServiceImpl.java
@@ -0,0 +1,86 @@
+package se.su.dsv.scipro.project.split;
+
+import jakarta.inject.Inject;
+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.system.User;
+import se.su.dsv.scipro.util.Pair;
+
+import java.util.List;
+
+public class SplitOrRestartProjectServiceImpl implements SplitOrRestartProjectService {
+
+    private final ProjectService projectService;
+    private final FinalSeminarService finalSeminarService;
+
+    @Inject
+    public SplitOrRestartProjectServiceImpl(ProjectService projectService, FinalSeminarService finalSeminarService) {
+        this.projectService = projectService;
+        this.finalSeminarService = finalSeminarService;
+    }
+
+    @Override
+    public Pair<SplittableStatus, Project> getSplittableStatus(int projectId) {
+        Project project = projectService.findOne(Long.valueOf(projectId));
+        if (project == null)
+            return new Pair<>(SplittableStatus.NOT_EXIST, null);
+
+        if (project.getProjectStatus() != ProjectStatus.ACTIVE) {
+            return new Pair<>(SplittableStatus.NOT_ACTIVE, project);
+        }
+
+        if (project.getProjectParticipants().size() != 2) {
+            return new Pair<>(SplittableStatus.NOT_TWO_PARTICIPANTS, project);
+        }
+
+        if (finalSeminarService.findByProject(project) != null) {
+            return new Pair<>(SplittableStatus.FINAL_SEMINAR_PHASE_STARTED, project);
+        } else {
+            return new Pair<>(SplittableStatus.OK, project);
+        }
+    }
+
+    @Override
+    public void splitProject(int projectId) {
+        Pair<SplittableStatus, Project> result = getSplittableStatus(projectId);
+        if (result.getHead() != 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();
+
+        for (User author : project.getProjectParticipants()) {
+            Project childProject = new Project();
+            childProject.setTitle(project.getTitle());
+            childProject.setProjectType(project.getProjectType());
+
+            childProject.setStartDate(project.getStartDate());
+            childProject.setExpectedEndDate(project.getExpectedEndDate());
+
+            // Copy supervisor
+            childProject.setProjectParticipants(List.of(author));
+            // Copy reviewer
+            // Copy cosupervisor
+            // Copy research area
+
+            childProject.setProjectStatus(ProjectStatus.ACTIVE);
+
+            // childProject.setParentProjectId
+            // childProject.setRootProjectId
+
+            childProject = projectService.save(childProject);
+
+            // Send event to eventBus to synchronize eventual Phase Two Approval
+        }
+
+        // Parent project will set as inactive
+        project.setProjectStatus(ProjectStatus.INACTIVE);
+        projectService.save(project);
+
+
+        System.out.println("Hello, split project -> " + projectId);
+    }
+}