diff --git a/src/main/java/org/olat/course/config/ui/CourseScoreController.java b/src/main/java/org/olat/course/config/ui/CourseScoreController.java index 66d18906f8055fa92580cafa435bc25abe03d195..2800837709a309f70b52f2343f548be386da522e 100644 --- a/src/main/java/org/olat/course/config/ui/CourseScoreController.java +++ b/src/main/java/org/olat/course/config/ui/CourseScoreController.java @@ -33,16 +33,19 @@ import org.olat.core.gui.components.util.KeyValues; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; +import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController; import org.olat.core.id.OLATResourceable; import org.olat.core.util.StringHelper; import org.olat.core.util.Util; import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.course.assessment.CourseAssessmentService; +import org.olat.course.config.ui.ScoreSettingsConfirmationController.ScoreSettingsConfirmationEvent; import org.olat.course.nodes.STCourseNode; import org.olat.course.run.RunMainController; import org.olat.course.tree.CourseEditorTreeNode; import org.olat.modules.ModuleConfiguration; +import org.olat.modules.assessment.AssessmentService; import org.olat.repository.RepositoryEntry; import org.springframework.beans.factory.annotation.Autowired; @@ -67,11 +70,16 @@ public class CourseScoreController extends FormBasicController { private MultipleSelectionElement passedPointsEl; private TextElement passedPointsCutEl; + private CloseableModalController cmc; + private ScoreSettingsConfirmationController settingsConfirmationCtrl; + private final RepositoryEntry courseEntry; private final boolean editable; @Autowired private CourseAssessmentService courseAssessmentService; + @Autowired + private AssessmentService assessmentService; public CourseScoreController(UserRequest ureq, WindowControl wControl, RepositoryEntry entry, boolean editable) { super(ureq, wControl); @@ -122,6 +130,7 @@ public class CourseScoreController extends FormBasicController { @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + flc.removeAll(); setFormTitle("options.score.title"); KeyValues scoreKV = new KeyValues(); @@ -212,6 +221,30 @@ public class CourseScoreController extends FormBasicController { super.formInnerEvent(ureq, source, event); } + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(source == settingsConfirmationCtrl) { + if (event instanceof ScoreSettingsConfirmationEvent) { + ScoreSettingsConfirmationEvent ssce = (ScoreSettingsConfirmationEvent)event; + doSettingsConfirmed(ureq, ssce); + } else if (event == ScoreSettingsConfirmationController.RESET_SETTING_EVENT) { + initForm(ureq); + } + cmc.deactivate(); + cleanUp(); + } else if(source == cmc) { + cleanUp(); + } + super.event(ureq, source, event); + } + + private void cleanUp() { + removeAsListenerAndDispose(settingsConfirmationCtrl); + removeAsListenerAndDispose(cmc); + settingsConfirmationCtrl = null; + cmc = null; + } + @Override protected boolean validateFormLogic(UserRequest ureq) { boolean allOk = true; @@ -248,12 +281,44 @@ public class CourseScoreController extends FormBasicController { return allOk; } + private void doConfirmSetting(UserRequest ureq) { + settingsConfirmationCtrl = new ScoreSettingsConfirmationController(ureq, getWindowControl()); + listenTo(settingsConfirmationCtrl); + cmc = new CloseableModalController(getWindowControl(), translate("close"), + settingsConfirmationCtrl.getInitialComponent(), true, translate("confirm.score.settings.title"), true); + listenTo(cmc); + cmc.activate(); + } + @Override protected void formOK(UserRequest ureq) { + doConfirmSetting(ureq); + } + + private void doSettingsConfirmed(UserRequest ureq, ScoreSettingsConfirmationEvent ssce) { + boolean saved = doSave(); + + if (saved) { + if (ssce.isResetOverriden()) { + assessmentService.resetAllOverridenRootPassed(courseEntry); + } + if (ssce.isResetPassed()) { + assessmentService.resetAllRootPassed(courseEntry); + } + if (ssce.isRecalculateAll()) { + ICourse course = CourseFactory.loadCourse(courseEntry); + courseAssessmentService.evaluateAll(course); + } + + fireEvent(ureq, Event.CHANGED_EVENT); + } + } + + private boolean doSave() { OLATResourceable courseOres = courseEntry.getOlatResource(); - if(CourseFactory.isCourseEditSessionOpen(courseOres.getResourceableId())) { + if (CourseFactory.isCourseEditSessionOpen(courseOres.getResourceableId())) { showWarning("error.editoralreadylocked", new String[] { "???" }); - return; + return false; } ICourse course = CourseFactory.openCourseEditSession(courseOres.getResourceableId()); @@ -331,9 +396,7 @@ public class CourseScoreController extends FormBasicController { CourseFactory.saveCourse(courseEntry.getOlatResource().getResourceableId()); CourseFactory.closeCourseEditSession(course.getResourceableId(), true); - courseAssessmentService.evaluateAll(course); - - fireEvent(ureq, Event.CHANGED_EVENT); + return true; } @Override diff --git a/src/main/java/org/olat/course/config/ui/CourseSettingsController.java b/src/main/java/org/olat/course/config/ui/CourseSettingsController.java index c4eb018e5616eb5f478ea153475249475804c583..179528d766d2add168aa64cfe9c7de662049121d 100644 --- a/src/main/java/org/olat/course/config/ui/CourseSettingsController.java +++ b/src/main/java/org/olat/course/config/ui/CourseSettingsController.java @@ -106,7 +106,7 @@ public class CourseSettingsController extends RepositoryEntrySettingsController doOpenLayout(ureq); } else if("Toolbar".equalsIgnoreCase(type)) { doOpenToolbarSettings(ureq); - } else if("Results".equalsIgnoreCase(type)) { + } else if("Assessment".equalsIgnoreCase(type)) { doOpenAssessmentSettings(ureq); } else if("Options".equalsIgnoreCase(type)) { doOpenOptions(ureq); diff --git a/src/main/java/org/olat/course/config/ui/ScoreSettingsConfirmationController.java b/src/main/java/org/olat/course/config/ui/ScoreSettingsConfirmationController.java new file mode 100644 index 0000000000000000000000000000000000000000..3260a10e10b23b84ba2014f705518bf5604fe543 --- /dev/null +++ b/src/main/java/org/olat/course/config/ui/ScoreSettingsConfirmationController.java @@ -0,0 +1,148 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.config.ui; + +import org.olat.core.gui.UserRequest; +import org.olat.core.gui.components.form.flexible.FormItem; +import org.olat.core.gui.components.form.flexible.FormItemContainer; +import org.olat.core.gui.components.form.flexible.elements.FormLink; +import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement; +import org.olat.core.gui.components.form.flexible.impl.FormBasicController; +import org.olat.core.gui.components.form.flexible.impl.FormEvent; +import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; +import org.olat.core.gui.control.WindowControl; + +/** + * + * Initial date: 27 Mar 2020<br> + * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com + * + */ +public class ScoreSettingsConfirmationController extends FormBasicController { + + public static final Event RESET_SETTING_EVENT = new Event("reset.changes"); + + private static final String ENABLE = "enable"; + private static final String[] ENABLE_KEYS = new String [] {ENABLE}; + + private MultipleSelectionElement recalculateAllEl; + private MultipleSelectionElement resetPassedEl; + private MultipleSelectionElement resetOverridenEl; + private FormLink resetButton; + + public ScoreSettingsConfirmationController(UserRequest ureq, WindowControl wControl) { + super(ureq, wControl); + initForm(ureq); + } + + @Override + protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { + setFormDescription("confirm.score.settings.desc", null); + + recalculateAllEl = uifactory.addCheckboxesVertical("recalculate.all", + "confirm.score.settings.recalculate.all.label", formLayout, ENABLE_KEYS, + new String[] { translate("confirm.score.settings.recalculate.all") }, 1); + recalculateAllEl.select(recalculateAllEl.getKey(0), true); + recalculateAllEl.addActionListener(FormEvent.ONCHANGE); + + resetPassedEl = uifactory.addCheckboxesVertical("reset.passed", "confirm.score.settings.reset.passed.label", + formLayout, ENABLE_KEYS, new String[] { translate("confirm.score.settings.reset.passed") }, 1); + + resetOverridenEl = uifactory.addCheckboxesVertical("reset.overriden", + "confirm.score.settings.reset.overriden.label", formLayout, ENABLE_KEYS, + new String[] { translate("confirm.score.settings.reset.overriden") }, 1); + + FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); + formLayout.add(buttonsCont); + uifactory.addFormSubmitButton("save", buttonsCont); + uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl()); + resetButton = uifactory.addFormLink("confirm.score.settings.reset.changes", buttonsCont, Link.BUTTON); + + updateUI(); + } + + private void updateUI() { + boolean recalculate = recalculateAllEl.isAtLeastSelected(1); + resetPassedEl.setVisible(recalculate); + } + + @Override + protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { + if (source == recalculateAllEl) { + updateUI(); + } else + if (source == resetButton) { + fireEvent(ureq, RESET_SETTING_EVENT); + } + super.formInnerEvent(ureq, source, event); + } + + @Override + protected void formCancelled(UserRequest ureq) { + fireEvent(ureq, Event.CANCELLED_EVENT); + } + + @Override + protected void formOK(UserRequest ureq) { + boolean recalculateAll = recalculateAllEl.isAtLeastSelected(0); + boolean resetPassed = resetPassedEl.isVisible() && resetPassedEl.isAtLeastSelected(1); + boolean resetOverriden = resetOverridenEl.isAtLeastSelected(1); + Event confirmedEvent = new ScoreSettingsConfirmationEvent(recalculateAll, resetPassed, resetOverriden); + fireEvent(ureq, confirmedEvent ); + } + + @Override + protected void doDispose() { + // + } + + public static class ScoreSettingsConfirmationEvent extends Event { + + private static final long serialVersionUID = 915883316389709373L; + + private final boolean recalculateAll; + private final boolean resetPassed; + private final boolean resetOverriden; + + public ScoreSettingsConfirmationEvent(boolean recalculateAll, boolean resetPassed, boolean resetOverriden) { + super("score.settings.confirmed"); + this.resetPassed = resetPassed; + this.resetOverriden = resetOverriden; + this.recalculateAll = recalculateAll; + } + + public boolean isRecalculateAll() { + return recalculateAll; + } + + public boolean isResetPassed() { + return resetPassed; + } + + public boolean isResetOverriden() { + return resetOverriden; + } + + } + +} diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties index d523363009d9a613ed9834005765a69253afff22..f5cb562480489ec67cea6b6a3a97be71445b97bf 100644 --- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_de.properties @@ -27,6 +27,15 @@ chkbx.breadcrumb.onoff=Kr\u00FCmelnavigation command.choose=W\u00E4hlen command.glossary.add=Glossar w\u00E4hlen command.glossary.remove=Auswahl l\u00F6schen +confirm.score.settings.desc=Wollen Sie nur die Einstellungen \u00E4ndern oder wollen Sie auch die berechneten Bewertungen aktualisieren? +confirm.score.settings.recalculate.all=aktualisieren +confirm.score.settings.recalculate.all.label=Kursbewertungen und Leistungsausweise +confirm.score.settings.reset.changes=\u00C4nderungen verwerfen +confirm.score.settings.reset.overriden=zur\u00FCcksetzen +confirm.score.settings.reset.overriden.label=Manuell gesetzte "bestanden" +confirm.score.settings.reset.passed=zur\u00FCcksetzen +confirm.score.settings.reset.passed.label=Berechnete "bestanden" +confirm.score.settings.title=Einstellungen speichern course.log.changed.message=<br>Detaillierte Kurs-Log-Dateien k\u00F6nnen im Archivierungs-Tool heruntergeladen werden.<br><br>Alte Kurs-Log-Dateien (bis und mit OLAT 6.2) stehen im Ablageordner des Kurses zur Verf\u00FCgung. coursefolder=Ablageordner details.assessment=Bewertung diff --git a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties index 3540e06102ea608bcbf940349127460be5e369d1..78f1387f3e8cddfd7e9f05f9bbfc138a53693697 100644 --- a/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/config/ui/_i18n/LocalStrings_en.properties @@ -27,6 +27,15 @@ chkbx.breadcrumb.onoff=Bread-crumb navigation command.choose=Choose command.glossary.add=Select glossary command.glossary.remove=Delete selection +confirm.score.settings.desc=Do you only want to change the settings or do you want to recalculate the calculated assessments as well? +confirm.score.settings.recalculate.all=recalculate +confirm.score.settings.recalculate.all.label=Course assessment and efficiency statements +confirm.score.settings.reset.changes=Discard changes +confirm.score.settings.reset.overriden=reset +confirm.score.settings.reset.overriden.label=Manually set "passed" +confirm.score.settings.reset.passed=reset +confirm.score.settings.reset.passed.label=Calculated "passed" +confirm.score.settings.title=Save settings course.log.changed.message=<br>Detailed course log files can be downloaded with the archiving tool.<br><br> Older course log files (OLAT 6.2 and earlier versions) are at your disposal in the course's storage folder. coursefolder=Storage folder details.assessment=Assessment diff --git a/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentHandler.java b/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentHandler.java index bd10c94a2801b1f68f6e047f98913c846df72d40..d04e83f959a4fcbabdfdb098c6c47b8fa249344d 100644 --- a/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentHandler.java +++ b/src/main/java/org/olat/course/nodes/st/assessment/STAssessmentHandler.java @@ -130,7 +130,6 @@ public class STAssessmentHandler implements AssessmentHandler { AccountingEvaluatorsBuilder builder = AccountingEvaluatorsBuilder.builder() .withObligationEvaluator(MANDATORY_OBLIGATION_EVALUATOR) .withDurationEvaluator(CUMULATION_DURATION_EVALUATOR) - .withPassedEvaluator(CONDITION_PASSED_EVALUATOR) .withStatusEvaluator(LEARNING_PATH_STATUS_EVALUATOR) .withFullyAssessedEvaluator(FULLY_ASSESSED_EVALUATOR) .withLastModificationsEvaluator(LAST_MODIFICATION_EVALUATOR) diff --git a/src/main/java/org/olat/modules/assessment/AssessmentService.java b/src/main/java/org/olat/modules/assessment/AssessmentService.java index 2df6be832043ea5149616648a14ab91b10433769..4a5115969313e98ff34d7993059ddf7e086ee6b0 100644 --- a/src/main/java/org/olat/modules/assessment/AssessmentService.java +++ b/src/main/java/org/olat/modules/assessment/AssessmentService.java @@ -72,6 +72,9 @@ public interface AssessmentService { public AssessmentEntry updateAssessmentEntry(AssessmentEntry entry); + public void resetAllRootPassed(RepositoryEntry entry); + + public void resetAllOverridenRootPassed(RepositoryEntry entry); public List<AssessmentEntry> loadAssessmentEntriesBySubIdent(RepositoryEntry entry, String subIdent); diff --git a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java index 8fa716c2c2ddedc59ea0225f5a33d48daadeae74..792ef2e9fcada887eb7f0fea47bfd9a6d6d03056 100644 --- a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java +++ b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java @@ -231,6 +231,64 @@ public class AssessmentEntryDAO { return dbInstance.getCurrentEntityManager().merge(nodeAssessment); } + public void resetAllRootPassed(RepositoryEntry entry) { + if (entry == null) return; + + StringBuilder sb = new StringBuilder(); + sb.append("update assessmententry data"); + sb.append(" set data.passedOriginal = :passedOriginal"); + sb.append(" , data.lastModified = :lastModified"); + sb.append(" where data.entryRoot = true"); + sb.append(" and data.passedModificationDate is not null"); + sb.append(" and data.repositoryEntry.key = :repositoryEntryKey"); + + dbInstance.getCurrentEntityManager() + .createQuery(sb.toString()) + .setParameter("passedOriginal", null) + .setParameter("lastModified", new Date()) + .setParameter("repositoryEntryKey", entry.getKey()) + .executeUpdate(); + + sb = new StringBuilder(); + sb.append("update assessmententry data"); + sb.append(" set data.passed = :passed"); + sb.append(" , data.lastModified = :lastModified"); + sb.append(" where data.entryRoot = true"); + sb.append(" and data.passedModificationDate is null"); + sb.append(" and data.repositoryEntry.key = :repositoryEntryKey"); + + dbInstance.getCurrentEntityManager() + .createQuery(sb.toString()) + .setParameter("passed", null) + .setParameter("lastModified", new Date()) + .setParameter("repositoryEntryKey", entry.getKey()) + .executeUpdate(); + } + + public void resetAllOverridenRootPassed(RepositoryEntry entry) { + if (entry == null) return; + + StringBuilder sb = new StringBuilder(); + sb.append("update assessmententry data"); + sb.append(" set data.passed = data.passedOriginal"); + sb.append(" , data.passedOriginal = :passedOriginal"); + sb.append(" , data.passedModificationDate = :passedModificationDate"); + sb.append(" , data.passedModificationIdentity = :passedModificationIdentity"); + sb.append(" , data.lastModified = :lastModified"); + sb.append(" where data.entryRoot = true"); + sb.append(" and data.passedModificationDate is not null"); + sb.append(" and data.repositoryEntry.key = :repositoryEntryKey"); + + dbInstance.getCurrentEntityManager() + .createQuery(sb.toString()) + .setParameter("passedOriginal", null) + .setParameter("passedModificationDate", null) + .setParameter("passedModificationIdentity", null) + .setParameter("lastModified", new Date()) + .setParameter("repositoryEntryKey", entry.getKey()) + .executeUpdate(); + } + /** * Load all assessment entries for the specific assessed repository entry with * the specific sub identifier (it is mandatory). The anonym users are excluded diff --git a/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java b/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java index a89af06ccc9646e8d4240119aeab57ba722d7768..f30cd2fbce1980400f461880c2735125851f335f 100644 --- a/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java +++ b/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java @@ -96,6 +96,18 @@ public class AssessmentServiceImpl implements AssessmentService, UserDataDeletab public AssessmentEntry updateAssessmentEntry(AssessmentEntry entry) { return assessmentEntryDao.updateAssessmentEntry(entry); } + + @Override + public void resetAllRootPassed(RepositoryEntry entry) { + assessmentEntryDao.resetAllRootPassed(entry); + dbInstance.commit(); + } + + @Override + public void resetAllOverridenRootPassed(RepositoryEntry entry) { + assessmentEntryDao.resetAllOverridenRootPassed(entry); + dbInstance.commit(); + } @Override public List<AssessmentEntry> loadAssessmentEntriesBySubIdent(RepositoryEntry entry, String subIdent) { diff --git a/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java b/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java index 16e0ecab73c64990dd09a5431d2af3fb26d44534..5167a405ff4fe04256d13cb5994fda37e401c128 100644 --- a/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java +++ b/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java @@ -34,6 +34,7 @@ import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; +import org.assertj.core.api.SoftAssertions; import org.junit.Assert; import org.junit.Test; import org.olat.basesecurity.GroupRoles; @@ -447,7 +448,88 @@ public class AssessmentEntryDAOTest extends OlatTestCase { dbInstance.commitAndCloseSession(); Assert.assertNull(nodeAssessment.getFullyAssessedDate()); } - + + @Test + public void shouldResetAllRootPassed() { + Identity coach = JunitTestHelper.createAndPersistIdentityAsRndUser("coach"); + Identity assessedIdentity1 = JunitTestHelper.createAndPersistIdentityAsRndUser("as-node-6a"); + Identity assessedIdentity2 = JunitTestHelper.createAndPersistIdentityAsRndUser("as-node-6b"); + RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry(); + // Assessment entry + AssessmentEntry ae = assessmentEntryDao.createAssessmentEntry(assessedIdentity1, null, entry, + null, Boolean.TRUE, null); + ae.setPassed(Boolean.FALSE); + ae = assessmentEntryDao.updateAssessmentEntry(ae); + // Overriden + AssessmentEntry aeOverriden = assessmentEntryDao.createAssessmentEntry(assessedIdentity2, null, entry, + null, Boolean.TRUE, null); + aeOverriden.setPassed(Boolean.FALSE); + aeOverriden = assessmentEntryDao.updateAssessmentEntry(aeOverriden); + aeOverriden.getPassedOverridable().override(Boolean.TRUE, coach, new Date()); + aeOverriden = assessmentEntryDao.updateAssessmentEntry(aeOverriden); + // Do not change assessment entries of other repository entries + RepositoryEntry entryOther = JunitTestHelper.createAndPersistRepositoryEntry(); + AssessmentEntry aeOther = assessmentEntryDao.createAssessmentEntry(assessedIdentity1, null, entryOther, + null, Boolean.TRUE, null); + aeOther.setPassed(Boolean.FALSE); + aeOther = assessmentEntryDao.updateAssessmentEntry(aeOther); + dbInstance.commitAndCloseSession(); + + assessmentEntryDao.resetAllRootPassed(entry); + dbInstance.commitAndCloseSession(); + + SoftAssertions softly = new SoftAssertions(); + ae = assessmentEntryDao.loadAssessmentEntryById(ae.getKey()); + softly.assertThat(ae.getPassed()).isNull(); + softly.assertThat(ae.getPassedOverridable().getCurrent()).isNull(); + aeOverriden = assessmentEntryDao.loadAssessmentEntryById(aeOverriden.getKey()); + softly.assertThat(aeOverriden.getPassedOverridable().getCurrent()).isEqualTo(Boolean.TRUE); + softly.assertThat(aeOverriden.getPassedOverridable().getOriginal()).isNull(); + softly.assertThat(aeOverriden.getPassedOverridable().getModBy()).isNotNull(); + softly.assertThat(aeOverriden.getPassedOverridable().getModDate()).isNotNull(); + aeOther = assessmentEntryDao.loadAssessmentEntryById(aeOther.getKey()); + softly.assertThat(aeOther.getPassed()).isNotNull(); + softly.assertThat(aeOther.getPassedOverridable().getCurrent()).isNotNull(); + softly.assertAll(); + } + + @Test + public void shouldResetOverridenAllRootPassed() { + Identity coach = JunitTestHelper.createAndPersistIdentityAsRndUser("coach"); + Identity assessedIdentity1 = JunitTestHelper.createAndPersistIdentityAsRndUser("as-node-6a"); + RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry(); + AssessmentEntry ae1 = assessmentEntryDao.createAssessmentEntry(assessedIdentity1, null, entry, + null, Boolean.TRUE, null); + ae1.setPassed(Boolean.FALSE); + ae1 = assessmentEntryDao.updateAssessmentEntry(ae1); + ae1.getPassedOverridable().override(Boolean.TRUE, coach, new Date()); + ae1 = assessmentEntryDao.updateAssessmentEntry(ae1); + // Do not change assessment entries of other repository entries + RepositoryEntry entryOther = JunitTestHelper.createAndPersistRepositoryEntry(); + AssessmentEntry aeOther = assessmentEntryDao.createAssessmentEntry(assessedIdentity1, null, entryOther, + null, Boolean.TRUE, null); + aeOther.setPassed(Boolean.FALSE); + aeOther = assessmentEntryDao.updateAssessmentEntry(aeOther); + aeOther.getPassedOverridable().override(Boolean.TRUE, coach, new Date()); + aeOther = assessmentEntryDao.updateAssessmentEntry(aeOther); + dbInstance.commitAndCloseSession(); + + assessmentEntryDao.resetAllOverridenRootPassed(entry); + dbInstance.commitAndCloseSession(); + + SoftAssertions softly = new SoftAssertions(); + ae1 = assessmentEntryDao.loadAssessmentEntryById(ae1.getKey()); + softly.assertThat(ae1.getPassedOverridable().getCurrent()).isEqualTo(Boolean.FALSE); + softly.assertThat(ae1.getPassedOverridable().getOriginal()).isNull(); + softly.assertThat(ae1.getPassedOverridable().getModBy()).isNull(); + softly.assertThat(ae1.getPassedOverridable().getModDate()).isNull(); + aeOther = assessmentEntryDao.loadAssessmentEntryById(aeOther.getKey()); + softly.assertThat(aeOther.getPassedOverridable().getCurrent()).isEqualTo(Boolean.TRUE); + softly.assertThat(aeOther.getPassedOverridable().getOriginal()).isNotNull(); + softly.assertThat(aeOther.getPassedOverridable().getModBy()).isNotNull(); + softly.assertThat(aeOther.getPassedOverridable().getModDate()).isNotNull(); + softly.assertAll(); + } @Test public void loadAssessmentEntries_subIdent() {