diff --git a/pom.xml b/pom.xml
index 674db7d34c91ed151337087d87f77b0883135d1d..dae72ed9aac30835d72b6ea83f65b2cad094cff4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -62,8 +62,8 @@
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<targetJdk>1.8</targetJdk>
-		<org.springframework.version>5.2.7.RELEASE</org.springframework.version>
-		<org.hibernate.version>5.4.18.Final</org.hibernate.version>
+		<org.springframework.version>5.2.8.RELEASE</org.springframework.version>
+		<org.hibernate.version>5.4.19.Final</org.hibernate.version>
 		<apache.cxf>3.3.7</apache.cxf>
 		<apache.pdfbox>2.0.20</apache.pdfbox>
 		<apache.poi>4.1.2</apache.poi>
@@ -73,11 +73,11 @@
 		<jackson.version>2.11.1</jackson.version>
 		<org.mysql.version>5.1.46</org.mysql.version>
 		<org.postgresql.version>42.2.14</org.postgresql.version>
-		<org.infinispan.version>11.0.0.Final</org.infinispan.version>
+		<org.infinispan.version>11.0.1.Final</org.infinispan.version>
 		<lucene.version>7.7.0</lucene.version>
 		<version.selenium>3.141.59</version.selenium>
 		<version.drone>2.5.1</version.drone>
-		<activemq.version>5.15.12</activemq.version>
+		<activemq.version>5.16.0</activemq.version>
 		<qtiworks.version>1.0.19</qtiworks.version>
 
 	    <!-- properties for testing and Q&A -->
@@ -99,9 +99,9 @@
 	    <test.env.db.oracle.host>localhost</test.env.db.oracle.host>
 	    <test.env.db.oracle.host.port>1521</test.env.db.oracle.host.port>
 	    <test.env.instance.id>myolat</test.env.instance.id>
-	    <test.env.jmx.rmi.port.0>3000</test.env.jmx.rmi.port.0>
 	    <test.env.webdriver.browser>chrome</test.env.webdriver.browser>
-	    <test.env.webdriver.chrome.version></test.env.webdriver.chrome.version>
+	    <test.env.webdriver.firefox.version>v0.27.0</test.env.webdriver.firefox.version>
+	    <test.env.webdriver.chrome.version>84.0.4147.30</test.env.webdriver.chrome.version>
 	    <test.env.webdriver.chrome.arguments></test.env.webdriver.chrome.arguments>
 	    <skipTests>true</skipTests>
 		<skipSeleniumTests>false</skipSeleniumTests>
@@ -1400,9 +1400,9 @@
 						<test.env.db.postgresql.host.name>${test.env.db.postgresql.host.name}</test.env.db.postgresql.host.name>
 						<test.env.db.postgresql.host.port>${test.env.db.postgresql.host.port}</test.env.db.postgresql.host.port>
 						<test.env.instance.id>${test.env.instance.id}</test.env.instance.id>
-						<test.env.jmx.rmi.port.0>${test.env.jmx.rmi.port.0}</test.env.jmx.rmi.port.0>
 						<arquillian.launch>tomcat-7-managed</arquillian.launch>
 						<webdriver.browser>${test.env.webdriver.browser}</webdriver.browser>
+						<webdriver.firefox.version>${test.env.webdriver.firefox.version}</webdriver.firefox.version>
 						<webdriver.chrome.version>${test.env.webdriver.chrome.version}</webdriver.chrome.version>
 						<webdriver.chrome.arguments>${test.env.webdriver.chrome.arguments}</webdriver.chrome.arguments>
 					</systemPropertyVariables>
diff --git a/src/main/java/org/olat/admin/user/UsermanagerUserSearchController.java b/src/main/java/org/olat/admin/user/UsermanagerUserSearchController.java
index 5f49300550629658ad85c20642b7d5e862fd6361..402ec0e58cd1d3f395d4a21af47ad0dfcf261c3b 100644
--- a/src/main/java/org/olat/admin/user/UsermanagerUserSearchController.java
+++ b/src/main/java/org/olat/admin/user/UsermanagerUserSearchController.java
@@ -76,6 +76,7 @@ public class UsermanagerUserSearchController extends BasicController implements
 
 	private final boolean showDelete;
 	private final boolean showEmailButton;
+	private final boolean showTableSearch;
 	private final boolean showStatusFilters;
 	private final boolean showOrganisationMove;
 	private final boolean isAdministrativeUser;
@@ -106,6 +107,7 @@ public class UsermanagerUserSearchController extends BasicController implements
 		showEmailButton = true;
 		showDelete = true;
 		showOrganisationMove = false;
+		showTableSearch = true;
 		
 		isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles());
 
@@ -131,12 +133,14 @@ public class UsermanagerUserSearchController extends BasicController implements
 	 * @param searchCreatedBefore
 	 */
 	public UsermanagerUserSearchController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackedPanel,
-			SearchIdentityParams predefinedQuery, boolean showEmailButton, boolean showOrganisationMove, boolean showDelete, boolean showStatusFilters) {
+			SearchIdentityParams predefinedQuery, boolean showEmailButton, boolean showOrganisationMove, boolean showDelete,
+			boolean showStatusFilters, boolean showTableSearch) {
 		super(ureq, wControl);
 		setTranslator(userManager.getPropertyHandlerTranslator(getTranslator()));
 		this.showDelete = showDelete;
 		this.stackedPanel = stackedPanel;
 		this.showEmailButton = showEmailButton;
+		this.showTableSearch = showTableSearch;
 		this.showStatusFilters = showStatusFilters;
 		this.showOrganisationMove = showOrganisationMove;
 
@@ -144,7 +148,7 @@ public class UsermanagerUserSearchController extends BasicController implements
 		isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles());
 		
 		tableCtr = new UserSearchTableController(ureq, getWindowControl(), stackedPanel,
-				UserSearchTableSettings.withVCard(showEmailButton, showOrganisationMove, showDelete, showStatusFilters));
+				UserSearchTableSettings.withVCard(showEmailButton, showOrganisationMove, showDelete, showStatusFilters, true));
 		listenTo(tableCtr);
 		tableCtr.loadModel(identityQueryParams);
 		putInitialPanel(tableCtr.getInitialComponent());
@@ -168,12 +172,13 @@ public class UsermanagerUserSearchController extends BasicController implements
 		this.stackedPanel = stackedPanel;
 		this.showEmailButton = showEmailButton;
 		showStatusFilters = false;
+		showTableSearch = false;
 		showOrganisationMove = false;
 		
 		isAdministrativeUser = securityModule.isUserAllowedAdminProps(ureq.getUserSession().getRoles());
 
 		tableCtr = new UserSearchTableController(ureq, getWindowControl(), stackedPanel,
-				UserSearchTableSettings.withVCard(showEmailButton, false, showDelete, true));
+				UserSearchTableSettings.withVCard(showEmailButton, false, showDelete, true, true));
 		listenTo(tableCtr);
 		tableCtr.loadModel(identitiesList);
 		
@@ -229,11 +234,11 @@ public class UsermanagerUserSearchController extends BasicController implements
 		searchState.setDelegate(states);
 		searchFormCtrl.setStateEntry(searchState);
 		
-		doPushSearch(ureq);
+		doPushSearch(ureq, showTableSearch);
 		tableCtr.activate(ureq, entries, null);
 	}
 	
-	private void doPushSearch(UserRequest ureq) {
+	private void doPushSearch(UserRequest ureq, boolean withTableSearch) {
 		identityQueryParams = searchFormCtrl.getSearchIdentityParams();
 		if(identityQueryParams.getOrganisations() == null || identityQueryParams.getOrganisations().isEmpty()) {
 			identityQueryParams.setOrganisations(manageableOrganisations);
@@ -243,7 +248,7 @@ public class UsermanagerUserSearchController extends BasicController implements
 		ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
 		WindowControl bwControl = addToHistory(ureq, ores, null);
 		tableCtr = new UserSearchTableController(ureq, bwControl, stackedPanel,
-				UserSearchTableSettings.withVCard(showEmailButton, showOrganisationMove, showDelete, showStatusFilters));
+				UserSearchTableSettings.withVCard(showEmailButton, showOrganisationMove, showDelete, showStatusFilters, withTableSearch));
 		listenTo(tableCtr);
 		tableCtr.loadModel(identityQueryParams);
 		stackedPanel.pushController("Results", tableCtr);
@@ -261,7 +266,7 @@ public class UsermanagerUserSearchController extends BasicController implements
 	public void event(UserRequest ureq, Controller source, Event event) {
 		if (source == searchFormCtrl) {
 			if (event == Event.DONE_EVENT) {
-				doPushSearch(ureq);
+				doPushSearch(ureq, false);
 			} else if (event == Event.CANCELLED_EVENT) {
 				fireEvent(ureq, Event.CANCELLED_EVENT);
 			}
diff --git a/src/main/java/org/olat/admin/user/UsermanagerUserSearchForm.java b/src/main/java/org/olat/admin/user/UsermanagerUserSearchForm.java
index 5f0679adfa33a5f23e80dfb0650b82487d42700a..4fd7d81ca08dcc7e44306a859ad5a8b9a68fad39 100644
--- a/src/main/java/org/olat/admin/user/UsermanagerUserSearchForm.java
+++ b/src/main/java/org/olat/admin/user/UsermanagerUserSearchForm.java
@@ -141,8 +141,8 @@ public class UsermanagerUserSearchForm extends FormBasicController {
 		statusValues = new String[] {
 				translate("rightsForm.status.activ"),
 				translate("rightsForm.status.permanent"),
-				translate("rightsForm.status.inactive"),
 				translate("rightsForm.status.pending"),
+				translate("rightsForm.status.inactive"),
 				translate("rightsForm.status.login_denied")
 		};
 		
diff --git a/src/main/java/org/olat/core/commons/services/jmx/_spring/jmxContext.xml b/src/main/java/org/olat/core/commons/services/jmx/_spring/jmxContext.xml
index 603ad7a412a6428ba1e68c41fb1268c55f04d59c..f7be7d25a78f79f055340ccca0ae066a98f9bd37 100644
--- a/src/main/java/org/olat/core/commons/services/jmx/_spring/jmxContext.xml
+++ b/src/main/java/org/olat/core/commons/services/jmx/_spring/jmxContext.xml
@@ -12,9 +12,5 @@
 	<bean id="org.springframework.jmx.support.MBeanServerFactoryBean" class="org.springframework.jmx.support.MBeanServerFactoryBean">
 		<property name="locateExistingServerIfPossible" value="true" />
 	</bean>
-	
-	<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean" lazy-init="true">
-	  <property name="port" value="${jmx.rmi.port}"/>
-	</bean>	
 
 </beans>
diff --git a/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java b/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java
index 6dafc3b23f2612069bc5d48c2e5f362dbd4c78d4..3a75af5f3e13367fa4db9f9cc1590ab565e7f4ce 100644
--- a/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java
+++ b/src/main/java/org/olat/core/gui/components/link/LinkRenderer.java
@@ -189,11 +189,11 @@ public class LinkRenderer extends DefaultComponentRenderer {
 					  .append(";\" ")
 					  .append("onclick=\"return o2cl_dirtyCheckOnly();\" ");
 				} else {
-					String href = StringHelper.containsNonWhitespace(link.getUrl()) ? link.getUrl() : "javascript:;";
+					boolean hasUrl = StringHelper.containsNonWhitespace(link.getUrl());
+					String href = hasUrl ? link.getUrl() : "javascript:;";
 					sb.append("href=\"").append(href).append("\" onclick=\"")
 					  .append(FormJSHelper.getJSFnCallFor(flexiLink.getRootForm(), elementId, 1))
-					  .append(";");
-					sb.append("\" ");
+					  .append("; ").append(" return false;", hasUrl).append("\" ");
 				}
 			} else if(link.isPopup()) {
 				try(StringOutput href = new StringOutput()) {
diff --git a/src/main/java/org/olat/course/assessment/ui/tool/IdentityListCourseNodeController.java b/src/main/java/org/olat/course/assessment/ui/tool/IdentityListCourseNodeController.java
index 26dc189640769fb5e0dabcd85232f33b1ec39535..d4edfa5628eda8489b69abc864d69bc1210be717 100644
--- a/src/main/java/org/olat/course/assessment/ui/tool/IdentityListCourseNodeController.java
+++ b/src/main/java/org/olat/course/assessment/ui/tool/IdentityListCourseNodeController.java
@@ -160,11 +160,11 @@ public class IdentityListCourseNodeController extends FormBasicController
 	private ContactFormController contactCtrl;
 	
 	@Autowired
-	private DB dbInstance;
+	protected DB dbInstance;
 	@Autowired
 	private UserManager userManager;
 	@Autowired
-	private BaseSecurity securityManager;
+	protected BaseSecurity securityManager;
 	@Autowired
 	private GradingService gradingService;
 	@Autowired
@@ -987,14 +987,14 @@ public class IdentityListCourseNodeController extends FormBasicController
 			ICourse course = CourseFactory.loadCourse(courseEntry);
 			for(AssessedIdentityElementRow row:rows) {
 				Identity assessedIdentity = securityManager.loadIdentityByKey(row.getIdentityKey());
-				doSetDone(assessedIdentity, courseNode, course);
+				doSetStatus(assessedIdentity, AssessmentEntryStatus.done, courseNode, course);
 				dbInstance.commitAndCloseSession();
 			}
 			loadModel(ureq);
 		}
 	}
 	
-	protected void doSetDone(Identity assessedIdentity, CourseNode courseNode, ICourse course) {
+	protected void doSetStatus(Identity assessedIdentity, AssessmentEntryStatus status, CourseNode courseNode, ICourse course) {
 		Roles roles = securityManager.getRoles(assessedIdentity);
 		
 		IdentityEnvironment identityEnv = new IdentityEnvironment(assessedIdentity, roles);
@@ -1003,11 +1003,10 @@ public class IdentityListCourseNodeController extends FormBasicController
 
 		ScoreEvaluation scoreEval = courseAssessmentService.getAssessmentEvaluation(courseNode, assessedUserCourseEnv);
 		ScoreEvaluation doneEval = new ScoreEvaluation(scoreEval.getScore(), scoreEval.getPassed(),
-				AssessmentEntryStatus.done, null, scoreEval.getCurrentRunCompletion(),
+				status, null, scoreEval.getCurrentRunCompletion(),
 				scoreEval.getCurrentRunStatus(), scoreEval.getAssessmentID());
 		courseAssessmentService.updateScoreEvaluation(courseNode, doneEval, assessedUserCourseEnv,
 				getIdentity(), false, Role.coach);
-		
 	}
 	
 	private void doUpdateCompletion(Double completion, AssessmentRunStatus status, Long assessedIdentityKey) {
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/GTAIdentityListCourseNodeController.java b/src/main/java/org/olat/course/nodes/gta/ui/GTAIdentityListCourseNodeController.java
index 45003a2fc389dfb666c4f834d4e718728ed5f8e1..096e1549a542e91d845325ef87d8766dbe4a81a1 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/GTAIdentityListCourseNodeController.java
+++ b/src/main/java/org/olat/course/nodes/gta/ui/GTAIdentityListCourseNodeController.java
@@ -56,6 +56,7 @@ import org.olat.group.BusinessGroup;
 import org.olat.modules.ModuleConfiguration;
 import org.olat.modules.assessment.AssessmentToolOptions;
 import org.olat.modules.assessment.Role;
+import org.olat.modules.assessment.model.AssessmentEntryStatus;
 import org.olat.modules.assessment.ui.AssessedIdentityElementRow;
 import org.olat.modules.assessment.ui.AssessmentToolContainer;
 import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
@@ -218,12 +219,12 @@ public class GTAIdentityListCourseNodeController extends IdentityListCourseNodeC
 	}
 
 	@Override
-	protected void doSetDone(Identity assessedIdentity, CourseNode assessableCourseNode, ICourse course) {
-		super.doSetDone(assessedIdentity, assessableCourseNode, course);
+	protected void doSetStatus(Identity assessedIdentity, AssessmentEntryStatus status, CourseNode assessableCourseNode, ICourse course) {
+		super.doSetStatus(assessedIdentity, status, assessableCourseNode, course);
 		
 		TaskList taskList = gtaManager.getTaskList(getCourseRepositoryEntry(), (GTACourseNode)assessableCourseNode);
 		Task task = gtaManager.getTask(assessedIdentity, taskList);
-		if(task != null) {
+		if(task != null && status == AssessmentEntryStatus.done) {
 			gtaManager.updateTask(task, TaskProcess.graded, (GTACourseNode)assessableCourseNode, false, getIdentity(), Role.coach);
 		}
 	}
diff --git a/src/main/java/org/olat/course/nodes/iq/ConfirmReopenAssessmentEntriesController.java b/src/main/java/org/olat/course/nodes/iq/ConfirmReopenAssessmentEntriesController.java
new file mode 100644
index 0000000000000000000000000000000000000000..e55c39aae8490d16bf0e185b9e0ea44363af4e1e
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/iq/ConfirmReopenAssessmentEntriesController.java
@@ -0,0 +1,91 @@
+package org.olat.course.nodes.iq;
+
+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.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;
+import org.olat.core.util.Util;
+import org.olat.ims.qti21.ui.ConfirmReopenAssessmentEntryController;
+
+/**
+ * 
+ * Initial date: 28 juil. 2020<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ConfirmReopenAssessmentEntriesController extends FormBasicController {
+	
+	private FormLink readOnlyButton;
+	
+	private Object userObject;
+	private final long numOfAssessmentEntriesDone;
+	
+	/**
+	 * Confirm reopen of the assessment entries .
+	 * 
+	 * @param ureq The user request
+	 * @param wControl The window control
+	 */
+	public ConfirmReopenAssessmentEntriesController(UserRequest ureq, WindowControl wControl, long numOfAssessmentEntriesDone) {
+		super(ureq, wControl, "confirm_reopen_assessments", Util
+				.createPackageTranslator(ConfirmReopenAssessmentEntryController.class, ureq.getLocale()));
+		this.numOfAssessmentEntriesDone = numOfAssessmentEntriesDone;
+		initForm(ureq);
+	}
+
+	public Object getUserObject() {
+		return userObject;
+	}
+
+	public void setUserObject(Object userObject) {
+		this.userObject = userObject;
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		if(formLayout instanceof FormLayoutContainer) {
+			FormLayoutContainer layoutCont = (FormLayoutContainer)formLayout;
+			String msg;
+			if(numOfAssessmentEntriesDone == 1) {
+				msg = translate("reopen.assessment.text");
+			} else {
+				msg = translate("reopen.assessments.text", new String[] { Long.toString(numOfAssessmentEntriesDone) });
+			}
+			layoutCont.contextPut("msg", msg);
+		}
+		
+		uifactory.addFormCancelButton("cancel", formLayout, ureq, getWindowControl());
+		uifactory.addFormSubmitButton("reopen.assessment", formLayout);
+		readOnlyButton = uifactory.addFormLink("correction.readonly", formLayout, Link.BUTTON);
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(readOnlyButton == source) {
+			fireEvent(ureq, Event.DONE_EVENT);
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		fireEvent(ureq, Event.CHANGED_EVENT);
+	}
+
+	@Override
+	protected void formCancelled(UserRequest ureq) {
+		fireEvent(ureq, Event.CANCELLED_EVENT);
+	}
+}
diff --git a/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java b/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
index a9ac1306653b2e38b3467dabb470e3a441443300..ee13d1c46a4b614976e46b6ee47d8993c0b300e2 100644
--- a/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
+++ b/src/main/java/org/olat/course/nodes/iq/IQIdentityListCourseNodeController.java
@@ -28,6 +28,8 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 import org.olat.basesecurity.GroupRoles;
 import org.olat.basesecurity.IdentityRef;
@@ -49,6 +51,8 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.closablewrapper.CloseableModalController;
 import org.olat.core.gui.media.MediaResource;
 import org.olat.core.id.Identity;
+import org.olat.course.CourseFactory;
+import org.olat.course.ICourse;
 import org.olat.course.archiver.ScoreAccountingHelper;
 import org.olat.course.assessment.AssessmentHelper;
 import org.olat.course.assessment.CourseAssessmentService;
@@ -118,6 +122,7 @@ public class IQIdentityListCourseNodeController extends IdentityListCourseNodeCo
 	private ConfirmExtraTimeController extraTimeCtrl;
 	private ValidationXmlSignatureController validationCtrl;
 	private CorrectionOverviewController correctionIdentitiesCtrl;
+	private ConfirmReopenAssessmentEntriesController reopenForCorrectionCtrl;
 	
 	private boolean modelDirty = false;
 
@@ -340,6 +345,16 @@ public class IQIdentityListCourseNodeController extends IdentityListCourseNodeCo
 			} else if(event == Event.DONE_EVENT) {
 				loadModel(ureq);
 			}
+		} else if(reopenForCorrectionCtrl == source) {
+			CorrectionOverviewController correctionCtrl = (CorrectionOverviewController)reopenForCorrectionCtrl.getUserObject();
+			cmc.deactivate();
+			cleanUp();
+			if(event == Event.CHANGED_EVENT) {
+				doReopenAssessmentEntries(correctionCtrl);
+				doOpenCorrection(correctionCtrl);
+			} else if(event == Event.DONE_EVENT) {
+				doOpenCorrection(correctionCtrl);
+			}
 		}
 		super.event(ureq, source, event);
 	}
@@ -367,10 +382,12 @@ public class IQIdentityListCourseNodeController extends IdentityListCourseNodeCo
 	
 	@Override
 	protected void cleanUp() {
+		removeAsListenerAndDispose(reopenForCorrectionCtrl);
 		removeAsListenerAndDispose(retrieveConfirmationCtr);
 		removeAsListenerAndDispose(validationCtrl);
 		removeAsListenerAndDispose(extraTimeCtrl);
 		removeAsListenerAndDispose(resetDataCtrl);
+		reopenForCorrectionCtrl = null;
 		retrieveConfirmationCtr = null;
 		validationCtrl = null;
 		extraTimeCtrl = null;
@@ -431,14 +448,51 @@ public class IQIdentityListCourseNodeController extends IdentityListCourseNodeCo
 	private void doStartCorrection(UserRequest ureq) {
 		AssessmentToolOptions asOptions = getOptions();
 
-		correctionIdentitiesCtrl = new CorrectionOverviewController(ureq, getWindowControl(), stackPanel,
+		CorrectionOverviewController correctionCtrl = new CorrectionOverviewController(ureq, getWindowControl(), stackPanel,
 				getCourseEnvironment(), asOptions, (IQTESTCourseNode)courseNode);
-		if(correctionIdentitiesCtrl.getNumberOfAssessedIdentities() == 0) {
+		long numOfAssessmentEntriesDone = usersTableModel.getObjects().stream()
+				.filter(row -> row.getAssessmentStatus() == AssessmentEntryStatus.done)
+				.count();
+		if(correctionCtrl.getNumberOfAssessedIdentities() == 0) {
 			showWarning("grade.nobody");
-			correctionIdentitiesCtrl = null;
+		} else if(numOfAssessmentEntriesDone > 0) {
+			doReopenForCorrection(ureq, correctionCtrl, numOfAssessmentEntriesDone);
 		} else {
-			listenTo(correctionIdentitiesCtrl);
-			stackPanel.pushController(translate("correction.test.title"), correctionIdentitiesCtrl);
+			doOpenCorrection(correctionCtrl);
+		}
+	}
+	
+	private void doOpenCorrection(CorrectionOverviewController correctionCtrl) {
+		correctionIdentitiesCtrl = correctionCtrl;
+		listenTo(correctionIdentitiesCtrl);
+		stackPanel.pushController(translate("correction.test.title"), correctionIdentitiesCtrl);
+	}
+	
+	private void doReopenForCorrection(UserRequest ureq, CorrectionOverviewController correctionCtrl, long numOfAssessmentEntriesDone) {
+		if(guardModalController(reopenForCorrectionCtrl)) return;
+		
+		reopenForCorrectionCtrl = new ConfirmReopenAssessmentEntriesController(ureq, getWindowControl(), numOfAssessmentEntriesDone);
+		reopenForCorrectionCtrl.setUserObject(correctionCtrl);
+		listenTo(reopenForCorrectionCtrl);
+		
+		cmc = new CloseableModalController(getWindowControl(), "close", reopenForCorrectionCtrl.getInitialComponent(),
+				true, translate("reopen.assessments.title"));
+		cmc.activate();
+		listenTo(cmc);
+	}
+	
+	private void doReopenAssessmentEntries(CorrectionOverviewController correctionCtrl) {
+		List<Identity> assessedIdentities = correctionCtrl.getAssessedIdentities();
+		Set<Long> assessedIdentitiesKeys = assessedIdentities.stream()
+				.map(Identity::getKey)
+				.collect(Collectors.toSet());
+		List<AssessedIdentityElementRow> rows = usersTableModel.getObjects();
+		ICourse course = CourseFactory.loadCourse(courseEntry);
+		for(AssessedIdentityElementRow row:rows) {
+			if(row.getAssessmentStatus() == AssessmentEntryStatus.done && assessedIdentitiesKeys.contains(row.getIdentityKey())) {
+				Identity assessedIdentity = securityManager.loadIdentityByKey(row.getIdentityKey());
+				doSetStatus(assessedIdentity, AssessmentEntryStatus.inReview, courseNode, course);
+				dbInstance.commitAndCloseSession();			}
 		}
 	}
 	
diff --git a/src/main/java/org/olat/course/nodes/iq/QTI21IdentityListCourseNodeToolsController.java b/src/main/java/org/olat/course/nodes/iq/QTI21IdentityListCourseNodeToolsController.java
index 3ab1ce192cc5359a9d8d7428f4afbca88aa21f6e..55e25c7eec57f30f7b27202fbefeea05564c700b 100644
--- a/src/main/java/org/olat/course/nodes/iq/QTI21IdentityListCourseNodeToolsController.java
+++ b/src/main/java/org/olat/course/nodes/iq/QTI21IdentityListCourseNodeToolsController.java
@@ -47,6 +47,7 @@ import org.olat.ims.qti21.model.jpa.AssessmentTestSessionStatistics;
 import org.olat.ims.qti21.model.xml.ManifestBuilder;
 import org.olat.ims.qti21.ui.AssessmentTestDisplayController;
 import org.olat.ims.qti21.ui.AssessmentTestSessionComparator;
+import org.olat.ims.qti21.ui.ConfirmReopenAssessmentEntryController;
 import org.olat.ims.qti21.ui.QTI21ResetDataController;
 import org.olat.ims.qti21.ui.QTI21RetrieveTestsController;
 import org.olat.ims.qti21.ui.assessment.CorrectionIdentityAssessmentItemListController;
@@ -82,6 +83,7 @@ public class QTI21IdentityListCourseNodeToolsController extends AbstractToolsCon
 	private ConfirmExtraTimeController extraTimeCtrl;
 	private QTI21RetrieveTestsController retrieveConfirmationCtr;
 	private CorrectionIdentityAssessmentItemListController correctionCtrl;
+	private ConfirmReopenAssessmentEntryController reopenForCorrectionCtrl;
 	
 	private RepositoryEntry testEntry;
 	private RepositoryEntry courseEntry;
@@ -166,7 +168,7 @@ public class QTI21IdentityListCourseNodeToolsController extends AbstractToolsCon
 	protected void event(UserRequest ureq, Component source, Event event) {
 		if(correctionLink == source) {
 			fireEvent(ureq, Event.CLOSE_EVENT);
-			doOpenCorrection(ureq);
+			doCorrection(ureq);
 		} else if(pullTestLink == source) {
 			fireEvent(ureq, Event.CLOSE_EVENT);
 			doConfirmPullSession(ureq, lastSession);
@@ -203,6 +205,10 @@ public class QTI21IdentityListCourseNodeToolsController extends AbstractToolsCon
 			cmc.deactivate();
 			cleanUp();
 			fireAlteredEvent(ureq, event);
+		} else if(reopenForCorrectionCtrl == source) {
+			cmc.deactivate();
+			cleanUp();
+			doOpenCorrection(ureq);
 		} else if(cmc == source) {
 			cleanUp();
 			fireEvent(ureq, Event.CHANGED_EVENT);
@@ -221,17 +227,42 @@ public class QTI21IdentityListCourseNodeToolsController extends AbstractToolsCon
 	}
 	
 	private void cleanUp() {
+		removeAsListenerAndDispose(reopenForCorrectionCtrl);
 		removeAsListenerAndDispose(correctionCtrl);
 		removeAsListenerAndDispose(extraTimeCtrl);
 		removeAsListenerAndDispose(resetDataCtrl);
 		removeAsListenerAndDispose(cmc);
+		reopenForCorrectionCtrl = null;
 		correctionCtrl = null;
 		extraTimeCtrl = null;
 		resetDataCtrl = null;
 		cmc = null;
 	}
 	
+	private void doCorrection(UserRequest ureq) {
+		boolean assessmentEntryDone = isAssessementEntryDone();
+		if(assessmentEntryDone) {
+			doReopenForCorrection(ureq);
+		} else {
+			doOpenCorrection(ureq);
+		}	
+	}
+	
+	private void doReopenForCorrection(UserRequest ureq) {
+		if(guardModalController(reopenForCorrectionCtrl)) return;
+		
+		reopenForCorrectionCtrl = new ConfirmReopenAssessmentEntryController(ureq, getWindowControl(),
+				assessedUserCourseEnv, (IQTESTCourseNode)courseNode, null);
+		listenTo(reopenForCorrectionCtrl);
+		
+		cmc = new CloseableModalController(getWindowControl(), "close", reopenForCorrectionCtrl.getInitialComponent(),
+				true, translate("reopen.assessment.title"));
+		cmc.activate();
+		listenTo(cmc);
+	}
+	
 	private void doOpenCorrection(UserRequest ureq) {
+		boolean assessmentEntryDone = isAssessementEntryDone();
 		File unzippedDirRoot = FileResourceManager.getInstance().unzipFileResource(testEntry.getOlatResource());
 		ResolvedAssessmentTest resolvedAssessmentTest = qtiService.loadAndResolveAssessmentTest(unzippedDirRoot, false, false);
 		ManifestBuilder manifestBuilder = ManifestBuilder.read(new File(unzippedDirRoot, "imsmanifest.xml"));
@@ -242,8 +273,8 @@ public class QTI21IdentityListCourseNodeToolsController extends AbstractToolsCon
 		testSessionStates.put(assessedIdentity, testSessionState);
 		CorrectionOverviewModel model = new CorrectionOverviewModel(courseEntry, testCourseNode, testEntry,
 				resolvedAssessmentTest, manifestBuilder, lastSessionMap, testSessionStates);
-		boolean readOnly = isAssessementEntryDone();
-		correctionCtrl = new CorrectionIdentityAssessmentItemListController(ureq, getWindowControl(), stackPanel, model, assessedIdentity, readOnly);
+		
+		correctionCtrl = new CorrectionIdentityAssessmentItemListController(ureq, getWindowControl(), stackPanel, model, assessedIdentity, assessmentEntryDone);
 		listenTo(correctionCtrl);
 		stackPanel.pushController(translate("tool.correction"), correctionCtrl);
 	}
diff --git a/src/main/java/org/olat/course/nodes/iq/_content/confirm_reopen_assessments.html b/src/main/java/org/olat/course/nodes/iq/_content/confirm_reopen_assessments.html
new file mode 100644
index 0000000000000000000000000000000000000000..0cd82652d95a867088a188d4a620f6ce59640c16
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/iq/_content/confirm_reopen_assessments.html
@@ -0,0 +1,10 @@
+<p>$msg</p>
+<div class="o_button_group">
+	$r.render("cancel")
+	#if($r.available("reopen.assessment")) 
+		$r.render("reopen.assessment")
+	#end
+	#if($r.available("correction.readonly")) 
+		$r.render("correction.readonly")
+	#end
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
index 527bd3b57337a6d2ea872f1649c49f1797e7b085..1d4cac49fff98e854bfc3c988570ed2b1bd5c6c7 100644
--- a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_de.properties
@@ -165,6 +165,9 @@ qti.form.test.date.confirm=W\u00E4hrend dem Testzeitraum kann der Test gestartet
 qti.form.test.date.help=$\:qti.form.test.date.confirm
 qti.form.test.title=Test
 reopen=Erneut starten
+reopen.assessments.title=Abgeschlossene Bewertungen wieder \u00F6ffnen
+reopen.assessment.text=Es gibt bereits eine abgeschlossene Bewertung. Wollen Sie sie wieder\u00F6ffnen , um den Test erneut zu korrigieren?
+reopen.assessments.text=Es gibt bereits {0} abgeschlossene Bewertungen. Wollen Sie diese wieder \u00F6ffnen, um die Tests erneut zu korrigieren?
 reopen.explanation=Dieser Test wurde beendet. Sie k\u00F6nnen den Test erneut starten. Der Testteilnehmende kann den Test dann dort weiterf\u00FChren, wo er aufgeh\u00F6rt hat. Falls der Test auf 1 Versuch beschr\u00E4nkt ist, m\u00FCssen au�erdem die Versuche zur\u00FCckgesetzt werden, damit der Testteilnehmende den Test weiterf\u00FChren kann.
 reopen.test=Beendeten Test wieder \u00F6ffnen
 replace.wizard.information.empty.results=<b>HINWEIS\: Dieser Test/Fragebogen wurde bereits von {0} Teilnehmer(n) begonnen\!</b> Die bisherigen Ergebnisse dieser Nutzer werden mit Klick auf "Fertigstellen" im n\u00E4chsten Schritt gel\u00F6scht.<br /><br /><b>Publizieren Sie schnellstm\u00F6glich Ihren Kurs\!</b> Erst nach dem Publizieren des Kurses k\u00F6nnen die Kursteilnehmer den neu zugeordneten Test/Fragebogen starten und entsprechende Ergebnisse gespeichert werden.
diff --git a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
index dda05daef0a8f2530d558ef06b68e41c7091e845..b15c85fb0b0194f74f6c71a0d2342dcab5ddbc73 100644
--- a/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/iq/_i18n/LocalStrings_en.properties
@@ -166,6 +166,9 @@ qti.form.test.date.confirm=During the test  period the test can be started. As s
 qti.form.test.date.help=$\:qti.form.test.date.confirm
 qti.form.test.title=Test
 reopen=Start again
+reopen.assessments.title=Reopen closed assessments
+reopen.assessment.text=There are already a closed assessment. Do you want to reopen it to correct the test again?
+reopen.assessments.text=There are already {0} closed assessments. Do you want to reopen them to correct the tests again?
 reopen.explanation=This test has been finished. You can restart the test. The test participant continues the test where he left it. If the test is limited to 1 attempt, the number of attempts must be reset so the test participants can continue the test.
 reopen.test=Reopen finished test
 replace.wizard.information.empty.results=<b>NOTE\: This test/questionnaire has already been launched by {0} participant(s)\!</b> All user results already existing will be deleted by clicking next on "Finish".<br></br><b>Please publish your course as soon as possible\!</b> Only after publishing will course participants be able to launch your newly assigned test/questionnaire; any results can then be saved accordingly.
diff --git a/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java b/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
index 24701e45fb996f6b05b9c0a58b1e86931753cfb8..b4e8b89994989dce9396e80020ee9b7c00868968 100644
--- a/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
+++ b/src/main/java/org/olat/ims/qti21/manager/QTI21StatisticsManagerImpl.java
@@ -112,7 +112,8 @@ public class QTI21StatisticsManagerImpl implements QTI21StatisticsManager {
 		}
 		
 		sb.append(" and asession.lastModified = (select max(a2session.lastModified) from qtiassessmenttestsession a2session")
-		  .append("   where asession.testEntry.key=a2session.testEntry.key and a2session.repositoryEntry.key=asession.repositoryEntry.key");
+		  .append("   where asession.testEntry.key=a2session.testEntry.key and a2session.repositoryEntry.key=asession.repositoryEntry.key")
+		  .append("   and a2session.exploded=false and a2session.cancelled=false");
 		if(searchParams.getNodeIdent() != null ) {
 			sb.append(" and a2session.subIdent=asession.subIdent");
 		} else {
diff --git a/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java b/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
index 67c2a398c3d923c7ea306535610e798d02ba0373..7c713bae5f03383437c350772832505e6aa54d04 100644
--- a/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
+++ b/src/main/java/org/olat/ims/qti21/questionimport/CSVToAssessmentItemConverter.java
@@ -97,6 +97,7 @@ public class CSVToAssessmentItemConverter {
 	public void parse(String input) {
 		List<String[]> lines = getLines(input);
 		for(String[] line:lines) {
+			currentLine++;
 			processLine(line);
 		}
 		buildCurrentItem();
diff --git a/src/main/java/org/olat/ims/qti21/ui/ConfirmReopenAssessmentEntryController.java b/src/main/java/org/olat/ims/qti21/ui/ConfirmReopenAssessmentEntryController.java
new file mode 100644
index 0000000000000000000000000000000000000000..c73f98c61812e2fc5e81911723ca7e4e3615c51f
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/ConfirmReopenAssessmentEntryController.java
@@ -0,0 +1,144 @@
+package org.olat.ims.qti21.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.impl.FormBasicController;
+import org.olat.core.gui.components.form.flexible.impl.FormEvent;
+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;
+import org.olat.course.assessment.CourseAssessmentService;
+import org.olat.course.nodes.IQTESTCourseNode;
+import org.olat.course.run.scoring.ScoreEvaluation;
+import org.olat.course.run.userview.UserCourseEnvironment;
+import org.olat.ims.qti21.AssessmentTestSession;
+import org.olat.modules.assessment.AssessmentEntry;
+import org.olat.modules.assessment.AssessmentService;
+import org.olat.modules.assessment.Role;
+import org.olat.modules.assessment.model.AssessmentEntryStatus;
+import org.olat.repository.RepositoryEntry;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 28 juil. 2020<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class ConfirmReopenAssessmentEntryController extends FormBasicController {
+	
+	private FormLink readOnlyButton;
+	
+	private Object userObject;
+	private final IQTESTCourseNode courseNode;
+	private final AssessmentTestSession session;
+	private final UserCourseEnvironment assessedUserCourseEnv;
+	
+	@Autowired
+	private AssessmentService assessmentService;
+	@Autowired
+	private CourseAssessmentService courseAssessmentService;
+	
+	/**
+	 * Confirm reopen of the assessment in a course element.
+	 * 
+	 * @param ureq The user request
+	 * @param wControl The window control
+	 * @param assessedUserCourseEnv The user course environment of the assessed identity
+	 * @param courseNode The course node
+	 * @param session The assessment test session
+	 */
+	public ConfirmReopenAssessmentEntryController(UserRequest ureq, WindowControl wControl,
+			UserCourseEnvironment assessedUserCourseEnv, IQTESTCourseNode courseNode,
+			AssessmentTestSession session) {
+		super(ureq, wControl, "confirm_reopen_assessment");
+		this.assessedUserCourseEnv = assessedUserCourseEnv;
+		this.courseNode = courseNode;
+		this.session = session;
+		initForm(ureq);
+	}
+	
+	/**
+	 * Confirm reopen of the assessment of test done within a test
+	 * repository entry.
+	 * 
+	 * @param ureq The user request
+	 * @param wControl The window control
+	 * @param session The assessment test session
+	 */
+	public ConfirmReopenAssessmentEntryController(UserRequest ureq, WindowControl wControl,
+			AssessmentTestSession session) {
+		super(ureq, wControl, "confirm_reopen_assessment");
+		assessedUserCourseEnv = null;
+		courseNode = null;
+		this.session = session;
+		initForm(ureq);
+	}
+	
+	public AssessmentTestSession getAssessmentTestSession() {
+		return session;
+	}
+
+	public Object getUserObject() {
+		return userObject;
+	}
+
+	public void setUserObject(Object userObject) {
+		this.userObject = userObject;
+	}
+
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		
+		uifactory.addFormCancelButton("cancel", formLayout, ureq, getWindowControl());
+		uifactory.addFormSubmitButton("reopen.assessment", formLayout);
+		readOnlyButton = uifactory.addFormLink("correction.readonly", formLayout, Link.BUTTON);
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if(readOnlyButton == source) {
+			fireEvent(ureq, Event.DONE_EVENT);
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		doReopen();
+		fireEvent(ureq, Event.CHANGED_EVENT);
+	}
+
+	@Override
+	protected void formCancelled(UserRequest ureq) {
+		fireEvent(ureq, Event.CANCELLED_EVENT);
+	}
+	
+	private void doReopen() {
+		if(courseNode != null) {
+			ScoreEvaluation scoreEval = assessedUserCourseEnv.getScoreAccounting().evalCourseNode(courseNode);
+			if (scoreEval != null) {
+				ScoreEvaluation reopenedEval = new ScoreEvaluation(scoreEval.getScore(), scoreEval.getPassed(),
+						AssessmentEntryStatus.inReview, scoreEval.getUserVisible(), scoreEval.getCurrentRunCompletion(),
+						scoreEval.getCurrentRunStatus(), scoreEval.getAssessmentID());
+				courseAssessmentService.updateScoreEvaluation(courseNode, reopenedEval, assessedUserCourseEnv,
+						getIdentity(), false, Role.coach);
+			}
+		} else if(session != null) {
+			RepositoryEntry testEntry = session.getTestEntry();
+			AssessmentEntry assessmentEntry = assessmentService.loadAssessmentEntry(session.getIdentity(), testEntry, null, testEntry);
+			if (assessmentEntry != null) {
+				assessmentEntry.setAssessmentStatus(AssessmentEntryStatus.inReview);
+				assessmentService.updateAssessmentEntry(assessmentEntry);
+			}
+		}
+	}
+}
diff --git a/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java b/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java
index 9c7a4af6a4961cce0f7686bd2f16110170fcb885..13726e65851ed647ebaad90c387a1bcedbf40e44 100644
--- a/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentDetailsController.java
@@ -143,6 +143,7 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 	private DialogBoxController retrieveConfirmationCtr;
 	private CloseableCalloutWindowController calloutCtrl;
 	private CorrectionIdentityAssessmentItemListController correctionCtrl;
+	private ConfirmReopenAssessmentEntryController reopenForCorrectionCtrl;
 	private ConfirmAssessmentTestSessionInvalidationController invalidateConfirmationCtr;
 	private ConfirmAssessmentTestSessionRevalidationController revalidateConfirmationCtr;
 
@@ -376,6 +377,15 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 			}
 			cmc.deactivate();
 			cleanUp();
+		} else if(reopenForCorrectionCtrl == source) {
+			cmc.deactivate();
+			AssessmentTestSession session = reopenForCorrectionCtrl.getAssessmentTestSession();
+			cleanUp();
+			if(event == Event.DONE_EVENT || event == Event.CHANGED_EVENT) {
+				fireEvent(ureq, Event.CHANGED_EVENT);
+				AssessmentTestSession testSession = qtiService.getAssessmentTestSession(session.getKey());
+				doOpenCorrection(ureq, testSession);
+			}
 		} else if(toolsCtrl == source) {
 			if(event == Event.DONE_EVENT) {
 				calloutCtrl.deactivate();
@@ -389,6 +399,7 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 		removeAsListenerAndDispose(invalidateConfirmationCtr);
 		removeAsListenerAndDispose(revalidateConfirmationCtr);
 		removeAsListenerAndDispose(retrieveConfirmationCtr);
+		removeAsListenerAndDispose(reopenForCorrectionCtrl);
 		removeAsListenerAndDispose(correctionCtrl);
 		removeAsListenerAndDispose(resetToolCtrl);
 		removeAsListenerAndDispose(calloutCtrl);
@@ -398,6 +409,7 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 		invalidateConfirmationCtr = null;
 		revalidateConfirmationCtr = null;
 		retrieveConfirmationCtr = null;
+		reopenForCorrectionCtrl = null;
 		correctionCtrl = null;
 		resetToolCtrl = null;
 		calloutCtrl = null;
@@ -443,6 +455,16 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 	}
 
 	private void doCorrection(UserRequest ureq, AssessmentTestSession session) {
+		boolean assessmentEntryDone = isAssessmentEntryDone();
+		if(assessmentEntryDone && !readOnly) {
+			confirmReopenAssessment(ureq, session);
+		} else {
+			doOpenCorrection(ureq, session);
+		}
+	}
+	
+	private void doOpenCorrection(UserRequest ureq, AssessmentTestSession session) {
+		boolean assessmentEntryDone = isAssessmentEntryDone();
 		RepositoryEntry testEntry = session.getTestEntry();
 		File unzippedDirRoot = FileResourceManager.getInstance().unzipFileResource(testEntry.getOlatResource());
 		ResolvedAssessmentTest resolvedAssessmentTest = qtiService.loadAndResolveAssessmentTest(unzippedDirRoot, false, false);
@@ -454,11 +476,11 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 			lastSessions.put(assessedIdentity, session);
 			Map<Identity, TestSessionState> testSessionStates = new HashMap<>();
 			testSessionStates.put(assessedIdentity, testSessionState);
-			boolean assessmentEntryDone = isCorrectionReadOnly();
+			boolean correctionReadOnly = readOnly || assessmentEntryDone;
 			CorrectionOverviewModel model = new CorrectionOverviewModel(entry, courseNode, testEntry,
 					resolvedAssessmentTest, manifestBuilder, lastSessions, testSessionStates);
 			correctionCtrl = new CorrectionIdentityAssessmentItemListController(ureq, getWindowControl(), stackPanel,
-					model, assessedIdentity, assessmentEntryDone);
+					model, assessedIdentity, correctionReadOnly);
 			listenTo(correctionCtrl);
 			stackPanel.pushController(translate("correction"), correctionCtrl);
 		} catch(Exception e) {
@@ -467,9 +489,20 @@ public class QTI21AssessmentDetailsController extends FormBasicController {
 		}
 	}
 	
-	private boolean isCorrectionReadOnly() {
-		if(readOnly) return true;
+	private void confirmReopenAssessment(UserRequest ureq, AssessmentTestSession session) {
+		if(guardModalController(reopenForCorrectionCtrl)) return;
 		
+		reopenForCorrectionCtrl = new ConfirmReopenAssessmentEntryController(ureq, getWindowControl(),
+				assessedUserCourseEnv, courseNode, session);
+		listenTo(reopenForCorrectionCtrl);
+		
+		cmc = new CloseableModalController(getWindowControl(), "close", reopenForCorrectionCtrl.getInitialComponent(),
+				true, translate("reopen.assessment.title"));
+		cmc.activate();
+		listenTo(cmc);
+	}
+	
+	private boolean isAssessmentEntryDone() {
 		if(assessedUserCourseEnv != null) {
 			AssessmentEvaluation eval = assessedUserCourseEnv.getScoreAccounting().getScoreEvaluation(courseNode);
 			return eval != null && eval.getAssessmentStatus() == AssessmentEntryStatus.done;
diff --git a/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentTestSessionTableModel.java b/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentTestSessionTableModel.java
index 957c7468deb6692010114d97854b803054ed65f2..58e84e16da80e5c2ff702f68ce1cf5b61c80a228 100644
--- a/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentTestSessionTableModel.java
+++ b/src/main/java/org/olat/ims/qti21/ui/QTI21AssessmentTestSessionTableModel.java
@@ -122,17 +122,19 @@ public class QTI21AssessmentTestSessionTableModel extends DefaultFlexiTableDataM
 				}
 				return "";
 			}
-			case open: {
-				Date finished = session.getTestSession().getFinishTime();
-				return finished == null ? Boolean.FALSE : Boolean.TRUE;
-			}
+			case open: return Boolean.valueOf(!isTestSessionOpen(session));
 			case correction: return (lastSession != null && lastSession.equals(session.getTestSession()));
-			case invalidate: return !session.getTestSession().isCancelled() && !session.getTestSession().isExploded();
+			case invalidate: return !isTestSessionOpen(session) && !session.getTestSession().isCancelled() && !session.getTestSession().isExploded();
 			case tools: return session.getToolsLink();
 			default: return "ERROR";
 		}
 	}
 	
+	private boolean isTestSessionOpen(QTI21AssessmentTestSessionDetails session) {
+		Date finished = session.getTestSession().getFinishTime();
+		return finished == null;
+	}
+	
 	private Date getTerminationTime(QTI21AssessmentTestSessionDetails session) {
 		Date endTime = session.getTestSession().getTerminationTime();
 		if(endTime == null) {
diff --git a/src/main/java/org/olat/ims/qti21/ui/_content/confirm_reopen_assessment.html b/src/main/java/org/olat/ims/qti21/ui/_content/confirm_reopen_assessment.html
new file mode 100644
index 0000000000000000000000000000000000000000..13beba566959a8d9a4d4834b9276d1083f60a7ae
--- /dev/null
+++ b/src/main/java/org/olat/ims/qti21/ui/_content/confirm_reopen_assessment.html
@@ -0,0 +1,10 @@
+<p>$r.translate("reopen.assessment.text")</p>
+<div class="o_button_group">
+	$r.render("cancel")
+	#if($r.available("reopen.assessment")) 
+		$r.render("reopen.assessment")
+	#end
+	#if($r.available("correction.readonly")) 
+		$r.render("correction.readonly")
+	#end
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties
index 05ce41e31d1efeada125d023bd510f404f55dc96..1ed94bcc933a5d3469ddc5b42aead40a3542d85d 100644
--- a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_de.properties
@@ -80,6 +80,7 @@ confirm.suspend.test=$org.olat.modules.iq\:confirmSuspend
 confirmation=Best\u00E4tigung
 correct.solution=Korrekte L\u00F6sung
 correction=Korrigieren
+correction.readonly=Korrektur nur sehen
 correction.workflow=Korrekturworkflow
 correction.workflow.anonymous=Anonym
 countdown.running=Zeitlimit {1} Sekunden\: nur <strong>{0} Sekunden \u00FCbrigs</strong>
@@ -143,7 +144,7 @@ interaction.order.target=Ziel
 invalidate=Annullieren
 invalidate.overwrite=Annullieren und Resultat \u00FCbertragen
 invalidate.test.confirm.title=Annullieren
-invalidate.test.confirm.text=Wollen Sie den Test Session ung\u00FCltig machen? Die Daten werden nicht gel\u00F6scht.
+invalidate.test.confirm.text=Wollen Sie diese Test-Session als ung\u00FCltig markieren? Die Daten werden nicht gel\u00F6scht.
 item.comment=Kommentar
 kprim.minus=Falsch
 kprim.plus=Richtig
@@ -193,6 +194,9 @@ question.progress.noMaxScore=$org.olat.modules.iq\:noMaxScore
 question.progress.score=$org.olat.modules.iq\:actualPoints
 question.title=Frage {0}
 questions=Anzahl Fragen im Test
+reopen.assessment=Bewertung wiederöffnen
+reopen.assessment.title=Abgeschlossene Bewertung wieder \u00F6ffnen
+reopen.assessment.text=Diese Bewertung ist bereits abgeschlossen. Wollen Sie sie wieder \u00F6ffnen, um den Test erneut zu korrigieren?
 reset.data=Daten zur\u00FCcksetzen
 reset.test.data.acknowledge=Ich verstehe, dass die Daten endg\u00FCltig gel\u00F6scht werden.
 reset.test.data.text=Wollen Sie wirklich alle Daten von dem Test zur\u00FCcksetzen? Die Resultate von <strong>{0} Benutzern</strong> werden definitiv gel\u00F6scht.
@@ -290,8 +294,8 @@ upload.explanation=Datei auf lokalem Computer f\u00FCr \u00DCbertragung w\u00E4h
 validate.xml.signature=Testquittung validieren
 validate.xml.signature.file=XML Datei
 validate.xml.signature.ok=Testquittung und Datei konnte erfolgreich validiert werden.
-warning.assignment.done=Korrektur von diesem Test ist abgeschlossen. Wenn dieser Test ung\u00FCltig gemachen wird, werden alle Korrekturen verloren.
-warning.assignment.inProcess=Korrektur von diesem Test wurde angefangen. Wenn dieser Test ung\u00FCltig gemachen wird, werden alle Korrekturen verloren.
+warning.assignment.done=Die Korrektur dieses Tests ist bereits abgeschlossen. Wird diese Test-Session als ung\u00FCltig markiert (annulliert) wird, so gehen alle bestehenden Korrekturen verloren.
+warning.assignment.inProcess=Dieser Test befindet sich bereits in Korrektur. Wird diese Test-Session als ung\u00FCltig markiert (annulliert), so gehen alle Korrekturen verloren.
 warning.download.log=Es gibt leider kein Logdatei f\u00FCr diesen Test.
 warning.reset.assessmenttest.data=Die Test-Resultate wurden von einem Administrator oder Kursbesitzer zur\u00FCckgesetzt. Sie k\u00F6nnen den Test nicht fortsetzen und m\u00FCssen ihn erneut starten.
 warning.reset.test.data.nobody=Es gibt kein Teilnehmer zu zur\u00FCcksetzen
diff --git a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties
index bae8ed6dd36fad24cbb3e0570165d4393570c17d..5be1eefe82d97c31922a55c2be17deab204ec26f 100644
--- a/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/_i18n/LocalStrings_en.properties
@@ -80,6 +80,7 @@ confirm.suspend.test=$org.olat.modules.iq\:confirmSuspend
 confirmation=Confirmation
 correct.solution=Correct solution
 correction=Grade
+correction.readonly=See correction read only
 correction.workflow=Correction workflow
 correction.workflow.anonymous=Anonymous
 countdown.running=Time limit {1} seconds\: <strong>{0} seconds left</strong>
@@ -143,7 +144,7 @@ interaction.order.target=Target
 invalidate=Invalidate
 invalidate.overwrite=Invalidate and transfer result
 invalidate.test.confirm.title=Invalidate
-invalidate.test.confirm.text=Do you want to invalidate this test session? The date will not be deleted.
+invalidate.test.confirm.text=Do you want to mark this test session as invalid? The data will not be deleted.
 item.comment=Comment
 kprim.minus=False
 kprim.plus=True
@@ -193,6 +194,9 @@ question.progress.noMaxScore=$org.olat.modules.iq\:noMaxScore
 question.progress.score=$org.olat.modules.iq\:actualPoints
 question.title=Question {0}
 questions=Number of questions in test
+reopen.assessment=Reopen assessment
+reopen.assessment.title=Reopen closed assessment 
+reopen.assessment.text=This assessment is already closed. Do you want to reopen it to correct the test?
 reset.data=Reset data
 reset.test.data.acknowledge=I understand that the data will be definitely deleted.
 reset.test.data.text=Do you really want to reset the assessment data of test? The results of <strong>{0} users</strong> will be definitively deleted.
@@ -290,8 +294,8 @@ upload.explanation=Select a file from your computer to upload it
 validate.xml.signature=Validate test receipt
 validate.xml.signature.file=XML file
 validate.xml.signature.ok=Test receipt and results was successfully validated.
-warning.assignment.done=Grading of this test is done. If the test is invalidated, all correction will be lost.
-warning.assignment.inProcess=Grading of this test was already started. If the test is invalidated, all correction will be lost.
+warning.assignment.done=The grading of this test has already been completed. If this test session is marked as invalid, all existing corrections will be lost.
+warning.assignment.inProcess=The grading of the test has already started. If this test session is marked as invalid, all existing corrections will be lost.
 warning.download.log=There is not a log file for this test.
 warning.reset.assessmenttest.data=The test results were reset by an administrator or course owner. You cannot continue the test and have to restart it.
 warning.suspended.ended.assessmenttest=You have already suspended or ended this test, probably in an other window. Please close this window.
diff --git a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionAssessmentItemListController.java b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionAssessmentItemListController.java
index 7d1ccbc8117f6d03a6f7456f9238e14fbc3fbcb9..9d137b4834af29b9f5d24606e9700a4e855a8fe5 100644
--- a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionAssessmentItemListController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionAssessmentItemListController.java
@@ -469,10 +469,10 @@ public class CorrectionAssessmentItemListController extends FormBasicController
 						itemRef, itemNode);
 				itemCorrection.setItemSession(reloadItemSession);
 
-				boolean readOnly = model.isReadOnly(assessedIdentity);
+				boolean assessmentEntryDone = model.isAssessmentEntryDone(assessedIdentity);
 				identityItemCtrl = new CorrectionIdentityAssessmentItemNavigationController(ureq, getWindowControl(),
 						model.getTestEntry(), model.getResolvedAssessmentTest(), itemCorrection, listEntry,
-						selectedItemSessions, model, null, readOnly, true);
+						selectedItemSessions, model, null, assessmentEntryDone, true);
 				listenTo(identityItemCtrl);
 				updatePreviousNext();
 				
diff --git a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionIdentityListController.java b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionIdentityListController.java
index c23406eeb58e16c5fcb9e9c7971f1699a2e20e25..65bf5eedc1d085fc2b68892c7ff395864c7d7a4c 100644
--- a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionIdentityListController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionIdentityListController.java
@@ -52,11 +52,14 @@ import org.olat.core.id.Identity;
 import org.olat.core.id.Roles;
 import org.olat.core.util.coordinate.CoordinatorManager;
 import org.olat.core.util.coordinate.LockResult;
+import org.olat.course.assessment.AssessmentHelper;
+import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.ims.qti21.AssessmentItemSession;
 import org.olat.ims.qti21.AssessmentTestSession;
 import org.olat.ims.qti21.QTI21Module;
 import org.olat.ims.qti21.QTI21Module.CorrectionWorkflow;
 import org.olat.ims.qti21.QTI21Service;
+import org.olat.ims.qti21.ui.ConfirmReopenAssessmentEntryController;
 import org.olat.ims.qti21.ui.assessment.CorrectionIdentityTableModel.IdentityCols;
 import org.olat.ims.qti21.ui.assessment.components.CorrectedFlexiCellRenderer;
 import org.olat.ims.qti21.ui.assessment.components.NotCorrectedFlexiCellRenderer;
@@ -98,6 +101,7 @@ public class CorrectionIdentityListController extends FormBasicController {
 
 	private CloseableModalController cmc;
 	private ConfirmSaveTestsController confirmSaveTestCtrl;
+	private ConfirmReopenAssessmentEntryController reopenForCorrectionCtrl;
 	private CorrectionIdentityAssessmentItemListController identityItemListCtrl;
 
 	private final boolean isAdministrativeUser;
@@ -320,6 +324,14 @@ public class CorrectionIdentityListController extends FormBasicController {
 			}
 			cmc.deactivate();
 			cleanUp();
+		} else if(reopenForCorrectionCtrl == source) {
+			cmc.deactivate();
+			CorrectionIdentityRow row = (CorrectionIdentityRow)reopenForCorrectionCtrl.getUserObject();
+			cleanUp();
+			if(event == Event.CHANGED_EVENT || event == Event.DONE_EVENT) {
+				model.discardAssessmentEntryDone(row.getIdentity());
+				doOpenCorrection(ureq, row);
+			}
 		} else if(cmc == source) {
 			cleanUp();
 		}
@@ -327,8 +339,10 @@ public class CorrectionIdentityListController extends FormBasicController {
 	}
 	
 	private void cleanUp() {
+		removeAsListenerAndDispose(reopenForCorrectionCtrl);
 		removeAsListenerAndDispose(confirmSaveTestCtrl);
 		removeAsListenerAndDispose(cmc);
+		reopenForCorrectionCtrl = null;
 		confirmSaveTestCtrl = null;
 		cmc = null;
 	}
@@ -361,10 +375,36 @@ public class CorrectionIdentityListController extends FormBasicController {
 		}
 		
 		Identity assessedIdentity = row.getIdentity();
-		boolean readOnly = model.isReadOnly(assessedIdentity); 
+		boolean assessmentEntryDone = model.isAssessmentEntryDone(assessedIdentity);
+		if(assessmentEntryDone) {
+			doReopenForCorrection(ureq, row);
+		} else {
+			doOpenCorrection(ureq, row);
+		}
+	}
+	
+	private void doReopenForCorrection(UserRequest ureq, CorrectionIdentityRow row) {
+		if(guardModalController(reopenForCorrectionCtrl)) return;
+
+		UserCourseEnvironment assessedUserCourseEnv = AssessmentHelper
+				.createAndInitUserCourseEnvironment(row.getIdentity(), model.getCourseEnvironment());
+		reopenForCorrectionCtrl = new ConfirmReopenAssessmentEntryController(ureq, getWindowControl(),
+				assessedUserCourseEnv, model.getCourseNode(), row.getCandidateSession());
+		reopenForCorrectionCtrl.setUserObject(row);
+		listenTo(reopenForCorrectionCtrl);
+		
+		cmc = new CloseableModalController(getWindowControl(), "close", reopenForCorrectionCtrl.getInitialComponent(),
+				true, translate("reopen.assessment.title"));
+		cmc.activate();
+		listenTo(cmc);
+	}
+
+	private void doOpenCorrection(UserRequest ureq, CorrectionIdentityRow row) {
+		Identity assessedIdentity = row.getIdentity();
+		boolean assessmentEntryDone = model.isAssessmentEntryDone(assessedIdentity);
 		String title = anonymous ? row.getUser() : userManager.getUserDisplayName(row.getIdentity());
 		identityItemListCtrl = new CorrectionIdentityAssessmentItemListController(ureq, getWindowControl(), stackPanel,
-				model, assessedIdentity, title, readOnly);
+				model, assessedIdentity, title, assessmentEntryDone);
 		listenTo(identityItemListCtrl);
 		
 		String crumb;
diff --git a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionOverviewController.java b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionOverviewController.java
index ccfa892765a0abce1add22de5a76d5def084d678..206a334d09253e645b7f5138ccf5d7891eec1b92 100644
--- a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionOverviewController.java
+++ b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionOverviewController.java
@@ -109,7 +109,7 @@ public class CorrectionOverviewController extends BasicController implements Too
 			identifierToRefs.put(itemRef.getIdentifier(), itemRef);
 		}
 
-		List<Identity> assessedIdentities = getAssessedIdentities();
+		List<Identity> assessedIdentities = initializeAssessedIdentities();
 		model = new CorrectionOverviewModel(courseEntry, courseNode, testEntry,
 				resolvedAssessmentTest, manifestBuilder, assessedIdentities);
 		
@@ -134,7 +134,11 @@ public class CorrectionOverviewController extends BasicController implements Too
 		return model.getNumberOfAssessedIdentities();
 	}
 	
-	private List<Identity> getAssessedIdentities() {
+	public List<Identity> getAssessedIdentities() {
+		return model.getAssessedIdentities();
+	}
+	
+	private List<Identity> initializeAssessedIdentities() {
 		Set<Identity> identitiesSet;
 		if(asOptions.getGroup() != null) {
 			List<Identity> identities = businessGroupService.getMembers(asOptions.getGroup(), GroupRoles.participant.name());
diff --git a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionOverviewModel.java b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionOverviewModel.java
index 4e190d3a5b02182ad075de66f869beca67bfd910..17dedb9adb07dc61529e2f941f6b2905238b8479 100644
--- a/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionOverviewModel.java
+++ b/src/main/java/org/olat/ims/qti21/ui/assessment/CorrectionOverviewModel.java
@@ -262,7 +262,11 @@ public class CorrectionOverviewModel {
 		return manifestBuilder.getResourceBuilderByHref(itemRef.getHref().toString());
 	}
 	
-	public boolean isReadOnly(Identity assessedIdentity) {
+	public void discardAssessmentEntryDone(Identity assessedIdentity) {
+		assessedIdentitiesDone.remove(assessedIdentity);
+	}
+	
+	public boolean isAssessmentEntryDone(Identity assessedIdentity) {
 		Boolean done = assessedIdentitiesDone.computeIfAbsent(assessedIdentity, identity -> {
 			if(getCourseNode() != null) {
 				UserCourseEnvironment assessedUserCourseEnv = AssessmentHelper
diff --git a/src/main/java/org/olat/ims/qti21/ui/assessment/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/assessment/_i18n/LocalStrings_de.properties
index 72fc0bb3dcb865a0dc495109ea44f0d23613f317..bcb52f79a9652e6d69a7d0c606bfdd3a71bf8375 100644
--- a/src/main/java/org/olat/ims/qti21/ui/assessment/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/assessment/_i18n/LocalStrings_de.properties
@@ -26,6 +26,7 @@ not.responded=Die Frage wurde nicht beantwortet
 overview.tests=\u00DCbersicht und abschliessen
 previous.item=Vorherige Frage
 previous.user=Vorheriger Benutzer
+reopen.assessment.title=$org.olat.ims.qti21.ui\:reopen.assessment.title
 save.back=Speichern und zur \u00DCbersicht
 save.next=Speichern und n\u00E4chste Frage
 save.next.identity=Speichern und n\u00E4chster Teilnehmer
diff --git a/src/main/java/org/olat/ims/qti21/ui/assessment/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/assessment/_i18n/LocalStrings_en.properties
index 524ddb4f1e4df2d52ab33ed3b2a44941eee606a3..f62c1d79e5a40162f3b470d43be2a4fa0812555d 100644
--- a/src/main/java/org/olat/ims/qti21/ui/assessment/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/assessment/_i18n/LocalStrings_en.properties
@@ -26,6 +26,7 @@ override.score=Override score
 overview.tests=Overview and closing
 previous.item=Previous question
 previous.user=Previous user
+reopen.assessment.title=$org.olat.ims.qti21.ui\:reopen.assessment.title
 save.back=Save and back to overview
 save.next=Save and next question
 save.next.identity=Save and next participant
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
index a17019eecc96f189c32d213b8aaaa76f895267a3..8cba37429b84c9ae2cc6fc19e973bb4d4ce98d6b 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_de.properties
@@ -90,7 +90,7 @@ fib.tolerance.mode.relative.example=Prozent, zum Beispiel 15 oder 99.0
 fib.tolerance.mode.relative.help=Die Schranke stellt eine relative Zahl in Prozent dar.\u2028Beispiel\: L\u00F6sung 20, Untere Schranke 10, Obere Schranke 10 &rarr; Alle L\u00F6sungen zwischen 18 und 22 sind g\u00FCltig, denn die untere Schranke bedeutet minus 10% (20-2) und die obere Schranke plus 10% (20+2).
 fib.tolerance.up=Obere Schranke
 file=Datei
-force.inherited.max.attempts=Setzt alle unter "L\u00F6sungsversuche" zu "Vererbt"
+force.inherited.max.attempts=Anzahl L\u00F6sungsversuche an alle Unterelemente (Fragen, Sektionen) vererben
 form.choice=Auswahl
 form.drawing=Zeichnen
 form.essay=Freitext
diff --git a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
index 53202636e26ce76327459d7196997aff2b0613e0..73c88a05be274d4384259ab222a51e0848b6fa97 100644
--- a/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/ims/qti21/ui/editor/_i18n/LocalStrings_en.properties
@@ -90,7 +90,7 @@ fib.tolerance.mode.relative.example=Percentage, example 15 or 99.0
 fib.tolerance.mode.relative.help=The solution is accepted until a lower and an upper bound. The bound is a relative number in percent. Example\: Solution 20, lower bound 10, upper bound 10 &rarr; all solutions between 18 and 22 are correct, as the lower bound means minus 10% (20-2) and the upper bound plus 10% (20+2).
 fib.tolerance.up=Upper bound
 file=File
-force.inherited.max.attempts=Set all under "Number of attempts" to inherit
+force.inherited.max.attempts=Inherit number of attempts to all sub-elements (sections, questions)
 form.choice=Choice
 form.drawing=Drawing
 form.essay=Essay
diff --git a/src/main/java/org/olat/modules/grading/manager/GradingServiceImpl.java b/src/main/java/org/olat/modules/grading/manager/GradingServiceImpl.java
index 9d9d0f22353f4d04513703c68194ce06137b4396..818da3c2b0ac30bc9fe102692de6af0db142b61c 100644
--- a/src/main/java/org/olat/modules/grading/manager/GradingServiceImpl.java
+++ b/src/main/java/org/olat/modules/grading/manager/GradingServiceImpl.java
@@ -36,6 +36,7 @@ import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import org.apache.logging.log4j.Logger;
+import org.olat.basesecurity.BaseSecurity;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.commons.calendar.CalendarUtils;
 import org.olat.core.commons.persistence.DB;
@@ -119,6 +120,8 @@ public class GradingServiceImpl implements GradingService, UserDataDeletable, Re
 	@Autowired
 	private MailManager mailManager;
 	@Autowired
+	private BaseSecurity securityManager;
+	@Autowired
 	private GradingModule gradingModule;
 	@Autowired
 	private TaxonomyModule taxonomyModule;
@@ -306,7 +309,11 @@ public class GradingServiceImpl implements GradingService, UserDataDeletable, Re
 		}
 		
 		for(IdentityTimeRecordStatistics record:records) {
-			GraderWithStatistics statistics = identityToStatistics.get(record.getKey());
+			Long graderIdentityKey = record.getKey();
+			GraderWithStatistics statistics = identityToStatistics.computeIfAbsent(graderIdentityKey, key -> {
+				Identity grader = securityManager.loadIdentityByKey(graderIdentityKey);
+				return new GraderWithStatistics(grader, GraderStatistics.empty(graderIdentityKey));
+			});
 			statistics.addRecordedTimeInSeconds(record.getTime());
 			statistics.addRecordedMetadataTimeInSeconds(record.getMetadataTime());
 		}
diff --git a/src/main/java/org/olat/user/ui/admin/UserAdminMainController.java b/src/main/java/org/olat/user/ui/admin/UserAdminMainController.java
index 90ae5c7737bfdb7e9ca5e7ed4c3b9efe3239f9a9..716fd574fc6b55bdc321f3c8707fbf831c34f761 100644
--- a/src/main/java/org/olat/user/ui/admin/UserAdminMainController.java
+++ b/src/main/java/org/olat/user/ui/admin/UserAdminMainController.java
@@ -346,16 +346,16 @@ public class UserAdminMainController extends MainLayoutBasicController implement
 			case "useradmin": return createUserSearchController(ureq, bwControl);
 			// groups
 			case "groupcoach": return createUserSearchController(ureq, bwControl,
-					SearchIdentityParams.resources(null, true, GroupRoles.coach, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true);
+					SearchIdentityParams.resources(null, true, GroupRoles.coach, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true, true);
 			case "groupparticipant": return createUserSearchController(ureq, bwControl,
-					SearchIdentityParams.resources(null, true, GroupRoles.participant, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true);
+					SearchIdentityParams.resources(null, true, GroupRoles.participant, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true, true);
 			// resources
 			case "coauthors": return createUserSearchController(ureq, bwControl,
-					SearchIdentityParams.resources(GroupRoles.owner, true, null, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true);
+					SearchIdentityParams.resources(GroupRoles.owner, true, null, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true, true);
 			case "courseparticipants": return createUserSearchController(ureq, bwControl,
-					SearchIdentityParams.resources(GroupRoles.participant, true, null, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true);
+					SearchIdentityParams.resources(GroupRoles.participant, true, null, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true, true);
 			case "coursecoach": return createUserSearchController(ureq, bwControl,
-					SearchIdentityParams.resources(GroupRoles.coach, true, null, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true);
+					SearchIdentityParams.resources(GroupRoles.coach, true, null, null, null, null, Identity.STATUS_VISIBLE_LIMIT), false, true, true, true);
 			// status
 			case "pendinggroup": return createUserSearchController(ureq, bwControl, Identity.STATUS_PENDING);
 			case "inactivegroup": return createUserSearchController(ureq, bwControl, Identity.STATUS_INACTIVE);
@@ -363,7 +363,7 @@ public class UserAdminMainController extends MainLayoutBasicController implement
 			case "deletedusers": return createDeletedUserController(ureq, bwControl);
 			// predefined queries
 			case "userswithoutgroup":
-				return createUserSearchController(ureq, bwControl, SearchIdentityParams.withBusinesGroups(), false, true, true);
+				return createUserSearchController(ureq, bwControl, SearchIdentityParams.withBusinesGroups(), false, true, true, true);
 			case "userswithoutemail":
 				List<Identity> usersWithoutEmail = userManager.findVisibleIdentitiesWithoutEmail();
 				return new UsermanagerUserSearchController(ureq, bwControl, content, usersWithoutEmail, true, true, false);
@@ -371,7 +371,7 @@ public class UserAdminMainController extends MainLayoutBasicController implement
 				List<Identity> usersEmailDuplicates = userManager.findVisibleIdentitiesWithEmailDuplicates();
 				return new UsermanagerUserSearchController(ureq, bwControl, content, usersEmailDuplicates, true, true, false);
 			case "noauthentication": return createUserSearchController(ureq, bwControl,
-					SearchIdentityParams.authenticationProviders(new String[]{ null }, Identity.STATUS_VISIBLE_LIMIT), false, true, true);
+					SearchIdentityParams.authenticationProviders(new String[]{ null }, Identity.STATUS_VISIBLE_LIMIT), false, true, true, true);
 			// time based predefined queries
 			case "created.lastweek": return createUserSearchControllerAfterDate(ureq, bwControl, Calendar.DAY_OF_MONTH, -7);
 			case "created.lastmonth": return createUserSearchControllerAfterDate(ureq, bwControl, Calendar.MONTH, -1);
@@ -383,7 +383,7 @@ public class UserAdminMainController extends MainLayoutBasicController implement
 
 	private Controller getController(UserRequest ureq, Organisation organisation) {
 		SearchIdentityParams predefinedQuery = SearchIdentityParams.organisation(organisation, Identity.STATUS_VISIBLE_LIMIT);
-		return createUserSearchController(ureq, getWindowControl(), predefinedQuery, true, true, true);
+		return createUserSearchController(ureq, getWindowControl(), predefinedQuery, true, true, true, true);
 	}
 	
 	private Controller createInfoController(UserRequest ureq, WindowControl bwControl, Presentation template) {
@@ -394,23 +394,23 @@ public class UserAdminMainController extends MainLayoutBasicController implement
 		Calendar cal = Calendar.getInstance();
 		cal.add(unit, amount);
 		SearchIdentityParams predefinedQuery = SearchIdentityParams.params(cal.getTime(), null, Identity.STATUS_VISIBLE_LIMIT);
-		return createUserSearchController(ureq, bwControl, predefinedQuery, false, true, true);
+		return createUserSearchController(ureq, bwControl, predefinedQuery, false, true, true, true);
 	}
 	
 	private UsermanagerUserSearchController createUserSearchController(UserRequest ureq, WindowControl bwControl, OrganisationRoles role) {
 		final OrganisationRoles[] roles = { role };
 		SearchIdentityParams predefinedQuery = SearchIdentityParams.params(roles, Identity.STATUS_VISIBLE_LIMIT);
-		return createUserSearchController(ureq, bwControl, predefinedQuery, false, true, true);
+		return createUserSearchController(ureq, bwControl, predefinedQuery, false, true, true, true);
 	}
 	
 	private UsermanagerUserSearchController createUserSearchController(UserRequest ureq, WindowControl bwControl, CurriculumRoles role) {
 		SearchIdentityParams predefinedQuery = SearchIdentityParams.resources(null, true, null, role, null, null, Identity.STATUS_VISIBLE_LIMIT);
-		return createUserSearchController(ureq, bwControl, predefinedQuery, false, true, true);
+		return createUserSearchController(ureq, bwControl, predefinedQuery, false, true, true, true);
 	}
 	
 	private UsermanagerUserSearchController createUserSearchController(UserRequest ureq, WindowControl bwControl, Integer status) {
 		SearchIdentityParams predefinedQuery = SearchIdentityParams.params(null, status);
-		return createUserSearchController(ureq, bwControl, predefinedQuery, false, true, false);
+		return createUserSearchController(ureq, bwControl, predefinedQuery, false, true, false, true);
 	}
 	
 	private UsermanagerUserSearchController createUserSearchController(UserRequest ureq, WindowControl bwControl) {
@@ -418,7 +418,7 @@ public class UserAdminMainController extends MainLayoutBasicController implement
 	}
 	
 	private UsermanagerUserSearchController createUserSearchController(UserRequest ureq, WindowControl bwControl,
-			SearchIdentityParams predefinedQuery, boolean showOrganisationMove, boolean showDelete, boolean statusFilter) {
+			SearchIdentityParams predefinedQuery, boolean showOrganisationMove, boolean showDelete, boolean statusFilter, boolean tableSearch) {
 		if(manageableOrganisations != null) {
 			List<OrganisationRef> allowedOrganisations = new ArrayList<>(manageableOrganisations);
 			if(predefinedQuery.getOrganisations() != null) {
@@ -426,7 +426,8 @@ public class UserAdminMainController extends MainLayoutBasicController implement
 			}
 			predefinedQuery.setOrganisations(allowedOrganisations);
 		}
-		return new UsermanagerUserSearchController(ureq, bwControl, content, predefinedQuery, true, showOrganisationMove, showDelete, statusFilter);
+		return new UsermanagerUserSearchController(ureq, bwControl, content, predefinedQuery, true, showOrganisationMove, showDelete,
+				statusFilter, tableSearch);
 	}
 	
 	private UsermanagerUserSearchController createUserSearchController(UserRequest ureq, WindowControl bwControl, IdentityRelation relation) {
diff --git a/src/main/java/org/olat/user/ui/admin/UserSearchTableController.java b/src/main/java/org/olat/user/ui/admin/UserSearchTableController.java
index 96abdbf796aca5032e3da0c405addebfddabd1b2..785746aa4e282278e4762124ab092c24045b66cf 100644
--- a/src/main/java/org/olat/user/ui/admin/UserSearchTableController.java
+++ b/src/main/java/org/olat/user/ui/admin/UserSearchTableController.java
@@ -209,7 +209,7 @@ public class UserSearchTableController extends FormBasicController implements Ac
 		tableEl.setExportEnabled(true);
 		tableEl.setMultiSelect(true);
 		tableEl.setSelectAllEnable(true);
-		tableEl.setSearchEnabled(true);
+		tableEl.setSearchEnabled(settings.isTableSearch());
 		tableEl.setAndLoadPersistedPreferences(ureq, "user_search_table");
 		
 		initBulkActions(formLayout);
diff --git a/src/main/java/org/olat/user/ui/admin/UserSearchTableSettings.java b/src/main/java/org/olat/user/ui/admin/UserSearchTableSettings.java
index f8956ef30eb4679bea777bb22f43bef3616ff465..7d0833683ccc01f9e3e649943ef790fcd17decee 100644
--- a/src/main/java/org/olat/user/ui/admin/UserSearchTableSettings.java
+++ b/src/main/java/org/olat/user/ui/admin/UserSearchTableSettings.java
@@ -32,27 +32,36 @@ public class UserSearchTableSettings {
 	private final boolean bulkDelete;
 	private final boolean bulkOrganisationMove;
 	private final boolean statusFilter;
+	private final boolean tableSearch;
 	
-	private UserSearchTableSettings(boolean vCard, boolean bulkMail, boolean bulkOrganisationMove, boolean bulkDelete, boolean statusFilter) {
+	private UserSearchTableSettings(boolean vCard, boolean bulkMail, boolean bulkOrganisationMove, boolean bulkDelete, boolean statusFilter, boolean tableSearch) {
 		this.vCard = vCard;
 		this.bulkMail = bulkMail;
 		this.bulkDelete = bulkDelete;
 		this.bulkOrganisationMove = bulkOrganisationMove;
 		this.statusFilter = statusFilter;
+		this.tableSearch = tableSearch;
 	}
 	
-	public static UserSearchTableSettings none() {
-		return new UserSearchTableSettings(false, false, false, false, false);
+	/**
+	 * @return The table seetings with only the search enabled
+	 */
+	public static UserSearchTableSettings minimal() {
+		return new UserSearchTableSettings(false, false, false, false, false, true);
 	}
 	
-	public static UserSearchTableSettings withVCard(boolean bulkMail, boolean bulkOrganisationMove, boolean bulkDelete, boolean statusFilter) {
-		return new UserSearchTableSettings(false, bulkMail, bulkOrganisationMove, bulkDelete, statusFilter);
+	public static UserSearchTableSettings withVCard(boolean bulkMail, boolean bulkOrganisationMove, boolean bulkDelete, boolean statusFilter, boolean tableSearch) {
+		return new UserSearchTableSettings(false, bulkMail, bulkOrganisationMove, bulkDelete, statusFilter, tableSearch);
 	}
 	
 	public boolean isVCard() {
 		return vCard;
 	}
 	
+	public boolean isTableSearch() {
+		return tableSearch;
+	}
+	
 	public boolean isBulkMail() {
 		return bulkMail;
 	}
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/ConfirmDeleteUserController.java b/src/main/java/org/olat/user/ui/admin/lifecycle/ConfirmDeleteUserController.java
index 5e1cf362a684f082a48d76153b664ed37a7fed4f..2e9a4da5d49697e6762686a2ac9cc559c3719f5f 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/ConfirmDeleteUserController.java
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/ConfirmDeleteUserController.java
@@ -76,7 +76,13 @@ public class ConfirmDeleteUserController extends FormBasicController {
 		if(formLayout instanceof FormLayoutContainer) {
 			FormLayoutContainer layout = (FormLayoutContainer)formLayout;
 			String names = buildUserNameList(toDelete);
-			layout.contextPut("names", names);
+			String message;
+			if(toDelete.size() == 1) {
+				message = translate("readyToDelete.delete.confirm.single", names);
+			} else {
+				message = translate("readyToDelete.delete.confirm", names);
+			}
+			layout.contextPut("msg", message);
 			
 			FormLayoutContainer layoutCont = FormLayoutContainer.createDefaultFormLayout("confirm", getTranslator());
 			formLayout.add("confirm", layoutCont);
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/UserLifecycleOverviewController.java b/src/main/java/org/olat/user/ui/admin/lifecycle/UserLifecycleOverviewController.java
index d6edbb3d77c2d10addac9995e6958212dfeb63c0..562974c80571059cc723e3f76f6848607ec83abb 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/UserLifecycleOverviewController.java
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/UserLifecycleOverviewController.java
@@ -143,7 +143,7 @@ public class UserLifecycleOverviewController extends BasicController implements
 		mainVC.put("tabPane", lifecycleTabbedPane);
 		
 		// ready to inactivate
-		readyToInactivateUserCtrl = new UserSearchTableController(ureq, getWindowControl(), stackPanel, UserSearchTableSettings.none());
+		readyToInactivateUserCtrl = new UserSearchTableController(ureq, getWindowControl(), stackPanel, UserSearchTableSettings.minimal());
 		listenTo(readyToInactivateUserCtrl);
 		lifecycleTabbedPane.addTab(translate("overview.ready.to.inactivate.user"), readyToInactivateUserCtrl.getInitialComponent());
 			
@@ -151,7 +151,7 @@ public class UserLifecycleOverviewController extends BasicController implements
 		readyToInactivateUserCtrl.loadModel(readyToInactivateSearchParams);
 
 		// inactive
-		inactiveUserCtrl = new UserSearchTableController(ureq, getWindowControl(), stackPanel, UserSearchTableSettings.none());
+		inactiveUserCtrl = new UserSearchTableController(ureq, getWindowControl(), stackPanel, UserSearchTableSettings.minimal());
 		listenTo(inactiveUserCtrl);
 		lifecycleTabbedPane.addTab(translate("overview.inactive.user"), inactiveUserCtrl.getInitialComponent());
 
@@ -159,7 +159,7 @@ public class UserLifecycleOverviewController extends BasicController implements
 		inactiveUserCtrl.loadModel(inactiveSearchParams);
 		
 		// ready to delete
-		readyToDeleteUserCtrl = new UserSearchTableController(ureq, getWindowControl(), stackPanel, UserSearchTableSettings.none());
+		readyToDeleteUserCtrl = new UserSearchTableController(ureq, getWindowControl(), stackPanel, UserSearchTableSettings.minimal());
 		listenTo(readyToDeleteUserCtrl);
 		lifecycleTabbedPane.addTab(translate("overview.ready.to.delete.user"), readyToDeleteUserCtrl.getInitialComponent());
 
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/_content/confirm_delete.html b/src/main/java/org/olat/user/ui/admin/lifecycle/_content/confirm_delete.html
index b6355ca0bfe6dbf15de6179171c45ba9db149500..71f7ac34b3f63a9d275849e181a032d4091cf419 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/_content/confirm_delete.html
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/_content/confirm_delete.html
@@ -1,5 +1,5 @@
 <div class="o_error">
-	<i class="o_icon o_icon-lg o_icon_important"> </i> $r.translate("readyToDelete.delete.confirm", $names)
+	<i class="o_icon o_icon-lg o_icon_important"> </i> $r.xssScan($msg)
 </div>
 #if($notAllDeleteable)
 <div class="o_warning">
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_de.properties
index cdb1fdbeee3f9ddd86a82fc13652e75d0814903a..e99014d6e61dc661ff7733e6bdd4ea479b926e54 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_de.properties
@@ -37,6 +37,7 @@ overview.inactive.user=Deaktivierte Benutzer
 overview.ready.to.delete.user=Bereits zu l\u00F6schen
 overview.ready.to.inactivate.user=Benutzer ohne Aktivit\u00E4t
 readyToDelete.delete.confirm=Die ausgew\u00E4hlten Benutzerkonten "<strong>{0}</strong>" (inklusive pers\u00F6nliche Daten) werden gel\u00F6scht und k\u00F6nnen nicht wiederhergestellt werden.
+readyToDelete.delete.confirm.single=Das ausgew\u00E4hlte Benutzerkonto "<strong>{0}</strong>" (inklusive pers\u00F6nliche Daten) wird gel\u00F6scht und kann nicht wiederhergestellt werden.
 readyToDelete.delete.confirm.check=Alle Dateien werden definitiv gel\u00F6scht und k\u00F6nnen nicht mehr wiederhergestellt werden.
 readyToDelete.delete.confirm.check.label=Best\u00E4tigung
 table.identity.deleted.name=Del_Benutzername
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties
index 877c543b3dbb5418e4033fe91282c5dc1c8c7132..7f56d05f424f5392d13d7a47f1fafb8117ee2b14 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_en.properties
@@ -37,6 +37,7 @@ overview.inactive.user=Deactivated users
 overview.ready.to.delete.user=Ready to delete
 overview.ready.to.inactivate.user=Users with no activity
 readyToDelete.delete.confirm=The selected user accounts "<strong>{0}</strong>" (along with personal data) will be deleted unrecoverably.
+readyToDelete.delete.confirm.singlle=The selected user account "<strong>{0}</strong>" (along with personal data) will be deleted unrecoverably.
 readyToDelete.delete.confirm.check=All files will be permanently removed and cannot be recovered.
 readyToDelete.delete.confirm.check.label=Confirmation
 table.identity.deleted.name=Del_User name
diff --git a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_fr.properties
index 7a466a87092ca53b971000fbc4c980d0372c4d1c..012d00978b109b3cbf59d7b9ee67163b82453441 100644
--- a/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_fr.properties
+++ b/src/main/java/org/olat/user/ui/admin/lifecycle/_i18n/LocalStrings_fr.properties
@@ -36,7 +36,8 @@ num.inactive.day.deletion=Nombre de jours d\u00E9sactiv\u00E9 avant effacement
 overview.inactive.user=Utilisateurs d\u00E9sactiv\u00E9s
 overview.ready.to.delete.user=Pr\u00EAt \u00E0 \u00EAtre effac\u00E9
 overview.ready.to.inactivate.user=Utilisateurs sans activit\u00E9
-readyToDelete.delete.confirm=Les comptes d'utilisateur s\u00E9lectionn\u00E9s "<strong>{0}</strong>" (y compris les donn\u00E9es personnelles) seront supprim\u00E9s et ne pourront plus \u00EAtre r\u00E9tablis. 
+readyToDelete.delete.confirm=Les comptes des utilisateurs s\u00E9lectionn\u00E9s "<strong>{0}</strong>" (y compris les donn\u00E9es personnelles) seront supprim\u00E9s et ne pourront plus \u00EAtre r\u00E9tablis.
+readyToDelete.delete.confirm.single=Le compte de l'utilisateur s\u00E9lectionn\u00E9 "<strong>{0}</strong>" (y compris les donn\u00E9es personnelles) sera supprim\u00E9 et ne pourra plus \u00EAtre r\u00E9tabli.
 readyToDelete.delete.confirm.check=Toutes les donn\u00E9es seront d\u00E9finitivement effac\u00E9es et ne pourront pas \u00EAtre r\u00E9cup\u00E9r\u00E9es.
 readyToDelete.delete.confirm.check.label=Confirmation
 table.identity.deleted.name=Del_Nom d'utilisateur
diff --git a/src/main/resources/serviceconfig/olat.properties b/src/main/resources/serviceconfig/olat.properties
index bfcc6cdd975a15f80347ec77935db715f9ca7530..b99a353f7a2de36ab1cf1e0b11c7249b253d495e 100644
--- a/src/main/resources/serviceconfig/olat.properties
+++ b/src/main/resources/serviceconfig/olat.properties
@@ -649,8 +649,6 @@ mobile.context=/mobile
 server.domainname=localhost
 # the port on which the container is listening
 server.port=8080
-# OLAT JMX server port (must be unique per node in a cluster)
-jmx.rmi.port=3000
 
 ########################################################################
 # MathJAX CDN
@@ -1114,10 +1112,10 @@ certificate.broker.url=vm://embedded?broker.persistent=false
 
 #if you use the jndi connection
 jms.broker.jndi=OpenOLATConnectionFactory
-sysbus.broker.jndi=topic/sysbus
-search.broker.jndi=queue/searchQueue
-index.broker.jndi=queue/indexQueue
-certificate.broker.jndi=queue/certificateQueue
+sysbus.broker.jndi=topic/sysbus&broker.useJmx=false
+search.broker.jndi=queue/searchQueue&broker.useJmx=false
+index.broker.jndi=queue/indexQueue&broker.useJmx=false
+certificate.broker.jndi=queue/certificateQueue&broker.useJmx=false
 
 #####
 #query cache config for singlevm/cluster
diff --git a/src/test/profile/mysql/olat.local.properties b/src/test/profile/mysql/olat.local.properties
index b79526968cd496263d2d0d4662b9226cca4fb6dd..00b93048559e8478ca993fa069789ef04a9512a8 100644
--- a/src/test/profile/mysql/olat.local.properties
+++ b/src/test/profile/mysql/olat.local.properties
@@ -31,7 +31,6 @@ keepUserLoginAfterDeletion=true
 
 # do not run upgrades and scheduled jobs and such
 cluster.singleton.services = disabled
-jmx.rmi.port=${test.env.jmx.rmi.port.0:1009}
 
 # SingleVM jms.broker.url
 jms.broker.url=vm://embedded?broker.persistent=false
diff --git a/src/test/profile/oracle/olat.local.properties b/src/test/profile/oracle/olat.local.properties
index 54304245ef03cb66adf38c68f848346210aadba6..078aaf062e37114a3ffd60c26386426891272371 100644
--- a/src/test/profile/oracle/olat.local.properties
+++ b/src/test/profile/oracle/olat.local.properties
@@ -31,7 +31,6 @@ keepUserLoginAfterDeletion=true
 
 # do not run upgrades and scheduled jobs and such
 cluster.singleton.services = disabled
-jmx.rmi.port=${test.env.jmx.rmi.port.0:1009}
 
 # SingleVM jms.broker.url
 jms.broker.url=vm://embedded?broker.persistent=false
diff --git a/src/test/profile/postgresql/olat.local.properties b/src/test/profile/postgresql/olat.local.properties
index 1dda8938a7e5a5eba96e25519e09c541ebaaf74e..99fa6854fbcdf4df21a0d2d1ab046daa13649cab 100644
--- a/src/test/profile/postgresql/olat.local.properties
+++ b/src/test/profile/postgresql/olat.local.properties
@@ -31,7 +31,6 @@ keepUserLoginAfterDeletion=true
 
 # do not run upgrades and scheduled jobs and such
 cluster.singleton.services = disabled
-jmx.rmi.port=${test.env.jmx.rmi.port.0:1009}
 
 # SingleVM jms.broker.url
 jms.broker.url=vm://embedded?broker.persistent=false
diff --git a/src/test/resources/arquillian.xml b/src/test/resources/arquillian.xml
index c2667baa98ff5397688bd864f7dab35de62fe77f..f656a58437d8e95cd593cd1915c1e90663339a3b 100644
--- a/src/test/resources/arquillian.xml
+++ b/src/test/resources/arquillian.xml
@@ -28,6 +28,7 @@
 		<property name="chromeDriverBinary">target/drone/675a673c111fdcc9678d11df0e69b334/chromedriver</property>
 		<property name="firefoxDriverBinary">target/drone/ce03addb1fc8c24900011f90fc80f3c1/geckodriver</property>
 		-->
+		<property name="firefoxDriverVersion">${webdriver.firefox.version:v0.27.0}</property>
 		<property name="firefoxUserPreferences">src/test/profile/firefox/prefs.js</property>
 		<property name="chromeDriverVersion">${webdriver.chrome.version:84.0.4147.30}</property>
 		<property name="chromeArguments">${webdriver.chrome.arguments}</property>