Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assessment: Keep long feedback after saving an assessment #10090

Merged
merged 8 commits into from
Jan 5, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -522,23 +522,26 @@ private void handleFeedbackPersistence(Feedback feedback, Result result, Map<Lon
// Temporarily detach feedback from the parent result to avoid Hibernate issues
feedback.setResult(null);

// Clear the long feedback if it exists in the map
// Connect old long feedback text to the feedback before saving, otherwise it would be deleted
if (feedback.getId() != null && feedback.getHasLongFeedbackText()) {
LongFeedbackText longFeedback = longFeedbackTextMap.get(feedback.getId());
if (longFeedback != null) {
feedback.clearLongFeedback();

// If the long feedback is not empty, it means that changes have been made on the client, so we do not want
// to override the new long feedback with its previous version
if (feedback.getLongFeedback().isPresent()) {
// Delete the old long feedback so we don't get a duplicate key error
longFeedbackTextRepository.deleteByFeedbackIds(List.of(feedback.getId()));
b-fein marked this conversation as resolved.
Show resolved Hide resolved
}
else {
LongFeedbackText longFeedback = longFeedbackTextMap.get(feedback.getId());
feedback.setLongFeedbackText(Set.of(longFeedback));
}
}

// Persist the feedback entity without the parent association
feedback = feedbackRepository.saveAndFlush(feedback);

// Restore associations to the result and long feedback after persistence
// Restore associations to the result
feedback.setResult(result);
LongFeedbackText longFeedback = longFeedbackTextMap.get(feedback.getId());
if (longFeedback != null) {
feedback.setDetailText(longFeedback.getText());
}
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,6 @@ private Result saveManualAssessment(Result result, User assessor) {
* @return the new saved result
*/
public Result saveAndSubmitManualAssessment(StudentParticipation participation, Result newManualResult, Result existingManualResult, User assessor, boolean submit) {
// long feedback text is deleted as it otherwise causes duplicate entries errors and will be saved again with {@link resultRepository.save}
resultService.deleteLongFeedback(newManualResult.getFeedbacks(), newManualResult);
// make sure that the submission cannot be manipulated on the client side
var submission = (ProgrammingSubmission) existingManualResult.getSubmission();
ProgrammingExercise exercise = (ProgrammingExercise) participation.getExercise();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.springframework.beans.factory.annotation.Autowired;

import de.tum.cit.aet.artemis.assessment.repository.ComplaintRepository;
import de.tum.cit.aet.artemis.assessment.repository.LongFeedbackTextRepository;
import de.tum.cit.aet.artemis.assessment.util.ComplaintUtilService;
import de.tum.cit.aet.artemis.core.test_repository.UserTestRepository;
import de.tum.cit.aet.artemis.core.user.util.UserUtilService;
Expand Down Expand Up @@ -124,6 +125,9 @@ public abstract class AbstractProgrammingIntegrationIndependentTest extends Abst
@Autowired
protected UserTestRepository userRepository;

@Autowired
protected LongFeedbackTextRepository longFeedbackTextRepository;

// Services
@Autowired
protected AuxiliaryRepositoryService auxiliaryRepositoryService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import org.eclipse.jgit.lib.ObjectId;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentMatchers;
import org.springframework.http.HttpStatus;
import org.springframework.security.test.context.support.WithMockUser;
Expand Down Expand Up @@ -526,7 +528,6 @@ void updateManualProgrammingExerciseResult_newResult() throws Exception {
@Test
@WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA")
void updateManualProgrammingExerciseResult_addFeedbackAfterManualLongFeedback() throws Exception {

List<Feedback> feedbacks = new ArrayList<>();
var manualLongFeedback = new Feedback().credits(1.00).type(FeedbackType.MANUAL_UNREFERENCED);
manualLongFeedback.setDetailText("abc".repeat(5000));
Expand All @@ -553,6 +554,54 @@ void updateManualProgrammingExerciseResult_addFeedbackAfterManualLongFeedback()
assertThat(savedAutomaticLongFeedback.getDetailText()).isEqualTo(manualLongFeedback.getDetailText());
}

@ParameterizedTest
@ValueSource(booleans = { true, false })
@WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA")
void shouldKeepExistingLongFeedbackWhenSavingAnAssessment(boolean submit) throws Exception {
var manualLongFeedback = new Feedback().credits(0.0);
var longText = "abc".repeat(5000);
manualLongFeedback.setDetailText(longText);
var result = new Result().feedbacks(List.of(manualLongFeedback)).score(0.0);
result = resultRepository.save(result);

LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("submit", String.valueOf(submit));
result = request.putWithResponseBodyAndParams("/api/participations/" + programmingExerciseStudentParticipation.getId() + "/manual-results", result, Result.class,
HttpStatus.OK, params);

var longFeedbackText = longFeedbackTextRepository.findByFeedbackId(result.getFeedbacks().getFirst().getId());
assertThat(longFeedbackText).isPresent();
assertThat(longFeedbackText.get().getText()).isEqualTo(longText);
}

@ParameterizedTest
@ValueSource(booleans = { true, false })
@WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA")
void shouldUpdateUnreferencedLongFeedbackWhenSavingAnAssessment(boolean submit) throws Exception {
var manualLongFeedback = new Feedback().credits(0.0).type(FeedbackType.MANUAL_UNREFERENCED);
var longText = "abc".repeat(5000);
manualLongFeedback.setDetailText(longText);
var result = new Result().feedbacks(List.of(manualLongFeedback)).score(0.0);
result = resultRepository.save(result);

var newLongText = "def".repeat(5000);
manualLongFeedback = result.getFeedbacks().getFirst();

// The actual complete longtext is still stored in the detailText field when the result is sent from the client
var detailText = Feedback.class.getDeclaredField("detailText");
detailText.setAccessible(true);
detailText.set(manualLongFeedback, newLongText);

LinkedMultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("submit", String.valueOf(submit));
result = request.putWithResponseBodyAndParams("/api/participations/" + programmingExerciseStudentParticipation.getId() + "/manual-results", result, Result.class,
HttpStatus.OK, params);

var longFeedbackText = longFeedbackTextRepository.findByFeedbackId(result.getFeedbacks().getFirst().getId());
assertThat(longFeedbackText).isPresent();
assertThat(longFeedbackText.get().getText()).isEqualTo(newLongText);
}

@Test
@WithMockUser(username = TEST_PREFIX + "tutor1", roles = "TA")
void updateManualProgrammingExerciseResult_addFeedbackAfterAutomaticLongFeedback() throws Exception {
Expand Down
Loading