task/3382: Fixed decision and reviewer_approval and their related JPA-mappings

This commit is contained in:
Tom Zhao 2024-10-28 14:30:50 +01:00
parent a76eb0c03c
commit de27d3d212
3 changed files with 174 additions and 63 deletions
core/src/main
java/se/su/dsv/scipro/reviewing
resources/db/migration

@ -20,51 +20,73 @@ import se.su.dsv.scipro.system.User;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.*; import java.util.Date;
import java.util.Optional;
@Entity @Entity
@Table(name = "Decision") @Table(name = "decision")
public class Decision { public class Decision {
// ----------------------------------------------------------------------------------
// Basic JPA-mappings
// ----------------------------------------------------------------------------------
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@Basic
@Column(name = "status")
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private Status status = Status.UNDECIDED; private Status status = Status.UNDECIDED;
@OneToOne(optional = false)
@JoinColumn(name = "thesis_reference_id")
private FileReference thesis;
@Basic @Basic
@Column(name = "reason")
private String reason; private String reason;
@Basic @Basic
@Column(name = "comment")
private String comment; private String comment;
@OneToOne(optional = true) @Basic
@JoinColumn(name = "attachment_reference_id") @Column(name = "requested_date")
private FileReference attachment;
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
private Date requested; private Date requested;
@Temporal(TemporalType.TIMESTAMP) @Basic
private Date deadline; @Column(name = "decision_date")
@Temporal(TemporalType.TIMESTAMP) @Temporal(TemporalType.TIMESTAMP)
private Date decisionDate; private Date decisionDate;
@ManyToOne(optional = false) @Basic
private ReviewerApproval reviewerApproval; @Column(name = "deadline")
@Temporal(TemporalType.TIMESTAMP)
@ManyToOne private Date deadline;
@JoinColumn(name = "assigned_reviewer_id")
private User assignedReviewer;
@Basic
@Column(name = "assigned_reviewer_date") @Column(name = "assigned_reviewer_date")
private LocalDate reviewerAssignedAt; private LocalDate reviewerAssignedAt;
// ----------------------------------------------------------------------------------
// JPA-mappings of foreign keys in this table (decision) referencing other tables.
// ----------------------------------------------------------------------------------
@ManyToOne
@JoinColumn(name = "assigned_reviewer_id", referencedColumnName = "id")
private User assignedReviewer;
@OneToOne(optional = true)
@JoinColumn(name = "attachment_reference_id", referencedColumnName = "id")
private FileReference attachment;
@ManyToOne(optional = false)
@JoinColumn(name = "reviewer_approval_id", referencedColumnName = "id")
private ReviewerApproval reviewerApproval;
@OneToOne(optional = false)
@JoinColumn(name = "thesis_reference_id", referencedColumnName = "id")
private FileReference thesis;
// ----------------------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------------------
protected Decision() {} // JPA protected Decision() {} // JPA
Decision(ReviewerApproval reviewerApproval, final FileReference thesis, final String comment, final Date deadline) { Decision(ReviewerApproval reviewerApproval, final FileReference thesis, final String comment, final Date deadline) {
@ -79,6 +101,9 @@ public class Decision {
this.comment = comment; this.comment = comment;
} }
// ----------------------------------------------------------------------------------
// Properties (Getters and Setters)
// ----------------------------------------------------------------------------------
public Long getId() { public Long getId() {
return id; return id;
} }
@ -87,14 +112,6 @@ public class Decision {
this.id = id; this.id = id;
} }
public FileReference getThesis() {
return thesis;
}
public ReviewerApproval getReviewerApproval() {
return reviewerApproval;
}
public Status getStatus() { public Status getStatus() {
return status; return status;
} }
@ -107,10 +124,6 @@ public class Decision {
return comment; return comment;
} }
public Optional<FileReference> getAttachment() {
return Optional.ofNullable(attachment);
}
public Date getRequested() { public Date getRequested() {
return requested; return requested;
} }
@ -127,14 +140,6 @@ public class Decision {
this.deadline = deadline; this.deadline = deadline;
} }
public User getAssignedReviewer() {
return assignedReviewer;
}
public void setAssignedReviewer(User assignedReviewer) {
this.assignedReviewer = assignedReviewer;
}
public LocalDate getReviewerAssignedAt() { public LocalDate getReviewerAssignedAt() {
return reviewerAssignedAt; return reviewerAssignedAt;
} }
@ -143,6 +148,29 @@ public class Decision {
this.reviewerAssignedAt = reviewerAssignedAt; this.reviewerAssignedAt = reviewerAssignedAt;
} }
public User getAssignedReviewer() {
return assignedReviewer;
}
public void setAssignedReviewer(User assignedReviewer) {
this.assignedReviewer = assignedReviewer;
}
public Optional<FileReference> getAttachment() {
return Optional.ofNullable(attachment);
}
public ReviewerApproval getReviewerApproval() {
return reviewerApproval;
}
public FileReference getThesis() {
return thesis;
}
// ----------------------------------------------------------------------------------
// Other methods
// ----------------------------------------------------------------------------------
void approve(final String reason, final Optional<FileReference> attachment) { void approve(final String reason, final Optional<FileReference> attachment) {
decide(Status.APPROVED, reason, attachment); decide(Status.APPROVED, reason, attachment);
} }

@ -1,6 +1,8 @@
package se.su.dsv.scipro.reviewing; package se.su.dsv.scipro.reviewing;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.Table;
import se.su.dsv.scipro.file.FileReference; import se.su.dsv.scipro.file.FileReference;
import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.system.DomainObject; import se.su.dsv.scipro.system.DomainObject;
@ -13,31 +15,61 @@ import jakarta.persistence.Id;
import jakarta.persistence.OneToMany; import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne; import jakarta.persistence.OneToOne;
import jakarta.persistence.OrderBy; import jakarta.persistence.OrderBy;
import java.util.*;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
@Entity @Entity
@Table(name = "reviewer_approval")
@DiscriminatorColumn(name = "type", length = 64) @DiscriminatorColumn(name = "type", length = 64)
public abstract class ReviewerApproval extends DomainObject { public abstract class ReviewerApproval extends DomainObject {
@OneToOne(optional = false) // ----------------------------------------------------------------------------------
protected Project project; // Basic JPA-mappings
// ----------------------------------------------------------------------------------
@OneToMany(mappedBy = "reviewerApproval", cascade = CascadeType.ALL)
@OrderBy("requested desc")
protected List<Decision> decisions = new LinkedList<>();
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
public abstract Step getStep(); // ----------------------------------------------------------------------------------
// JPA-mappings of foreign keys in this table (reviewer_approval) referencing other
// tables.
// ----------------------------------------------------------------------------------
@OneToOne(optional = false)
@JoinColumn(name = "project_id", referencedColumnName = "id")
protected Project project;
public FileReference getCurrentThesis() { // ----------------------------------------------------------------------------------
return getCurrentDecision().getThesis(); // JPA-mappings of other tables referencing to this table "reviewer_approval"
// ----------------------------------------------------------------------------------
@OneToMany(mappedBy = "reviewerApproval", cascade = CascadeType.ALL)
@OrderBy("requested desc")
protected List<Decision> decisions = new LinkedList<>();
// ----------------------------------------------------------------------------------
// Properties (Getters and Setters)
// ----------------------------------------------------------------------------------
@Override
public Long getId() {
return this.id;
} }
public Project getProject(){return this.project;} public Project getProject(){return this.project;}
// ----------------------------------------------------------------------------------
// Other methods
// ----------------------------------------------------------------------------------
public abstract Step getStep();
public Decision getCurrentDecision() {
return decisions.get(0);
}
public FileReference getCurrentThesis() {
return getCurrentDecision().getThesis();
}
public Status getCurrentStatus() { public Status getCurrentStatus() {
return getCurrentDecision().getStatus(); return getCurrentDecision().getStatus();
@ -63,10 +95,6 @@ public abstract class ReviewerApproval extends DomainObject {
getCurrentDecision().reject(reason, attachment); getCurrentDecision().reject(reason, attachment);
} }
public Decision getCurrentDecision() {
return decisions.get(0);
}
public void addNewThesis(final FileReference thesis, final String comment, final Date deadline) { public void addNewThesis(final FileReference thesis, final String comment, final Date deadline) {
if (getCurrentStatus() != Status.REJECTED) { if (getCurrentStatus() != Status.REJECTED) {
throw new IllegalStateException(); throw new IllegalStateException();
@ -86,17 +114,15 @@ public abstract class ReviewerApproval extends DomainObject {
return getCurrentStatus() == Status.APPROVED; return getCurrentStatus() == Status.APPROVED;
} }
@Override public Date getCurrentDeadline() {
public Long getId() { return getCurrentDecision().getDeadline();
return this.id;
} }
// ----------------------------------------------------------------------------------
// Nested types.
// ----------------------------------------------------------------------------------
public enum Step { public enum Step {
ROUGH_DRAFT_APPROVAL, ROUGH_DRAFT_APPROVAL,
FINAL_SEMINAR_APPROVAL FINAL_SEMINAR_APPROVAL
} }
public Date getCurrentDeadline() {
return getCurrentDecision().getDeadline();
}
} }

@ -2709,9 +2709,66 @@ alter table `project_file`
* Step 18: Decision & ReviewerApproval * Step 18: Decision & ReviewerApproval
*/ */
-- todo: table: Decision -- table: Decision
-- todo: table: ReviewerApproval alter table `Decision` drop foreign key `fk_Decision_ReviewerApproval`;
alter table `Decision` drop foreign key `FK_decision_reviewer`;
alter table `Decision` drop foreign key `FK_Decision_thesis`;
alter table `Decision` drop foreign key `FK_Decision_attachment`;
alter table `Decision` drop key `FK_decision_reviewer`;
alter table `Decision` drop key `FK_Decision_attachment`;
alter table `Decision` drop key `FK_Decision_thesis`;
alter table `Decision` drop key `fk_ReviewerApproval_Decision_idx`;
rename table `Decision` to `decision`;
alter table `decision` change `status` `status` varchar(255) default null after `id`;
alter table `decision` change `requested` `requested_date` datetime not null;
alter table `decision` change `decisionDate` `decision_date` datetime default null;
alter table `decision` change `deadline` `deadline` datetime default null after `decision_date`;
alter table `decision` change `assigned_reviewer_date` `assigned_reviewer_date` date default null after `deadline`;
alter table `decision` change `assigned_reviewer_id` `assigned_reviewer_id` bigint(20) default null after `assigned_reviewer_date`;
alter table `decision` change `attachment_reference_id` `attachment_reference_id` bigint(20) default null after `assigned_reviewer_id`;
alter table `decision` change `reviewerApproval_id` `reviewer_approval_id` bigint(20) not null;
alter table `decision`
add constraint fk_decision_assigned_reviewer_id
foreign key (assigned_reviewer_id) references user (id)
on delete cascade on update cascade;
alter table `decision`
add constraint fk_decision_attachment_reference_id
foreign key (attachment_reference_id) references file_reference (id)
on delete cascade on update cascade;
alter table `decision`
add constraint fk_decision_thesis_reference_id
foreign key (thesis_reference_id) references file_reference (id)
on delete cascade on update cascade;
-- table: ReviewerApproval
alter table `ReviewerApproval` drop foreign key `FK_9lr1dn8boyfc5a0477ld4q8rw`;
alter table `ReviewerApproval` drop key `FK_9lr1dn8boyfc5a0477ld4q8rw`;
rename table `ReviewerApproval` to `reviewer_approval`;
alter table `reviewer_approval` change `type` `type` varchar(64) not null after `version`;
alter table `reviewer_approval` change `project_id` `project_id` bigint(20) not null after `type`;
alter table `reviewer_approval`
add constraint fk_reviewer_approval_project_id
foreign key (project_id) references project (id)
on delete cascade on update cascade;
-- add foreign key from decision to reviewer_approval
alter table `decision`
add constraint fk_decision_reviewer_approval_id
foreign key (reviewer_approval_id) references reviewer_approval (id)
on delete cascade on update cascade;
/* Useful SQL /* Useful SQL