2984 PO 4) Save (re-)submissions of authors for examination
This commit is contained in:
parent
c615ffea56
commit
b2c8d94d2f
core/src
main
java/se/su/dsv/scipro
grading
GradingHistory.javaGradingHistoryEventRepository.javaGradingHistoryEventRepositoryImpl.javaGradingModule.javaSubmissionEvent.javaThesisSubmissionHistoryService.java
report
resources/db/migration
test/java/se/su/dsv/scipro/test
@ -4,14 +4,18 @@ import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class GradingHistory implements ExaminerTimelineService, ThesisRejectionHistoryService, ThesisApprovedHistoryService {
|
||||
public class GradingHistory implements
|
||||
ExaminerTimelineService,
|
||||
ThesisRejectionHistoryService,
|
||||
ThesisApprovedHistoryService,
|
||||
ThesisSubmissionHistoryService
|
||||
{
|
||||
private final GradingHistoryEventRepository gradingHistoryEventRepository;
|
||||
|
||||
@Inject
|
||||
@ -21,27 +25,29 @@ public class GradingHistory implements ExaminerTimelineService, ThesisRejectionH
|
||||
|
||||
@Override
|
||||
public List<Event> getTimeline(Project project) {
|
||||
Instant morning = Instant.parse("2023-09-11T08:00:00Z");
|
||||
|
||||
ArrayList<Event> events = new ArrayList<>();
|
||||
|
||||
for (User author : project.getProjectParticipants()) {
|
||||
events.add(new Event.InitialSubmission(morning, author));
|
||||
|
||||
events.add(new Event.Resubmitted(morning.plus(Duration.ofHours(5)), author, "Ok they improved it"));
|
||||
Collection<SubmissionEvent> submissions = gradingHistoryEventRepository.findSubmissions(project);
|
||||
for (SubmissionEvent submission : submissions) {
|
||||
if (submission.getCorrections() == null || submission.getCorrections().isBlank()) {
|
||||
events.add(new Event.InitialSubmission(submission.getWhen(), submission.getAuthor()));
|
||||
} else {
|
||||
events.add(new Event.Resubmitted(
|
||||
submission.getWhen(),
|
||||
submission.getAuthor(),
|
||||
submission.getCorrections()));
|
||||
}
|
||||
}
|
||||
|
||||
Collection<RejectionEvent> rejections = gradingHistoryEventRepository.findRejections(project);
|
||||
rejections.forEach(rejection -> {
|
||||
for (RejectionEvent rejection : rejections) {
|
||||
events.add(new Event.Rejected(rejection.getWhen(), rejection.getReason()));
|
||||
});
|
||||
}
|
||||
|
||||
Collection<ApprovedEvent> approvals = gradingHistoryEventRepository.findApprovals(project);
|
||||
approvals.forEach(approval -> {
|
||||
for (ApprovedEvent approval : approvals) {
|
||||
events.add(new Event.Approved(approval.getWhen()));
|
||||
});
|
||||
|
||||
events.add(new Event.Approved(morning.plus(Duration.ofHours(8))));
|
||||
}
|
||||
|
||||
events.sort(Comparator.comparing(Event::when).reversed());
|
||||
|
||||
@ -64,4 +70,23 @@ public class GradingHistory implements ExaminerTimelineService, ThesisRejectionH
|
||||
approvedEvent.setWhen(when);
|
||||
gradingHistoryEventRepository.save(approvedEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInitialSubmission(Project project, User author, Instant when) {
|
||||
SubmissionEvent submissionEvent = new SubmissionEvent();
|
||||
submissionEvent.setProject(project);
|
||||
submissionEvent.setAuthor(author);
|
||||
submissionEvent.setWhen(when);
|
||||
gradingHistoryEventRepository.save(submissionEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResubmission(Project project, User author, Instant when, String corrections) {
|
||||
SubmissionEvent submissionEvent = new SubmissionEvent();
|
||||
submissionEvent.setProject(project);
|
||||
submissionEvent.setAuthor(author);
|
||||
submissionEvent.setWhen(when);
|
||||
submissionEvent.setCorrections(corrections);
|
||||
gradingHistoryEventRepository.save(submissionEvent);
|
||||
}
|
||||
}
|
||||
|
@ -12,4 +12,8 @@ public interface GradingHistoryEventRepository {
|
||||
void save(ApprovedEvent approvedEvent);
|
||||
|
||||
Collection<ApprovedEvent> findApprovals(Project project);
|
||||
|
||||
void save(SubmissionEvent submissionEvent);
|
||||
|
||||
Collection<SubmissionEvent> findSubmissions(Project project);
|
||||
}
|
||||
|
@ -40,4 +40,17 @@ public class GradingHistoryEventRepositoryImpl extends AbstractRepository implem
|
||||
.where(QApprovedEvent.approvedEvent.project.eq(project))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void save(SubmissionEvent submissionEvent) {
|
||||
em().persist(submissionEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SubmissionEvent> findSubmissions(Project project) {
|
||||
return from(QSubmissionEvent.submissionEvent)
|
||||
.where(QSubmissionEvent.submissionEvent.project.eq(project))
|
||||
.fetch();
|
||||
}
|
||||
}
|
||||
|
@ -23,5 +23,7 @@ public class GradingModule extends PrivateModule {
|
||||
expose(ThesisRejectionHistoryService.class);
|
||||
bind(ThesisApprovedHistoryService.class).to(GradingHistory.class);
|
||||
expose(ThesisApprovedHistoryService.class);
|
||||
bind(ThesisSubmissionHistoryService.class).to(GradingHistory.class);
|
||||
expose(ThesisSubmissionHistoryService.class);
|
||||
}
|
||||
}
|
||||
|
108
core/src/main/java/se/su/dsv/scipro/grading/SubmissionEvent.java
Normal file
108
core/src/main/java/se/su/dsv/scipro/grading/SubmissionEvent.java
Normal file
@ -0,0 +1,108 @@
|
||||
package se.su.dsv.scipro.grading;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.Temporal;
|
||||
import jakarta.persistence.TemporalType;
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "grading_history_submissions")
|
||||
public class SubmissionEvent {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "project_id")
|
||||
private Project project;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "author_id")
|
||||
private User author;
|
||||
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@Column(name = "`when`")
|
||||
private Instant when;
|
||||
|
||||
@Basic
|
||||
private String corrections;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Project getProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
public void setProject(Project project) {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public User getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(User user) {
|
||||
this.author = user;
|
||||
}
|
||||
|
||||
public Instant getWhen() {
|
||||
return when;
|
||||
}
|
||||
|
||||
public void setWhen(Instant when) {
|
||||
this.when = when;
|
||||
}
|
||||
|
||||
public String getCorrections() {
|
||||
return corrections;
|
||||
}
|
||||
|
||||
public void setCorrections(String corrections) {
|
||||
this.corrections = corrections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
return o instanceof SubmissionEvent that
|
||||
&& Objects.equals(id, that.id)
|
||||
&& Objects.equals(project, that.project)
|
||||
&& Objects.equals(author, that.author)
|
||||
&& Objects.equals(when, that.when)
|
||||
&& Objects.equals(corrections, that.corrections);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, project, author, when, corrections);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RejectionEvent{" +
|
||||
"id=" + id +
|
||||
", project=" + project +
|
||||
", author=" + author +
|
||||
", when=" + when +
|
||||
", corrections='" + corrections + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package se.su.dsv.scipro.grading;
|
||||
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public interface ThesisSubmissionHistoryService {
|
||||
void addInitialSubmission(Project project, User author, Instant when);
|
||||
|
||||
void addResubmission(Project project, User author, Instant when, String corrections);
|
||||
}
|
@ -5,6 +5,7 @@ import com.google.inject.persist.Transactional;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition;
|
||||
import se.su.dsv.scipro.grading.GradingBasis;
|
||||
import se.su.dsv.scipro.grading.ThesisSubmissionHistoryService;
|
||||
import se.su.dsv.scipro.project.Project;
|
||||
import se.su.dsv.scipro.system.AbstractServiceImpl;
|
||||
import se.su.dsv.scipro.system.User;
|
||||
@ -13,6 +14,7 @@ import se.su.dsv.scipro.util.Either;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import java.time.Clock;
|
||||
import java.util.*;
|
||||
|
||||
@Named
|
||||
@ -21,11 +23,20 @@ public class GradingReportServiceImpl extends AbstractServiceImpl<GradingReport,
|
||||
public static final String OPPOSITION_SWEDISH = "Ö1 Oppositionsrapport";
|
||||
public static final String OPPOSITION_ENGLISH = "Ö1 Opposition report";
|
||||
private final EventBus eventBus;
|
||||
private final ThesisSubmissionHistoryService thesisSubmissionHistoryService;
|
||||
private final Clock clock;
|
||||
|
||||
@Inject
|
||||
public GradingReportServiceImpl(Provider<EntityManager> em, EventBus eventBus) {
|
||||
public GradingReportServiceImpl(
|
||||
Provider<EntityManager> em,
|
||||
EventBus eventBus,
|
||||
ThesisSubmissionHistoryService thesisSubmissionHistoryService,
|
||||
Clock clock)
|
||||
{
|
||||
super(em, GradingReport.class, QGradingReport.gradingReport);
|
||||
this.eventBus = eventBus;
|
||||
this.thesisSubmissionHistoryService = thesisSubmissionHistoryService;
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -133,6 +144,7 @@ public class GradingReportServiceImpl extends AbstractServiceImpl<GradingReport,
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public Either<List<SubmissionError>, SupervisorGradingReport> submitReport(SupervisorGradingReport supervisorGradingReport) {
|
||||
final ArrayList<SubmissionError> errors = new ArrayList<>();
|
||||
for (GradingCriterion gradingCriterion : supervisorGradingReport.getGradingCriteria()) {
|
||||
@ -141,7 +153,8 @@ public class GradingReportServiceImpl extends AbstractServiceImpl<GradingReport,
|
||||
}
|
||||
}
|
||||
|
||||
if (!isBlank(supervisorGradingReport.getRejectionComment()) && isBlank(supervisorGradingReport.getRejectionCommentFeedback())) {
|
||||
String rejectionCommentFeedback = supervisorGradingReport.getRejectionCommentFeedback();
|
||||
if (!isBlank(supervisorGradingReport.getRejectionComment()) && isBlank(rejectionCommentFeedback)) {
|
||||
errors.add(new SubmissionError.NoRejectionCommentFeedback());
|
||||
}
|
||||
|
||||
@ -152,6 +165,19 @@ public class GradingReportServiceImpl extends AbstractServiceImpl<GradingReport,
|
||||
supervisorGradingReport.submit();
|
||||
|
||||
eventBus.post(new SupervisorGradingReportSubmittedEvent(supervisorGradingReport));
|
||||
if (isBlank(rejectionCommentFeedback)) {
|
||||
thesisSubmissionHistoryService.addInitialSubmission(
|
||||
supervisorGradingReport.getProject(),
|
||||
supervisorGradingReport.getUser(),
|
||||
clock.instant());
|
||||
}
|
||||
else {
|
||||
thesisSubmissionHistoryService.addResubmission(
|
||||
supervisorGradingReport.getProject(),
|
||||
supervisorGradingReport.getUser(),
|
||||
clock.instant(),
|
||||
rejectionCommentFeedback);
|
||||
}
|
||||
|
||||
save(supervisorGradingReport);
|
||||
return Either.right(supervisorGradingReport);
|
||||
|
@ -0,0 +1,11 @@
|
||||
CREATE TABLE IF NOT EXISTS `grading_history_submissions`
|
||||
(
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
||||
`project_id` BIGINT NOT NULL,
|
||||
`when` TIMESTAMP NOT NULL DEFAULT 0, -- disable automatic CURRENT_TIMESTAMP behaviour
|
||||
`author_id` BIGINT NOT NULL,
|
||||
`corrections` TEXT NULL,
|
||||
PRIMARY KEY (id),
|
||||
CONSTRAINT `FK_grading_history_submissions_project` FOREIGN KEY (`project_id`) REFERENCES `project` (`id`),
|
||||
CONSTRAINT `FK_grading_history_submissions_author` FOREIGN KEY (`author_id`) REFERENCES `user` (`id`)
|
||||
) collate utf8mb4_swedish_ci;
|
@ -6,6 +6,11 @@ import com.google.inject.name.Names;
|
||||
import modules.CoreModule;
|
||||
import se.su.dsv.scipro.file.FileModule;
|
||||
import se.su.dsv.scipro.file.FileStore;
|
||||
import se.su.dsv.scipro.grading.GradingHistory;
|
||||
import se.su.dsv.scipro.grading.GradingHistoryEventRepository;
|
||||
import se.su.dsv.scipro.grading.GradingHistoryEventRepositoryImpl;
|
||||
import se.su.dsv.scipro.grading.GradingModule;
|
||||
import se.su.dsv.scipro.grading.ThesisSubmissionHistoryService;
|
||||
import se.su.dsv.scipro.plagiarism.urkund.UrkundModule;
|
||||
import se.su.dsv.scipro.reviewing.ReviewingModule;
|
||||
import se.su.dsv.scipro.sukat.SukatModule;
|
||||
@ -27,6 +32,8 @@ public abstract class IntegrationTest extends GuiceTest {
|
||||
install(new ReviewingModule());
|
||||
install(new SukatModule());
|
||||
install(new UrkundModule());
|
||||
bind(ThesisSubmissionHistoryService.class).to(GradingHistory.class);
|
||||
bind(GradingHistoryEventRepository.class).to(GradingHistoryEventRepositoryImpl.class);
|
||||
bind(CurrentUser.class).to(TestUser.class);
|
||||
bind(FileStore.class).to(InMemoryFileStore.class);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user