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 39 additions and 44 deletions
Showing only changes of commit 2261096f0a - Show all commits

View File

@ -8,4 +8,6 @@ public interface FinalSeminarOppositionService extends GenericService<FinalSemin
void delete(Long aLong);
List<OppositionCriterion> getCriteriaForOpposition(FinalSeminarOpposition opposition);
void gradeOpponent(FinalSeminarOpposition opposition, int points, String feedback);
}

View File

@ -25,4 +25,11 @@ public class FinalSeminarOppositionServiceImpl
public List<OppositionCriterion> getCriteriaForOpposition(FinalSeminarOpposition opposition) {
return finalSeminarOppositionGrading.oppositionCriteria(opposition);
}
@Override
public void gradeOpponent(FinalSeminarOpposition opposition, int points, String feedback) {
// TODO:
// * save assessment
// * post events
}
}

View File

@ -2,7 +2,6 @@ package se.su.dsv.scipro.report;
import java.time.Instant;
import java.util.List;
import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition;
import se.su.dsv.scipro.grading.GradingBasis;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.system.User;
@ -19,8 +18,6 @@ public interface GradingReportService {
SupervisorGradingReport supervisorGradingReport
);
boolean updateOppositionCriteria(SupervisorGradingReport report, FinalSeminarOpposition opposition);
GradingBasis getGradingBasis(Project project);
GradingBasis updateGradingBasis(Project project, GradingBasis gradingBasis);

View File

@ -1,6 +1,7 @@
package se.su.dsv.scipro.report;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import java.time.Clock;
@ -9,6 +10,7 @@ import java.time.LocalDate;
import java.util.*;
import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition;
import se.su.dsv.scipro.finalseminar.FinalSeminarOppositionGrading;
import se.su.dsv.scipro.finalseminar.OppositionApprovedEvent;
import se.su.dsv.scipro.finalseminar.OppositionCriterion;
import se.su.dsv.scipro.grading.GradingBasis;
import se.su.dsv.scipro.grading.GradingReportTemplateService;
@ -47,11 +49,11 @@ public class GradingReportServiceImpl
this.supervisorGradingReportRepository = supervisorGradingReportRepository;
this.gradingReportTemplateRepo = gradingReportTemplateRepo;
this.projectTypeService = projectTypeService;
eventBus.register(this);
}
@Override
@Transactional
public boolean updateOppositionCriteria(SupervisorGradingReport report, FinalSeminarOpposition opposition) {
private boolean updateOppositionCriteria(SupervisorGradingReport report, FinalSeminarOpposition opposition) {
for (GradingCriterion gradingCriterion : report.getIndividualCriteria()) {
boolean isOppositionCriterion = gradingCriterion.getFlag() == GradingCriterion.Flag.OPPOSITION;
boolean betterGrade =
@ -293,6 +295,12 @@ public class GradingReportServiceImpl
return gradingReportTemplateRepo.createTemplate(projectType, update);
}
@Subscribe
public void opponentApproved(OppositionApprovedEvent event) {
SupervisorGradingReport report = getSupervisorGradingReport(event.getProject(), event.getStudent());
updateOppositionCriteria(report, event.getOpposition());
}
@Override
@Transactional
public List<OppositionCriterion> oppositionCriteria(FinalSeminarOpposition opposition) {

View File

@ -5,6 +5,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.google.common.eventbus.EventBus;
import jakarta.inject.Inject;
import java.time.LocalDate;
import java.time.Month;
@ -13,6 +14,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import se.su.dsv.scipro.finalseminar.FinalSeminar;
import se.su.dsv.scipro.finalseminar.FinalSeminarOpposition;
import se.su.dsv.scipro.finalseminar.OppositionApprovedEvent;
import se.su.dsv.scipro.project.Project;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.system.DegreeType;
@ -31,6 +33,9 @@ public class GradingReportServiceImplIntegrationTest extends IntegrationTest {
@Inject
private GradingReportServiceImpl gradingReportService;
@Inject
private EventBus eventBus;
private ProjectType projectType;
private GradingReportTemplate gradingReportTemplate;
private Project project;
@ -45,7 +50,6 @@ public class GradingReportServiceImplIntegrationTest extends IntegrationTest {
project = createProject(projectType, 30);
gradingReportTemplate = createProjectGradingCriterion(gradingReportTemplate, 2);
gradingReportTemplate = createIndividualGradingCriterion(gradingReportTemplate, 2);
gradingReport = createGradingReport(project, student);
}
@Test
@ -68,6 +72,7 @@ public class GradingReportServiceImplIntegrationTest extends IntegrationTest {
@Test
public void submit_supervisor_grading_report_flags_report_as_submitted() {
gradingReport = createGradingReport(project, student);
assessAllCriteria(gradingReport);
Either<List<SubmissionError>, SupervisorGradingReport> result = gradingReportService.submitReport(
gradingReport
@ -77,6 +82,7 @@ public class GradingReportServiceImplIntegrationTest extends IntegrationTest {
@Test
public void submitting_supervisor_report_throws_exception_if_report_is_not_finished() {
gradingReport = createGradingReport(project, student);
Either<List<SubmissionError>, SupervisorGradingReport> result = gradingReportService.submitReport(
gradingReport
);
@ -86,38 +92,35 @@ public class GradingReportServiceImplIntegrationTest extends IntegrationTest {
@Test
public void update_opposition_criterion() {
addOppositionCriterion();
boolean updated = updateOppositionCriterion();
updateOppositionCriterion();
GradingCriterion oppositionCriterion = findOppositionCriterion();
assert oppositionCriterion != null;
assertEquals(FEEDBACK_ON_OPPOSITION, oppositionCriterion.getFeedback());
assertEquals((Integer) OPPOSITION_CRITERION_POINTS, oppositionCriterion.getPoints());
assertTrue(updated);
}
@Test
public void update_opposition_if_title_matches_english_title() {
addOppositionCriterion();
boolean updated = updateOppositionCriterion();
updateOppositionCriterion();
GradingCriterion oppositionCriterion = findEnglishOppositionCriterion("Ö1 Opposition report");
assert oppositionCriterion != null;
assertEquals(FEEDBACK_ON_OPPOSITION, oppositionCriterion.getFeedback());
assertEquals((Integer) OPPOSITION_CRITERION_POINTS, oppositionCriterion.getPoints());
assertTrue(updated);
}
@Test
public void updating_opposition_criterion_does_nothing_if_criterion_already_has_values() {
addOppositionCriterion();
assessAllCriteria(gradingReport);
boolean updated = updateOppositionCriterion();
updateOppositionCriterion();
GradingCriterion oppositionCriterion = findOppositionCriterion();
assert oppositionCriterion != null;
assertEquals(FEEDBACK, oppositionCriterion.getFeedback());
assertEquals((Integer) oppositionCriterion.getMaxPoints(), oppositionCriterion.getPoints());
assertFalse(updated);
}
@Test
@ -151,9 +154,9 @@ public class GradingReportServiceImplIntegrationTest extends IntegrationTest {
gradingReport = createGradingReport(project, student);
}
private boolean updateOppositionCriterion() {
private void updateOppositionCriterion() {
FinalSeminarOpposition opposition = createFinalSeminarOpposition();
return gradingReportService.updateOppositionCriteria(gradingReport, opposition);
eventBus.post(new OppositionApprovedEvent(opposition));
}
private GradingCriterion findOppositionCriterion() {
@ -176,8 +179,8 @@ public class GradingReportServiceImplIntegrationTest extends IntegrationTest {
private FinalSeminarOpposition createFinalSeminarOpposition() {
FinalSeminarOpposition finalSeminarOpposition = new FinalSeminarOpposition();
finalSeminarOpposition.setProject(createProject(projectType, 30));
finalSeminarOpposition.setUser(createStudent());
finalSeminarOpposition.setProject(project);
finalSeminarOpposition.setUser(student);
finalSeminarOpposition.setFinalSeminar(createFinalSeminar());
finalSeminarOpposition.setFeedback(FEEDBACK_ON_OPPOSITION);

View File

@ -33,7 +33,6 @@ import se.su.dsv.scipro.components.StatelessModel;
import se.su.dsv.scipro.profile.UserLinkPanel;
import se.su.dsv.scipro.report.GradingReportService;
import se.su.dsv.scipro.report.OppositionReportService;
import se.su.dsv.scipro.report.SupervisorGradingReport;
import se.su.dsv.scipro.security.auth.roles.Roles;
import se.su.dsv.scipro.session.SciProSession;
import se.su.dsv.scipro.system.ProjectModule;
@ -47,8 +46,6 @@ public class SeminarOppositionPanel extends Panel {
public static final String REMOVE = "remove";
public static final String FORM = "form";
public static final String POINTS = "points";
public static final int MIN_POINTS = 0;
public static final int MAX_POINTS = 2;
public static final String GRADING_FEEDBACK = "gradingFeedback";
public static final int FEEDBACK_MAX_LENGTH = 2000;
public static final String SUBMIT = "submit";
@ -258,31 +255,12 @@ public class SeminarOppositionPanel extends Panel {
new AjaxSubmitLink(SUBMIT) {
@Override
protected void onSubmit(AjaxRequestTarget target) {
if (getModelObject().getPoints().equals(0)) {
finalSeminarOpposition.getObject().setGrade(FinalSeminarGrade.NOT_APPROVED);
eventBus.post(new OppositionFailedEvent(finalSeminarOpposition.getObject()));
} else {
finalSeminarOpposition.getObject().setGrade(FinalSeminarGrade.APPROVED);
eventBus.post(new OppositionApprovedEvent(finalSeminarOpposition.getObject()));
}
finalSeminarOppositionService.save(finalSeminarOpposition.getObject());
boolean updated = true;
if (gradingModuleIsOnForProjectType()) {
SupervisorGradingReport report = gradingReportService.getSupervisorGradingReport(
finalSeminarOpposition.getObject().getProject(),
finalSeminarOpposition.getObject().getUser()
);
updated = gradingReportService.updateOppositionCriteria(
report,
finalSeminarOpposition.getObject()
);
}
success(
getString(
updated ? "feedback.opponent.updated" : "feedback.opponent.not.updated",
finalSeminarOpposition
)
finalSeminarOppositionService.gradeOpponent(
finalSeminarOpposition.getObject(),
pointsModel.getObject().points(),
feedbackModel.getObject()
);
success(getString("feedback.opponent.updated", finalSeminarOpposition));
target.add(feedbackPanel);
target.add(oppositionContainer);
}