Allow supervisors to request improvements from final seminar opponents #78

Merged
niat8586 merged 41 commits from opponent-completion into develop 2025-03-05 10:05:38 +01:00
6 changed files with 44 additions and 26 deletions
Showing only changes of commit fec631f2d0 - Show all commits

View File

@ -154,6 +154,7 @@ import se.su.dsv.scipro.report.GradingReportServiceImpl;
import se.su.dsv.scipro.report.GradingReportTemplateRepo; import se.su.dsv.scipro.report.GradingReportTemplateRepo;
import se.su.dsv.scipro.report.GradingReportTemplateRepoImpl; import se.su.dsv.scipro.report.GradingReportTemplateRepoImpl;
import se.su.dsv.scipro.report.OppositionReportRepo; import se.su.dsv.scipro.report.OppositionReportRepo;
import se.su.dsv.scipro.report.OppositionReportService;
import se.su.dsv.scipro.report.OppositionReportServiceImpl; import se.su.dsv.scipro.report.OppositionReportServiceImpl;
import se.su.dsv.scipro.report.ReportServiceImpl; import se.su.dsv.scipro.report.ReportServiceImpl;
import se.su.dsv.scipro.report.SupervisorGradingReportRepository; import se.su.dsv.scipro.report.SupervisorGradingReportRepository;
@ -438,7 +439,8 @@ public class CoreConfig {
FinalSeminarOppositionRepo finalSeminarOppositionRepository, FinalSeminarOppositionRepo finalSeminarOppositionRepository,
Clock clock, Clock clock,
FinalSeminarSettingsService finalSeminarSettingsService, FinalSeminarSettingsService finalSeminarSettingsService,
DaysService daysService DaysService daysService,
OppositionReportService oppositionReportService
) { ) {
return new FinalSeminarOppositionServiceImpl( return new FinalSeminarOppositionServiceImpl(
em, em,
@ -447,7 +449,8 @@ public class CoreConfig {
finalSeminarOppositionRepository, finalSeminarOppositionRepository,
clock, clock,
finalSeminarSettingsService, finalSeminarSettingsService,
daysService daysService,
oppositionReportService
); );
} }

View File

@ -3,10 +3,7 @@ package se.su.dsv.scipro.finalseminar;
import java.time.Instant; import java.time.Instant;
import se.su.dsv.scipro.system.GenericService; import se.su.dsv.scipro.system.GenericService;
public interface FinalSeminarOppositionService extends GenericService<FinalSeminarOpposition, Long> { public interface FinalSeminarOppositionService {
@Override
void delete(Long aLong);
OppositionCriteria getCriteriaForOpposition(FinalSeminarOpposition opposition); OppositionCriteria getCriteriaForOpposition(FinalSeminarOpposition opposition);
FinalSeminarOpposition gradeOpponent(FinalSeminarOpposition opposition, int points, String feedback) FinalSeminarOpposition gradeOpponent(FinalSeminarOpposition opposition, int points, String feedback)
@ -16,4 +13,6 @@ public interface FinalSeminarOppositionService extends GenericService<FinalSemin
* @return the deadline by which the improvements must have been submitted * @return the deadline by which the improvements must have been submitted
*/ */
Instant requestImprovements(FinalSeminarOpposition opposition, String supervisorComment); Instant requestImprovements(FinalSeminarOpposition opposition, String supervisorComment);
Opposition getOpposition(long id);
} }

View File

@ -10,6 +10,7 @@ import java.time.Instant;
import java.util.List; import java.util.List;
import se.su.dsv.scipro.misc.DaysService; import se.su.dsv.scipro.misc.DaysService;
import se.su.dsv.scipro.report.OppositionReport; import se.su.dsv.scipro.report.OppositionReport;
import se.su.dsv.scipro.report.OppositionReportService;
import se.su.dsv.scipro.system.AbstractServiceImpl; import se.su.dsv.scipro.system.AbstractServiceImpl;
public class FinalSeminarOppositionServiceImpl public class FinalSeminarOppositionServiceImpl
@ -22,6 +23,7 @@ public class FinalSeminarOppositionServiceImpl
private final Clock clock; private final Clock clock;
private final FinalSeminarSettingsService finalSeminarSettingsService; private final FinalSeminarSettingsService finalSeminarSettingsService;
private final DaysService daysService; private final DaysService daysService;
private final OppositionReportService oppositionReportService;
@Inject @Inject
public FinalSeminarOppositionServiceImpl( public FinalSeminarOppositionServiceImpl(
@ -31,7 +33,8 @@ public class FinalSeminarOppositionServiceImpl
FinalSeminarOppositionRepo finalSeminarOppositionRepository, FinalSeminarOppositionRepo finalSeminarOppositionRepository,
Clock clock, Clock clock,
FinalSeminarSettingsService finalSeminarSettingsService, FinalSeminarSettingsService finalSeminarSettingsService,
DaysService daysService DaysService daysService,
OppositionReportService oppositionReportService
) { ) {
super(em, FinalSeminarOpposition.class, QFinalSeminarOpposition.finalSeminarOpposition); super(em, FinalSeminarOpposition.class, QFinalSeminarOpposition.finalSeminarOpposition);
this.finalSeminarOppositionGrading = finalSeminarOppositionGrading; this.finalSeminarOppositionGrading = finalSeminarOppositionGrading;
@ -40,6 +43,7 @@ public class FinalSeminarOppositionServiceImpl
this.clock = clock; this.clock = clock;
this.finalSeminarSettingsService = finalSeminarSettingsService; this.finalSeminarSettingsService = finalSeminarSettingsService;
this.daysService = daysService; this.daysService = daysService;
this.oppositionReportService = oppositionReportService;
} }
@Override @Override
@ -95,4 +99,14 @@ public class FinalSeminarOppositionServiceImpl
return deadline; return deadline;
} }
@Override
public Opposition getOpposition(long id) {
FinalSeminarOpposition finalSeminarOpposition = finalSeminarOppositionRepository.findOne(id);
if (finalSeminarOpposition == null) {
return null;
}
OppositionReport report = oppositionReportService.findOrCreateReport(finalSeminarOpposition);
return new Opposition(finalSeminarOpposition.getUser(), report);
}
} }

View File

@ -0,0 +1,6 @@
package se.su.dsv.scipro.finalseminar;
import se.su.dsv.scipro.report.OppositionReport;
import se.su.dsv.scipro.system.User;
public record Opposition(User user, OppositionReport report) {}

View File

@ -35,13 +35,15 @@ public class OppositionReportPage extends AbstractProjectDetailsPage implements
throw new RestartResponseException(ProjectDetailsPage.class, pp); throw new RestartResponseException(ProjectDetailsPage.class, pp);
} }
final FinalSeminarOpposition opposition = finalSeminarOppositionService.findOne(pp.get("oid").toLong()); final IModel<Opposition> opposition = LoadableDetachableModel.of(() ->
finalSeminarOppositionService.getOpposition(pp.get("oid").toLong())
);
if (opposition == null) { if (opposition.getObject() == null) {
throw new RestartResponseException(ProjectDetailsPage.class, pp); throw new RestartResponseException(ProjectDetailsPage.class, pp);
} }
final IModel<OppositionReport> report = getOppositionReport(opposition); final IModel<OppositionReport> report = opposition.map(Opposition::report);
add( add(
new ViewAttachmentPanel( new ViewAttachmentPanel(
@ -71,18 +73,9 @@ public class OppositionReportPage extends AbstractProjectDetailsPage implements
@Override @Override
protected void onConfigure() { protected void onConfigure() {
super.onConfigure(); super.onConfigure();
setEnabled(opposition.getUser().equals(SciProSession.get().getUser())); setEnabled(opposition.getObject().user().equals(SciProSession.get().getUser()));
} }
} }
); );
} }
private IModel<OppositionReport> getOppositionReport(final FinalSeminarOpposition opposition) {
return new LoadableDetachableModel<>() {
@Override
protected OppositionReport load() {
return oppositionReportService.findOrCreateReport(opposition);
}
};
}
} }

View File

@ -76,10 +76,9 @@ public class OppositionReportPageTest extends SciProTest {
Mockito.when(finalSeminarService.findByProject(opponentsProject)).thenReturn(finalSeminar); Mockito.when(finalSeminarService.findByProject(opponentsProject)).thenReturn(finalSeminar);
} }
private void mockReport(ProjectType bachelor) { private OppositionReport mockReport(ProjectType bachelor) {
GradingReportTemplate reportTemplate = createTemplate(bachelor); GradingReportTemplate reportTemplate = createTemplate(bachelor);
OppositionReport oppositionReport = reportTemplate.createOppositionReport(finalSeminarOpposition); return reportTemplate.createOppositionReport(finalSeminarOpposition);
Mockito.when(oppositionReportService.findOrCreateReport(finalSeminarOpposition)).thenReturn(oppositionReport);
} }
@Test @Test
@ -104,14 +103,16 @@ public class OppositionReportPageTest extends SciProTest {
public void disable_form_if_opposition_does_not_belong_to_logged_in_user() { public void disable_form_if_opposition_does_not_belong_to_logged_in_user() {
mockReport(bachelor); mockReport(bachelor);
long oppositionId = 4L; long oppositionId = 4L;
Mockito.when(finalSeminarOppositionService.findOne(oppositionId)).thenReturn(finalSeminarOpposition); Mockito.when(finalSeminarOppositionService.getOpposition(oppositionId)).thenReturn(
new Opposition(user, mockReport(bachelor))
);
startPage(oppositionId); startPage(oppositionId);
tester.assertDisabled(FILL_OUT_REPORT); tester.assertDisabled(FILL_OUT_REPORT);
} }
@Test @Test
public void redirect_if_no_opposition_is_found_from_id() { public void redirect_if_no_opposition_is_found_from_id() {
Mockito.when(finalSeminarOppositionService.findOne(ArgumentMatchers.anyLong())).thenReturn(null); Mockito.when(finalSeminarOppositionService.getOpposition(ArgumentMatchers.anyLong())).thenReturn(null);
startPage(1L); startPage(1L);
tester.assertRenderedPage(ProjectDetailsPage.class); tester.assertRenderedPage(ProjectDetailsPage.class);
} }
@ -156,7 +157,9 @@ public class OppositionReportPageTest extends SciProTest {
private void startOppositionPage() { private void startOppositionPage() {
long oppositionId = 4L; long oppositionId = 4L;
setLoggedInAs(user); setLoggedInAs(user);
Mockito.when(finalSeminarOppositionService.findOne(oppositionId)).thenReturn(finalSeminarOpposition); Mockito.when(finalSeminarOppositionService.getOpposition(oppositionId)).thenReturn(
new Opposition(user, mockReport(bachelor))
);
startPage(oppositionId); startPage(oppositionId);
} }