87: Add clone functionality

This commit is contained in:
Tom Zhao 2025-04-02 12:44:24 +02:00
parent 1ebf21f14b
commit 8a050491f9
5 changed files with 91 additions and 1 deletions
core/src/main

@ -36,6 +36,9 @@ import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import se.su.dsv.scipro.data.dataobjects.Member;
import se.su.dsv.scipro.reusable.SciProUtilities;
import se.su.dsv.scipro.system.DegreeType;
@ -121,6 +124,11 @@ public class Project extends DomainObject {
@Column(name = "root_project_id")
private Long rootProjectId;
@Basic
@Column(name = "clone_timestamp")
@Temporal(TemporalType.TIMESTAMP)
private Date cloneTimestamp;
// ----------------------------------------------------------------------------------
// Embedded JPA-mapping
// ----------------------------------------------------------------------------------
@ -389,6 +397,14 @@ public class Project extends DomainObject {
this.rootProjectId = rootProjectId;
}
public Date getCloneTimestamp() {
return cloneTimestamp;
}
public void setCloneTimestamp(Date cloneTimestamp) {
this.cloneTimestamp = cloneTimestamp;
}
// ----------------------------------------------------------------------------------
// Methods Common To All Objects
// ----------------------------------------------------------------------------------

@ -196,6 +196,25 @@ public class Decision {
decideWithDecisionDate(status, reason, attachment, Instant.now());
}
Decision cloneToReviewerApproval(RoughDraftApproval roughDraftApproval) {
Decision clonedDecision = new Decision();
clonedDecision.reviewerApproval = roughDraftApproval;
clonedDecision.status = this.status;
clonedDecision.reason = this.reason;
clonedDecision.comment = this.comment;
clonedDecision.requested = this.requested;
clonedDecision.decisionDate = this.decisionDate;
clonedDecision.deadline = this.deadline;
clonedDecision.reviewerAssignedAt = this.reviewerAssignedAt;
clonedDecision.assignedReviewer = this.assignedReviewer;
clonedDecision.attachment = this.attachment;
clonedDecision.thesis = this.thesis;
return clonedDecision;
}
private void decideWithDecisionDate(
final Status status,
final String reason,

@ -1,6 +1,8 @@
package se.su.dsv.scipro.reviewing;
import jakarta.persistence.Basic;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.DiscriminatorColumn;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
@ -16,6 +18,9 @@ import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import jakarta.persistence.Temporal;
import jakarta.persistence.TemporalType;
import se.su.dsv.scipro.file.FileReference;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.system.DomainObject;
@ -32,6 +37,15 @@ public abstract class ReviewerApproval extends DomainObject {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Basic
@Column(name = "is_cloned")
protected Boolean isCloned = false;
@Basic
@Column(name = "clone_timestamp")
@Temporal(TemporalType.TIMESTAMP)
protected Date cloneTimestamp;
// ----------------------------------------------------------------------------------
// JPA-mappings of foreign keys in this table (reviewer_approval) referencing other
// tables.
@ -59,6 +73,22 @@ public abstract class ReviewerApproval extends DomainObject {
return this.project;
}
public Boolean getCloned() {
return isCloned;
}
public void setCloned(Boolean cloned) {
isCloned = cloned;
}
public Date getCloneTimestamp() {
return cloneTimestamp;
}
public void setCloneTimestamp(Date cloneDate) {
this.cloneTimestamp = cloneDate;
}
// ----------------------------------------------------------------------------------
// Other methods
// ----------------------------------------------------------------------------------

@ -1,7 +1,9 @@
package se.su.dsv.scipro.reviewing;
import jakarta.persistence.Entity;
import java.util.*;
import java.time.Instant;
import java.util.Date;
import se.su.dsv.scipro.file.FileReference;
import se.su.dsv.scipro.project.Project;
@ -24,4 +26,15 @@ public class RoughDraftApproval extends ReviewerApproval {
public Step getStep() {
return Step.ROUGH_DRAFT_APPROVAL;
}
public RoughDraftApproval cloneToProject(final Project newProject) {
RoughDraftApproval rda = new RoughDraftApproval();
rda.project = newProject;
this.decisions.forEach(decision -> rda.decisions.add(decision.cloneToReviewerApproval(rda)));
rda.isCloned = true;
rda.cloneTimestamp = Date.from(Instant.now());
return rda;
}
}

@ -5,6 +5,9 @@ alter table `project`
alter table `project`
add column `root_project_id` bigint(20) null default null;
alter table `project`
add column `clone_timestamp` datetime not null default null;
alter table `project`
add constraint fk_project_parent_project_id_project_id
foreign key (parent_project_id) references project(id)
@ -14,3 +17,12 @@ alter table `project`
add constraint fk_project_root_project_id_project_id
foreign key (root_project_id) references project(id)
on delete cascade on update cascade;
alter table `reviewer_approval`
add column `is_cloned` bit(1) not null default false;
alter table `reviewer_approval`
add column `clone_timestamp` datetime not null default null;
update table `reviewer_approval` set is_cloned = false;