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 6ecd8b4d2c..d94c934073 100644 --- a/core/src/main/java/se/su/dsv/scipro/CoreConfig.java +++ b/core/src/main/java/se/su/dsv/scipro/CoreConfig.java @@ -436,14 +436,18 @@ public class CoreConfig { FinalSeminarOppositionGrading finalSeminarOppositionGrading, EventBus eventBus, FinalSeminarOppositionRepo finalSeminarOppositionRepository, - Clock clock + Clock clock, + FinalSeminarSettingsService finalSeminarSettingsService, + DaysService daysService ) { return new FinalSeminarOppositionServiceImpl( em, finalSeminarOppositionGrading, eventBus, finalSeminarOppositionRepository, - clock + clock, + finalSeminarSettingsService, + daysService ); } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionService.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionService.java index fbd5003f7b..e3b82f0682 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionService.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionService.java @@ -1,5 +1,6 @@ package se.su.dsv.scipro.finalseminar; +import java.time.Instant; import se.su.dsv.scipro.system.GenericService; public interface FinalSeminarOppositionService extends GenericService<FinalSeminarOpposition, Long> { @@ -11,5 +12,8 @@ public interface FinalSeminarOppositionService extends GenericService<FinalSemin FinalSeminarOpposition gradeOpponent(FinalSeminarOpposition opposition, int points, String feedback) throws PointNotValidException; - void requestImprovements(FinalSeminarOpposition opposition, String supervisorComment); + /** + * @return the deadline by which the improvements must have been submitted + */ + Instant requestImprovements(FinalSeminarOpposition opposition, String supervisorComment); } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionServiceImpl.java index af4ae66be4..f175df78a9 100755 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarOppositionServiceImpl.java @@ -6,7 +6,9 @@ import jakarta.inject.Provider; import jakarta.persistence.EntityManager; import jakarta.transaction.Transactional; import java.time.Clock; +import java.time.Instant; import java.util.List; +import se.su.dsv.scipro.misc.DaysService; import se.su.dsv.scipro.report.OppositionReport; import se.su.dsv.scipro.system.AbstractServiceImpl; @@ -18,6 +20,8 @@ public class FinalSeminarOppositionServiceImpl private final EventBus eventBus; private final FinalSeminarOppositionRepo finalSeminarOppositionRepository; private final Clock clock; + private final FinalSeminarSettingsService finalSeminarSettingsService; + private final DaysService daysService; @Inject public FinalSeminarOppositionServiceImpl( @@ -25,13 +29,17 @@ public class FinalSeminarOppositionServiceImpl FinalSeminarOppositionGrading finalSeminarOppositionGrading, EventBus eventBus, FinalSeminarOppositionRepo finalSeminarOppositionRepository, - Clock clock + Clock clock, + FinalSeminarSettingsService finalSeminarSettingsService, + DaysService daysService ) { super(em, FinalSeminarOpposition.class, QFinalSeminarOpposition.finalSeminarOpposition); this.finalSeminarOppositionGrading = finalSeminarOppositionGrading; this.eventBus = eventBus; this.finalSeminarOppositionRepository = finalSeminarOppositionRepository; this.clock = clock; + this.finalSeminarSettingsService = finalSeminarSettingsService; + this.daysService = daysService; } @Override @@ -67,13 +75,24 @@ public class FinalSeminarOppositionServiceImpl @Override @Transactional - public void requestImprovements(FinalSeminarOpposition opposition, String supervisorComment) { + public Instant requestImprovements(FinalSeminarOpposition opposition, String supervisorComment) { OppositionReport oppositionReport = opposition.getOppositionReport(); if (oppositionReport == null) { - return; + throw new IllegalStateException("There is no opposition report submitted"); } + + FinalSeminarSettings finalSeminarSettings = finalSeminarSettingsService.getInstance(); + + Instant now = clock.instant(); + Instant deadline = daysService.workDaysAfter( + now, + finalSeminarSettings.getWorkDaysToFixRequestedImprovementsToOppositionReport() + ); + oppositionReport.setSubmitted(false); - opposition.setImprovementsRequestedAt(clock.instant()); + opposition.setImprovementsRequestedAt(now); opposition.setSupervisorCommentForImprovements(supervisorComment); + + return deadline; } } diff --git a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettings.java b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettings.java index 6468b01d85..012c9f4c38 100644 --- a/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettings.java +++ b/core/src/main/java/se/su/dsv/scipro/finalseminar/FinalSeminarSettings.java @@ -34,6 +34,9 @@ public class FinalSeminarSettings extends DomainObject { @Column(name = "days_ahead_to_upload_thesis", nullable = false) private int daysAheadToUploadThesis = DEFAULT_DAYS_AHEAD_TO_UPLOAD_THESIS; + @Column(name = "work_days_to_fix_requested_improvements_to_opposition_report", nullable = false) + private int workDaysToFixRequestedImprovementsToOppositionReport = 10; + @Column(name = "thesis_must_be_pdf", nullable = false) private boolean thesisMustBePDF = false; @@ -113,6 +116,17 @@ public class FinalSeminarSettings extends DomainObject { this.oppositionPriorityDays = oppositionPriorityDays; } + public int getWorkDaysToFixRequestedImprovementsToOppositionReport() { + return workDaysToFixRequestedImprovementsToOppositionReport; + } + + public void setWorkDaysToFixRequestedImprovementsToOppositionReport( + int workDaysToFixRequestedImprovementsToOppositionReport + ) { + this.workDaysToFixRequestedImprovementsToOppositionReport = + workDaysToFixRequestedImprovementsToOppositionReport; + } + @Override public String toString() { return ( diff --git a/core/src/main/java/se/su/dsv/scipro/misc/DaysService.java b/core/src/main/java/se/su/dsv/scipro/misc/DaysService.java index d52c0e467e..865d495bf7 100644 --- a/core/src/main/java/se/su/dsv/scipro/misc/DaysService.java +++ b/core/src/main/java/se/su/dsv/scipro/misc/DaysService.java @@ -1,6 +1,9 @@ package se.su.dsv.scipro.misc; +import java.time.Instant; import java.time.LocalDate; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Date; public interface DaysService { @@ -9,4 +12,11 @@ public interface DaysService { int workDaysBetween(Date startDate, Date endDate); LocalDate workDaysAhead(LocalDate date, int days); LocalDate workDaysAfter(LocalDate date, int days); + + default Instant workDaysAfter(Instant instant, int days) { + ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault()); + LocalDate localDate = zonedDateTime.toLocalDate(); + LocalDate newDate = workDaysAfter(localDate, days); + return newDate.atTime(zonedDateTime.toLocalTime()).atZone(ZoneId.systemDefault()).toInstant(); + } } diff --git a/core/src/main/resources/db/migration/V6__final_seminar_work_days_to_fix_opposition_report.sql b/core/src/main/resources/db/migration/V6__final_seminar_work_days_to_fix_opposition_report.sql new file mode 100644 index 0000000000..f102c8fe14 --- /dev/null +++ b/core/src/main/resources/db/migration/V6__final_seminar_work_days_to_fix_opposition_report.sql @@ -0,0 +1,2 @@ +ALTER TABLE `final_seminar_settings` + ADD COLUMN `work_days_to_fix_requested_improvements_to_opposition_report` INT(11) NOT NULL DEFAULT 10; diff --git a/view/src/main/java/se/su/dsv/scipro/finalseminar/AdminFinalSeminarSettingsPage.html b/view/src/main/java/se/su/dsv/scipro/finalseminar/AdminFinalSeminarSettingsPage.html index a17eec8b77..7b95106394 100755 --- a/view/src/main/java/se/su/dsv/scipro/finalseminar/AdminFinalSeminarSettingsPage.html +++ b/view/src/main/java/se/su/dsv/scipro/finalseminar/AdminFinalSeminarSettingsPage.html @@ -42,6 +42,13 @@ </div> </div> + <div class="mb-3"> + <label class="col-lg-4">How many work days opponents have to resubmit their report</label> + <div class="col-lg-1"> + <input class="form-control" type="text" wicket:id="work_days_to_fix_requested_improvements_to_opposition_report" /> + </div> + </div> + <div class="mb-3"> <div class="col-lg-offset-4 col-lg-4"> <div class="form-check"> diff --git a/view/src/main/java/se/su/dsv/scipro/finalseminar/AdminFinalSeminarSettingsPage.java b/view/src/main/java/se/su/dsv/scipro/finalseminar/AdminFinalSeminarSettingsPage.java index 59dad683ab..f04ffe4136 100755 --- a/view/src/main/java/se/su/dsv/scipro/finalseminar/AdminFinalSeminarSettingsPage.java +++ b/view/src/main/java/se/su/dsv/scipro/finalseminar/AdminFinalSeminarSettingsPage.java @@ -131,6 +131,17 @@ public class AdminFinalSeminarSettingsPage extends AbstractAdminSystemPage { Integer.class ) ); + add( + new RequiredTextField<>( + "work_days_to_fix_requested_improvements_to_opposition_report", + LambdaModel.of( + model, + FinalSeminarSettings::getWorkDaysToFixRequestedImprovementsToOppositionReport, + FinalSeminarSettings::setWorkDaysToFixRequestedImprovementsToOppositionReport + ), + Integer.class + ) + ); add( new CheckBox( SEMINAR_PDF, diff --git a/view/src/main/java/se/su/dsv/scipro/finalseminar/SeminarOppositionPanel.java b/view/src/main/java/se/su/dsv/scipro/finalseminar/SeminarOppositionPanel.java index 976c834af7..bb58ce4a9c 100644 --- a/view/src/main/java/se/su/dsv/scipro/finalseminar/SeminarOppositionPanel.java +++ b/view/src/main/java/se/su/dsv/scipro/finalseminar/SeminarOppositionPanel.java @@ -2,7 +2,7 @@ package se.su.dsv.scipro.finalseminar; import com.google.common.eventbus.EventBus; import jakarta.inject.Inject; -import java.time.Duration; +import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Date; @@ -360,19 +360,16 @@ public class SeminarOppositionPanel extends Panel { @Override protected void onSubmit() { - // TODO: return deadline - finalSeminarOppositionService.requestImprovements(getModelObject(), feedbackToOpponentModel.getObject()); + Instant deadline = finalSeminarOppositionService.requestImprovements( + getModelObject(), + feedbackToOpponentModel.getObject() + ); record ImprovementFeedback(String fullName, ZonedDateTime deadline) {} - ZonedDateTime deadline = getModelObject() - .getFinalSeminar() - .getStartDate() - .toInstant() - .plus(Duration.ofDays(10)) - .atZone(ZoneId.of("Europe/Stockholm")); + ZonedDateTime localDeadline = deadline.atZone(ZoneId.systemDefault()); success( getString("feedback.opponent.requested.improvements", () -> - new ImprovementFeedback(getModelObject().getUser().getFullName(), deadline) + new ImprovementFeedback(getModelObject().getUser().getFullName(), localDeadline) ) ); }