Allow supervisors to request improvements from final seminar opponents #78
@ -28,6 +28,7 @@ import se.su.dsv.scipro.file.ProjectFileRepository;
|
||||
import se.su.dsv.scipro.file.ProjectFileService;
|
||||
import se.su.dsv.scipro.file.ProjectFileServiceImpl;
|
||||
import se.su.dsv.scipro.finalseminar.AuthorRepository;
|
||||
import se.su.dsv.scipro.finalseminar.ExpireUnfulfilledOppositionImprovementsWorker;
|
||||
import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationRepository;
|
||||
import se.su.dsv.scipro.finalseminar.FinalSeminarActiveParticipationServiceImpl;
|
||||
import se.su.dsv.scipro.finalseminar.FinalSeminarCreationSubscribers;
|
||||
@ -204,6 +205,7 @@ import se.su.dsv.scipro.system.UserRepo;
|
||||
import se.su.dsv.scipro.system.UserService;
|
||||
import se.su.dsv.scipro.system.UserServiceImpl;
|
||||
import se.su.dsv.scipro.thesislink.ExternalLinkServiceImpl;
|
||||
import se.su.dsv.scipro.workerthreads.Scheduler;
|
||||
import se.su.dsv.scipro.workerthreads.WorkerDataServiceImpl;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ -1167,4 +1169,19 @@ public class CoreConfig {
|
||||
notificationController
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ExpireUnfulfilledOppositionImprovementsWorker expireUnfulfilledOppositionImprovementsWorker(
|
||||
FinalSeminarOppositionServiceImpl finalSeminarOppositionService
|
||||
) {
|
||||
return new ExpireUnfulfilledOppositionImprovementsWorker(finalSeminarOppositionService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ExpireUnfulfilledOppositionImprovementsWorker.Schedule expireUnfulfilledOppositionImprovementsWorkerSchedule(
|
||||
Scheduler scheduler,
|
||||
Provider<ExpireUnfulfilledOppositionImprovementsWorker> worker
|
||||
) {
|
||||
return new ExpireUnfulfilledOppositionImprovementsWorker.Schedule(scheduler, worker);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package se.su.dsv.scipro.finalseminar;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Provider;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import se.su.dsv.scipro.workerthreads.AbstractWorker;
|
||||
import se.su.dsv.scipro.workerthreads.Scheduler;
|
||||
|
||||
public class ExpireUnfulfilledOppositionImprovementsWorker extends AbstractWorker {
|
||||
|
||||
private final FinalSeminarOppositionServiceImpl oppositionService;
|
||||
|
||||
public ExpireUnfulfilledOppositionImprovementsWorker(FinalSeminarOppositionServiceImpl oppositionService) {
|
||||
this.oppositionService = oppositionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doWork() {
|
||||
oppositionService.expireUnfulfilledOppositionImprovements();
|
||||
}
|
||||
|
||||
public static class Schedule {
|
||||
|
||||
@Inject
|
||||
public Schedule(Scheduler scheduler, Provider<ExpireUnfulfilledOppositionImprovementsWorker> worker) {
|
||||
scheduler
|
||||
.schedule("Fail opponents that have not submitted improvements")
|
||||
.runBy(worker)
|
||||
.every(1, TimeUnit.HOURS);
|
||||
}
|
||||
}
|
||||
}
|
@ -11,4 +11,6 @@ import se.su.dsv.scipro.system.User;
|
||||
public interface FinalSeminarOppositionRepo
|
||||
extends JpaRepository<FinalSeminarOpposition, Long>, QueryDslPredicateExecutor<FinalSeminarOpposition> {
|
||||
List<FinalSeminarOpposition> findByOpposingUserAndType(User user, ProjectType projectType);
|
||||
|
||||
Collection<FinalSeminarOpposition> findUnfulfilledOppositionImprovements();
|
||||
}
|
||||
|
@ -24,4 +24,13 @@ public class FinalSeminarOppositionRepoImpl
|
||||
.where(QFinalSeminarOpposition.finalSeminarOpposition.project.projectType.eq(projectType))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FinalSeminarOpposition> findUnfulfilledOppositionImprovements() {
|
||||
return createQuery()
|
||||
.innerJoin(QFinalSeminarOpposition.finalSeminarOpposition.oppositionReport)
|
||||
.where(QFinalSeminarOpposition.finalSeminarOpposition.improvementsRequestedAt.isNotNull())
|
||||
.where(QFinalSeminarOpposition.finalSeminarOpposition.oppositionReport.submitted.isFalse())
|
||||
.fetch();
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import jakarta.persistence.EntityManager;
|
||||
import jakarta.transaction.Transactional;
|
||||
import java.time.Clock;
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import se.su.dsv.scipro.misc.DaysService;
|
||||
@ -65,11 +66,24 @@ public class FinalSeminarOppositionServiceImpl
|
||||
throw new PointNotValidException(points, List.of(0, 1));
|
||||
}
|
||||
|
||||
FinalSeminarGrade notApproved = criteriaForOpposition.pointsToPass() > points
|
||||
? FinalSeminarGrade.NOT_APPROVED
|
||||
: FinalSeminarGrade.APPROVED;
|
||||
return internalGradeOpponent(opposition, points, feedback, notApproved);
|
||||
}
|
||||
|
||||
private FinalSeminarOpposition internalGradeOpponent(
|
||||
FinalSeminarOpposition opposition,
|
||||
int points,
|
||||
String feedback,
|
||||
FinalSeminarGrade grade
|
||||
) {
|
||||
opposition.setGrade(grade);
|
||||
opposition.setPoints(points);
|
||||
opposition.setFeedback(feedback);
|
||||
FinalSeminarOpposition assessedOpposition = finalSeminarOppositionRepository.save(opposition);
|
||||
|
||||
if (criteriaForOpposition.pointsToPass() > points) {
|
||||
if (grade == FinalSeminarGrade.NOT_APPROVED) {
|
||||
eventBus.post(new OppositionFailedEvent(assessedOpposition));
|
||||
} else {
|
||||
eventBus.post(new OppositionApprovedEvent(assessedOpposition));
|
||||
@ -128,4 +142,36 @@ public class FinalSeminarOppositionServiceImpl
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
void expireUnfulfilledOppositionImprovements() {
|
||||
Collection<FinalSeminarOpposition> unfulfilledOppositions =
|
||||
finalSeminarOppositionRepository.findUnfulfilledOppositionImprovements();
|
||||
|
||||
Instant now = clock.instant();
|
||||
int workDaysToFixRequestedImprovementsToOppositionReport = finalSeminarSettingsService
|
||||
.getInstance()
|
||||
.getWorkDaysToFixRequestedImprovementsToOppositionReport();
|
||||
for (FinalSeminarOpposition unfulfilledOpposition : unfulfilledOppositions) {
|
||||
Instant deadline = daysService.workDaysAfter(
|
||||
unfulfilledOpposition.getImprovementsRequestedAt(),
|
||||
workDaysToFixRequestedImprovementsToOppositionReport
|
||||
);
|
||||
if (now.isAfter(deadline)) {
|
||||
internalGradeOpponent(
|
||||
unfulfilledOpposition,
|
||||
0,
|
||||
unfulfilledOpposition.getSupervisorCommentForImprovements(),
|
||||
FinalSeminarGrade.NOT_APPROVED
|
||||
);
|
||||
|
||||
OppositionReport oppositionReport = unfulfilledOpposition.getOppositionReport();
|
||||
if (oppositionReport != null) {
|
||||
// Lock the report so it's not possible to submit it again
|
||||
oppositionReport.setSubmitted(true);
|
||||
}
|
||||
|
||||
finalSeminarOppositionRepository.save(unfulfilledOpposition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user