diff --git a/src/main/java/org/olat/core/gui/components/util/KeyValues.java b/src/main/java/org/olat/core/gui/components/util/KeyValues.java
index c09e99629dce55baf243f2945dfb84f15ce55e2b..211ed12df47c743e14219b5d5cdc374013101cac 100644
--- a/src/main/java/org/olat/core/gui/components/util/KeyValues.java
+++ b/src/main/java/org/olat/core/gui/components/util/KeyValues.java
@@ -22,7 +22,6 @@ package org.olat.core.gui.components.util;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
-import java.util.Objects;
 
 /**
  * 
@@ -103,7 +102,7 @@ public class KeyValues {
 	}
 	
 	public boolean containsKey(String key) {
-		return keyValues.stream().map(KeyValue::getKey).anyMatch(k -> Objects.equals(k, key));
+		return keyValues.stream().map(KeyValue::getKey).anyMatch(k -> k.equals(key));
 	}
 	
 	public int size() {
diff --git a/src/main/java/org/olat/course/nodes/MSCourseNode.java b/src/main/java/org/olat/course/nodes/MSCourseNode.java
index 71ad44b0948f01ae9861f6fed2f1d369ea791c13..b98aeaa932d0617406a1ae8c3834e68126adb8c2 100644
--- a/src/main/java/org/olat/course/nodes/MSCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/MSCourseNode.java
@@ -41,20 +41,25 @@ import org.olat.core.gui.control.generic.tabbable.TabbableController;
 import org.olat.core.gui.translator.PackageTranslator;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
+import org.olat.core.id.Organisation;
 import org.olat.core.id.Roles;
 import org.olat.core.logging.OLATRuntimeException;
+import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
 import org.olat.course.ICourse;
 import org.olat.course.assessment.AssessmentManager;
 import org.olat.course.assessment.ui.tool.AssessmentCourseNodeController;
 import org.olat.course.auditing.UserNodeAuditManager;
+import org.olat.course.condition.ConditionEditController;
 import org.olat.course.editor.CourseEditorEnv;
 import org.olat.course.editor.NodeEditController;
 import org.olat.course.editor.StatusDescription;
 import org.olat.course.nodes.ms.MSCourseNodeEditController;
 import org.olat.course.nodes.ms.MSCourseNodeRunController;
-import org.olat.course.nodes.ms.MSEditFormController;
+import org.olat.course.nodes.ms.MSEvaluationFormExecutionController;
 import org.olat.course.nodes.ms.MSIdentityListCourseNodeController;
+import org.olat.course.nodes.ms.MSService;
+import org.olat.course.nodes.ms.MinMax;
 import org.olat.course.properties.CoursePropertyManager;
 import org.olat.course.properties.PersistingCoursePropertyManager;
 import org.olat.course.run.navigation.NodeRunConstructionResult;
@@ -69,8 +74,14 @@ import org.olat.modules.assessment.Role;
 import org.olat.modules.assessment.model.AssessmentRunStatus;
 import org.olat.modules.assessment.ui.AssessmentToolContainer;
 import org.olat.modules.assessment.ui.AssessmentToolSecurityCallback;
+import org.olat.modules.forms.EvaluationFormSession;
+import org.olat.modules.forms.handler.EvaluationFormResource;
 import org.olat.properties.Property;
 import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryEntryImportExport;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.handlers.RepositoryHandler;
+import org.olat.repository.handlers.RepositoryHandlerFactory;
 import org.olat.resource.OLATResource;
 
 /**
@@ -80,16 +91,22 @@ import org.olat.resource.OLATResource;
  * @author BPS (<a href="http://www.bps-system.de/">BPS Bildungsportal Sachsen GmbH</a>)
  */
 public class MSCourseNode extends AbstractAccessableCourseNode implements PersistentAssessableCourseNode {
+	
 	private static final long serialVersionUID = -7741172700015384397L;
+	
+	@SuppressWarnings("deprecation")
 	private static final String PACKAGE_MS = Util.getPackageName(MSCourseNodeRunController.class);
 
+	public static final int CURRENT_VERSION = 2;
 	private static final String TYPE = "ms";
 	/** configuration: score can be set */
 	public static final String CONFIG_KEY_HAS_SCORE_FIELD = "hasScoreField";
 	/** configuration: score min value */
 	public static final String CONFIG_KEY_SCORE_MIN = "scoreMin";
+	public static final Float CONFIG_DEFAULT_SCORE_MIN = Float.valueOf(0);
 	/** configuration: score max value */
 	public static final String CONFIG_KEY_SCORE_MAX = "scoreMax";
+	public static final Float CONFIG_DEFAULT_SCORE_MAX = Float.valueOf(0);
 	/** configuration: passed can be set */
 	public static final String CONFIG_KEY_HAS_PASSED_FIELD = "hasPassedField";
 	/** configuration: passed set to when score higher than cut value */
@@ -104,13 +121,23 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	public static final String CONFIG_KEY_INFOTEXT_COACH = "nfoTextCoach";
 	/** configuration: infotext for coach */
 	public static final String CONFIG_KEY_OPTIONAL = "cnOptional";
+	
+	public static final String CONFIG_KEY_SCORE = "score";
+	public static final String CONFIG_VALUE_SCORE_NONE = "score.none";
+	public static final String CONFIG_VALUE_SCORE_MANUAL = "score.manual";
+	public static final String CONFIG_VALUE_SCORE_EVAL_FORM_SUM = "score.evaluation.form.sum";
+	public static final String CONFIG_VALUE_SCORE_EVAL_FORM_AVG = "score.evaluation.form.avg";
+	public static final String CONFIG_KEY_EVAL_FORM_ENABLED = "evaluation.form.enabled";
+	public static final String CONFIG_KEY_EVAL_FORM_SOFTKEY = "evaluation.form.softkey";
+	public static final String CONFIG_KEY_EVAL_FORM_SCALE = "evaluation.form.scale";
+	public static final String CONFIG_DEFAULT_EVAL_FORM_SCALE = "1.0";
 
 	/**
 	 * Constructor for a course building block of type manual score
 	 */
 	public MSCourseNode() {
 		super(TYPE);
-		MSCourseNode.initDefaultConfig(getModuleConfiguration());
+		updateModuleConfigDefaults(true);
 	}
 
 	/**
@@ -121,32 +148,47 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 	 */
 	public static void initDefaultConfig(ModuleConfiguration moduleConfiguration) {
 		moduleConfiguration.set(CONFIG_KEY_HAS_SCORE_FIELD, Boolean.FALSE);
-		moduleConfiguration.set(CONFIG_KEY_SCORE_MIN, Float.valueOf(0));
-		moduleConfiguration.set(CONFIG_KEY_SCORE_MAX, Float.valueOf(0));
+		moduleConfiguration.set(CONFIG_KEY_SCORE_MIN, CONFIG_DEFAULT_SCORE_MIN);
+		moduleConfiguration.set(CONFIG_KEY_SCORE_MAX, CONFIG_DEFAULT_SCORE_MAX);
 		moduleConfiguration.set(CONFIG_KEY_HAS_PASSED_FIELD, Boolean.TRUE);
 		// no preset for passed cut value -> manual setting of passed
 		moduleConfiguration.set(CONFIG_KEY_HAS_COMMENT_FIELD, Boolean.TRUE);
 		moduleConfiguration.set(CONFIG_KEY_INFOTEXT_USER, "");
 		moduleConfiguration.set(CONFIG_KEY_INFOTEXT_COACH, "");
 	}
+	
+	@Override
+	public void updateModuleConfigDefaults(boolean isNewNode) {
+		ModuleConfiguration config = getModuleConfiguration();
+		if (isNewNode) {
+			initDefaultConfig(config);
+			config.setStringValue(CONFIG_KEY_SCORE, CONFIG_VALUE_SCORE_NONE);
+		}
+		if (config.getConfigurationVersion() < 2) {
+			// migrate legacy configs
+			boolean hasScoreFiled = config.getBooleanSafe(CONFIG_KEY_HAS_SCORE_FIELD, false);
+			if (hasScoreFiled) {
+				config.setStringValue(CONFIG_KEY_SCORE, CONFIG_VALUE_SCORE_MANUAL);
+			} else {
+				config.setStringValue(CONFIG_KEY_SCORE, CONFIG_VALUE_SCORE_NONE);
+			}
+			// init configs from v1
+			config.setBooleanEntry(CONFIG_KEY_HAS_INDIVIDUAL_ASSESSMENT_DOCS, false);
+			// new configs
+			config.setBooleanEntry(CONFIG_KEY_EVAL_FORM_ENABLED, false);
+			config.setStringValue(CONFIG_KEY_EVAL_FORM_SCALE, CONFIG_DEFAULT_EVAL_FORM_SCALE);
+		}
+		config.setConfigurationVersion(CURRENT_VERSION);
+	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#createEditController(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.control.WindowControl, org.olat.course.ICourse)
-	 */
 	@Override
 	public TabbableController createEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel, ICourse course, UserCourseEnvironment euce) {
+		updateModuleConfigDefaults(false);
 		MSCourseNodeEditController childTabCntrllr = new MSCourseNodeEditController(ureq, wControl, this, course, euce);
 		CourseNode chosenNode = course.getEditorTreeModel().getCourseNode(euce.getCourseEditorEnv().getCurrentCourseNodeId());
 		return new NodeEditController(ureq, wControl, course.getEditorTreeModel(), course, chosenNode, euce, childTabCntrllr);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#createNodeRunConstructionResult(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.control.WindowControl,
-	 *      org.olat.course.run.userview.UserCourseEnvironment,
-	 *      org.olat.course.run.userview.NodeEvaluation)
-	 */
 	@Override
 	public NodeRunConstructionResult createNodeRunConstructionResult(UserRequest ureq, WindowControl wControl,
 			UserCourseEnvironment userCourseEnv, NodeEvaluation ne, String nodecmd) {
@@ -166,64 +208,70 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return new NodeRunConstructionResult(wrappedCtrl);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#getReferencedRepositoryEntry()
-	 */
 	@Override
 	public RepositoryEntry getReferencedRepositoryEntry() {
-		return null;
+		return getEvaluationForm(getModuleConfiguration());
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#needsReferenceToARepositoryEntry()
-	 */
 	@Override
 	public boolean needsReferenceToARepositoryEntry() {
-		return false;
+		return getReferencedRepositoryEntry() != null? true: false;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#isConfigValid()
-	 */
+	@SuppressWarnings("deprecation")
+	@Override
+	public StatusDescription[] isConfigValid(CourseEditorEnv cev) {
+		String translatorStr = Util.getPackageName(ConditionEditController.class);
+		List<StatusDescription> statusDescs = isConfigValidWithTranslator(cev, translatorStr, getConditionExpressions());
+		return StatusDescriptionHelper.sort(statusDescs);
+	}
+	
 	@Override
 	public StatusDescription isConfigValid() {
-		/*
-		 * first check the one click cache
-		 */
-		if (oneClickStatusCache != null) { return oneClickStatusCache[0]; }
-
-		boolean isValid = MSEditFormController.isConfigValid(getModuleConfiguration());
-		StatusDescription sd = StatusDescription.NOERROR;
-		if (!isValid) {
-			// FIXME: refine statusdescriptions by moving the statusdescription
-			// generation to the MSEditForm
-			String shortKey = "error.missingconfig.short";
-			String longKey = "error.missingconfig.long";
-			String[] params = new String[] { this.getShortTitle() };
-			sd = new StatusDescription(StatusDescription.ERROR, shortKey, longKey, params, PACKAGE_MS);
-			sd.setDescriptionForUnit(getIdent());
-			// set which pane is affected by error
-			sd.setActivateableViewIdentifier(MSCourseNodeEditController.PANE_TAB_CONFIGURATION);
-		}
-		return sd;
+		return  StatusDescription.NOERROR;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#isConfigValid(org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
-	public StatusDescription[] isConfigValid(CourseEditorEnv cev) {
-		oneClickStatusCache = null;
-		// only here we know which translator to take for translating condition
-		// error messages
-		List<StatusDescription> sds = isConfigValidWithTranslator(cev, PACKAGE_MS, getConditionExpressions());
-		oneClickStatusCache = StatusDescriptionHelper.sort(sds);
-		return oneClickStatusCache;
+	public void exportNode(File exportDirectory, ICourse course) {
+		RepositoryEntry re = getEvaluationForm(getModuleConfiguration());
+		if (re == null) return;
+		
+		File fExportDirectory = new File(exportDirectory, getIdent());
+		fExportDirectory.mkdirs();
+		RepositoryEntryImportExport reie = new RepositoryEntryImportExport(re, fExportDirectory);
+		reie.exportDoExport();
+	}
+	
+	@Override
+	public void importNode(File importDirectory, ICourse course, Identity owner, Organisation organisation, Locale locale, boolean withReferences) {
+		RepositoryEntryImportExport rie = new RepositoryEntryImportExport(importDirectory, getIdent());
+		if(withReferences && rie.anyExportedPropertiesAvailable()) {
+			RepositoryHandler handler = RepositoryHandlerFactory.getInstance().getRepositoryHandler(EvaluationFormResource.TYPE_NAME);
+			RepositoryEntry re = handler.importResource(owner, rie.getInitialAuthor(), rie.getDisplayName(),
+				rie.getDescription(), false, organisation, locale, rie.importGetExportedFile(), null);
+			setEvaluationFormReference(re, getModuleConfiguration());
+		} else {
+			removeEvaluationFormReference(getModuleConfiguration());
+		}
+	}
+
+	public static RepositoryEntry getEvaluationForm(ModuleConfiguration config) {
+		if (config == null) return null;
+		
+		String repoSoftkey = config.getStringValue(CONFIG_KEY_EVAL_FORM_SOFTKEY);
+		if (!StringHelper.containsNonWhitespace(repoSoftkey)) return null;
+		
+		return RepositoryManager.getInstance().lookupRepositoryEntryBySoftkey(repoSoftkey, false);
+	}
+	
+	public static void setEvaluationFormReference(RepositoryEntry re, ModuleConfiguration moduleConfig) {
+		moduleConfig.set(CONFIG_KEY_EVAL_FORM_SOFTKEY, re.getSoftkey());
+	}
+	
+	public static void removeEvaluationFormReference(ModuleConfiguration moduleConfig) {
+		moduleConfig.remove(CONFIG_KEY_EVAL_FORM_SOFTKEY);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getUserScoreEvaluation(org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
 	public AssessmentEvaluation getUserScoreEvaluation(UserCourseEnvironment userCourseEnv) {
 		if(hasPassedConfigured() || hasScoreConfigured() || hasCommentConfigured()) {
@@ -244,10 +292,6 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return am.getAssessmentEntry(this, mySelf);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#informOnDelete(org.olat.core.gui.UserRequest,
-	 *      org.olat.course.ICourse)
-	 */
 	@Override
 	public String informOnDelete(Locale locale, ICourse course) {
 		CoursePropertyManager cpm = PersistingCoursePropertyManager.getInstance(course);
@@ -257,10 +301,6 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return trans.translate("warn.nodedelete");
 	}
 
-	/**
-	 * @see org.olat.course.nodes.CourseNode#cleanupOnDelete(
-	 *      org.olat.course.ICourse)
-	 */
 	@Override
 	public void cleanupOnDelete(ICourse course) {
 		super.cleanupOnDelete(course);
@@ -271,11 +311,13 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		
 		OLATResource resource = course.getCourseEnvironment().getCourseGroupManager().getCourseResource();
 		CoreSpringFactory.getImpl(TaskExecutorManager.class).delete(resource, getIdent());
+		
+		// Delete the surveys
+		MSService msService = CoreSpringFactory.getImpl(MSService.class);
+		RepositoryEntry ores = RepositoryManager.getInstance().lookupRepositoryEntry(course, true);
+		msService.deleteSessions(ores, getIdent());
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#hasCommentConfigured()
-	 */
 	@Override
 	public boolean hasCommentConfigured() {
 		ModuleConfiguration config = getModuleConfiguration();
@@ -289,9 +331,6 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return getModuleConfiguration().getBooleanSafe(CONFIG_KEY_HAS_INDIVIDUAL_ASSESSMENT_DOCS, false);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#hasPassedConfigured()
-	 */
 	@Override
 	public boolean hasPassedConfigured() {
 		ModuleConfiguration config = getModuleConfiguration();
@@ -300,20 +339,14 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return passed.booleanValue();
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#hasScoreConfigured()
-	 */
 	@Override
 	public boolean hasScoreConfigured() {
+		updateModuleConfigDefaults(false);
 		ModuleConfiguration config = getModuleConfiguration();
-		Boolean score = (Boolean) config.get(CONFIG_KEY_HAS_SCORE_FIELD);
-		if (score == null) return false;
-		return score.booleanValue();
+		String scoreKey = config.getStringValue(CONFIG_KEY_SCORE);
+		return !CONFIG_VALUE_SCORE_NONE.equals(scoreKey);
 	}
 	
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#hasStatusConfigured()
-	 */
 	@Override
 	public boolean hasStatusConfigured() {
 		return false;
@@ -324,31 +357,37 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return false;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getMaxScoreConfiguration()
-	 */
 	@Override
 	public Float getMaxScoreConfiguration() {
-		if (!hasScoreConfigured()) { throw new OLATRuntimeException(MSCourseNode.class, "getMaxScore not defined when hasScore set to false", null); }
-		ModuleConfiguration config = getModuleConfiguration();
-		Float max = (Float) config.get(CONFIG_KEY_SCORE_MAX);
-		return max;
+		if (!hasScoreConfigured()) { throw new OLATRuntimeException(MSCourseNode.class, "getMaxScore not defined", null); }
+		return getMinMax().getMax();
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getMinScoreConfiguration()
-	 */
 	@Override
 	public Float getMinScoreConfiguration() {
-		if (!hasScoreConfigured()) { throw new OLATRuntimeException(MSCourseNode.class, "getMinScore not defined when hasScore set to false", null); }
+		if (!hasScoreConfigured()) { throw new OLATRuntimeException(MSCourseNode.class, "getMinScore not defined", null); }
+		return getMinMax().getMin();
+	}
+	
+	private MinMax getMinMax() {
 		ModuleConfiguration config = getModuleConfiguration();
-		Float min = (Float) config.get(CONFIG_KEY_SCORE_MIN);
-		return min;
+		String scoreConfig = config.getStringValue(CONFIG_KEY_SCORE);
+		String scaleConfig = config.getStringValue(CONFIG_KEY_EVAL_FORM_SCALE);
+		
+		if (CONFIG_VALUE_SCORE_MANUAL.equals(scoreConfig)) {
+			Float min = (Float) config.get(CONFIG_KEY_SCORE_MIN);
+			Float max = (Float) config.get(CONFIG_KEY_SCORE_MAX);
+			return MinMax.of(min, max);
+		} else if (CONFIG_VALUE_SCORE_EVAL_FORM_SUM.equals(scoreConfig)) {
+			MSService msService = CoreSpringFactory.getImpl(MSService.class);
+			return  msService.calculateMinMaxSum(getEvaluationForm(config), Float.parseFloat(scaleConfig));
+		} else if (CONFIG_VALUE_SCORE_EVAL_FORM_AVG.equals(scoreConfig)) {
+			MSService msService = CoreSpringFactory.getImpl(MSService.class);
+			return  msService.calculateMinMaxAvg(getEvaluationForm(config), Float.parseFloat(scaleConfig));
+		}
+		return MinMax.of(0.0f,  0.0f);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getCutValueConfiguration()
-	 */
 	@Override
 	public Float getCutValueConfiguration() {
 		if (!hasPassedConfigured()) { throw new OLATRuntimeException(MSCourseNode.class, "getCutValue not defined when hasPassed set to false", null); }
@@ -357,9 +396,6 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return cut;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getUserCoachComment(org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
 	public String getUserCoachComment(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
@@ -367,9 +403,6 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return coachCommentValue;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getUserUserComment(org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
 	public String getUserUserComment(UserCourseEnvironment userCourseEnvironment) {
 		AssessmentManager am = userCourseEnvironment.getCourseEnvironment().getAssessmentManager();
@@ -382,9 +415,6 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return am.getIndividualAssessmentDocuments(this, userCourseEnvironment.getIdentityEnvironment().getIdentity());
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getUserLog(org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
 	public String getUserLog(UserCourseEnvironment userCourseEnvironment) {
 		UserNodeAuditManager am = userCourseEnvironment.getCourseEnvironment().getAuditManager();
@@ -392,19 +422,12 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return logValue;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#isEditableConfigured()
-	 */
 	@Override
 	public boolean isEditableConfigured() {
 		// manual scoring fields can be edited manually
 		return true;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#updateUserCoachComment(java.lang.String,
-	 *      org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
 	public void updateUserCoachComment(String coachComment, UserCourseEnvironment userCourseEnvironment) {
 		if (coachComment != null) {
@@ -414,11 +437,6 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		}
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#updateUserScoreEvaluation(org.olat.course.run.scoring.ScoreEvaluation,
-	 *      org.olat.course.run.userview.UserCourseEnvironment,
-	 *      org.olat.core.id.Identity)
-	 */
 	@Override
 	public void updateUserScoreEvaluation(ScoreEvaluation scoreEvaluation, UserCourseEnvironment userCourseEnvironment,
 			Identity coachingIdentity, boolean incrementAttempts, Role by) {
@@ -427,11 +445,6 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		am.saveScoreEvaluation(this, coachingIdentity, mySelf, new ScoreEvaluation(scoreEvaluation), userCourseEnvironment, incrementAttempts, by);		
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#updateUserUserComment(java.lang.String,
-	 *      org.olat.course.run.userview.UserCourseEnvironment,
-	 *      org.olat.core.id.Identity)
-	 */
 	@Override
 	public void updateUserUserComment(String userComment, UserCourseEnvironment userCourseEnvironment, Identity coachingIdentity) {
 		if (userComment != null) {
@@ -459,36 +472,22 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		}
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getUserAttempts(org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
 	public Integer getUserAttempts(UserCourseEnvironment userCourseEnvironment) {
 		throw new OLATRuntimeException(MSCourseNode.class, "No attempts available in MS nodes", null);
 
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#hasAttemptsConfigured()
-	 */
 	@Override
 	public boolean hasAttemptsConfigured() {
 		return false;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#updateUserAttempts(java.lang.Integer,
-	 *      org.olat.course.run.userview.UserCourseEnvironment,
-	 *      org.olat.core.id.Identity)
-	 */
 	@Override
 	public void updateUserAttempts(Integer userAttempts, UserCourseEnvironment userCourseEnvironment, Identity coachingIdentity, Role by) {
 		throw new OLATRuntimeException(MSCourseNode.class, "Attempts variable can't be updated in MS nodes", null);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#incrementUserAttempts(org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
 	public void incrementUserAttempts(UserCourseEnvironment userCourseEnvironment, Role by) {
 		throw new OLATRuntimeException(MSCourseNode.class, "Attempts variable can't be updated in MS nodes", null);
@@ -517,15 +516,10 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		am.updateLastModifications(this, assessedIdentity, userCourseEnvironment, by);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getDetailsEditController(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.control.WindowControl,
-	 *      org.olat.course.run.userview.UserCourseEnvironment)
-	 */
 	@Override
 	public Controller getDetailsEditController(UserRequest ureq, WindowControl wControl, BreadcrumbPanel stackPanel,
-			UserCourseEnvironment coachCourseenv, UserCourseEnvironment assessedUserCourseEnv) {
-		throw new OLATRuntimeException(MSCourseNode.class, "Details controler not available in MS nodes", null);
+			UserCourseEnvironment coachCourseEnv, UserCourseEnvironment assessedUserCourseEnv) {
+		return new MSEvaluationFormExecutionController(ureq, wControl, assessedUserCourseEnv, this);
 	}
 	
 	@Override
@@ -541,20 +535,61 @@ public class MSCourseNode extends AbstractAccessableCourseNode implements Persis
 		return null;
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#getDetailsListViewHeaderKey()
-	 */
 	@Override
 	public String getDetailsListViewHeaderKey() {
 		throw new OLATRuntimeException(MSCourseNode.class, "Details not available in MS nodes", null);
 	}
 
-	/**
-	 * @see org.olat.course.nodes.AssessableCourseNode#hasDetails()
-	 */
 	@Override
 	public boolean hasDetails() {
-		return false;
+		return getModuleConfiguration().getBooleanSafe(CONFIG_KEY_EVAL_FORM_ENABLED);
 	}
-
+	
+	public void updateScoreEvaluation(Identity identity, UserCourseEnvironment assessedUserCourseEnv,
+			Identity assessedIdentity, Role by, EvaluationFormSession session) {
+		AssessmentManager am = assessedUserCourseEnv.getCourseEnvironment().getAssessmentManager();
+		MSService msService = CoreSpringFactory.getImpl(MSService.class);
+		ModuleConfiguration config = getModuleConfiguration();
+		
+		// Get score
+		String scoreConfig = config.getStringValue(CONFIG_KEY_SCORE);
+		String scaleConfig = config.getStringValue(CONFIG_KEY_EVAL_FORM_SCALE);
+		float scale = Float.parseFloat(scaleConfig);
+		Float score = null;
+		if (CONFIG_VALUE_SCORE_EVAL_FORM_AVG.equals(scoreConfig)) {
+			score = msService.calculateScoreByAvg(session);
+			score = msService.scaleScore(score, scale);
+		} else if (CONFIG_VALUE_SCORE_EVAL_FORM_SUM.equals(scoreConfig)) {
+			score = msService.calculateScoreBySum(session);
+			score = msService.scaleScore(score, scale);
+		} else if (CONFIG_VALUE_SCORE_MANUAL.equals(scoreConfig)) {
+			ScoreEvaluation currentEval = getUserScoreEvaluation(am.getAssessmentEntry(this, assessedIdentity));
+			score = currentEval.getScore();
+		}
+		
+		// Score has to be in configured range.
+		MinMax minMax = getMinMax();
+		if(score != null && minMax.getMax().floatValue() < score.floatValue()) {
+			score = minMax.getMax();
+		}
+		if(score != null && minMax.getMin().floatValue() > score.floatValue()) {
+			score = minMax.getMin();
+		}
+		
+		// Get passed
+		Float cutConfig = (Float) config.get(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
+		Boolean passed = null;
+		if (cutConfig != null && score != null) {
+			boolean aboveCutValue = score.floatValue() >= cutConfig.floatValue();
+			passed = Boolean.valueOf(aboveCutValue);
+		} else {
+			ScoreEvaluation currentEval = getUserScoreEvaluation(am.getAssessmentEntry(this, assessedIdentity));
+			passed = currentEval.getPassed();
+		}
+		
+		// save
+		ScoreEvaluation scoreEvaluation = new ScoreEvaluation(score, passed);
+		am.saveScoreEvaluation(this, identity, assessedIdentity, scoreEvaluation, assessedUserCourseEnv, false, by);
+	}
+	
 }
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/SurveyCourseNode.java b/src/main/java/org/olat/course/nodes/SurveyCourseNode.java
index b532fe686f40bb4f8fe07c6fd5a38c8be400296c..a638274235ab0b7abe7deb01b1445e2b334bbdd8 100644
--- a/src/main/java/org/olat/course/nodes/SurveyCourseNode.java
+++ b/src/main/java/org/olat/course/nodes/SurveyCourseNode.java
@@ -19,12 +19,15 @@
  */
 package org.olat.course.nodes;
 
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.List;
 import java.util.Locale;
 import java.util.zip.ZipOutputStream;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.stack.BreadcrumbPanel;
@@ -33,7 +36,6 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.tabbable.TabbableController;
 import org.olat.core.id.Identity;
 import org.olat.core.id.Organisation;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
@@ -56,6 +58,7 @@ import org.olat.course.statistic.StatisticType;
 import org.olat.modules.ModuleConfiguration;
 import org.olat.modules.forms.EvaluationFormManager;
 import org.olat.modules.forms.EvaluationFormSurvey;
+import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
 import org.olat.modules.forms.SessionFilter;
 import org.olat.modules.forms.SessionFilterFactory;
 import org.olat.modules.forms.handler.EvaluationFormResource;
@@ -165,7 +168,7 @@ public class SurveyCourseNode extends AbstractAccessableCourseNode {
 			RepositoryEntry ores = userCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
 			SurveyRunSecurityCallback secCallback = new SurveyRunSecurityCallback(getModuleConfiguration(), userCourseEnv);
 			Identity identity = userCourseEnv.getIdentityEnvironment().getIdentity();
-			return new SurveyStatisticResourceResult(ores, getIdent(), identity, secCallback);
+			return new SurveyStatisticResourceResult(of(ores, getIdent()), identity, secCallback);
 		}
 		return null;
 	}
@@ -241,9 +244,10 @@ public class SurveyCourseNode extends AbstractAccessableCourseNode {
 		RepositoryEntry ores = RepositoryManager.getInstance().lookupRepositoryEntry(course, true);
 		EvaluationFormManager evaluationFormManager = CoreSpringFactory.getImpl(EvaluationFormManager.class);
 		RepositoryEntry formEntry = getEvaluationForm(getModuleConfiguration());
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(ores, getIdent());
+		EvaluationFormSurveyIdentifier surveyIdent = of(ores, getIdent());
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(surveyIdent);
 		if (survey == null) {
-			survey = evaluationFormManager.createSurvey(ores, getIdent(), formEntry);
+			survey = evaluationFormManager.createSurvey(surveyIdent, formEntry);
 		} else {
 			boolean isFormUpdateable = evaluationFormManager.isFormUpdateable(survey);
 			if (isFormUpdateable) {
@@ -258,7 +262,7 @@ public class SurveyCourseNode extends AbstractAccessableCourseNode {
 		EvaluationFormManager evaluationFormManager = CoreSpringFactory.getImpl(EvaluationFormManager.class);
 		
 		RepositoryEntry ores = RepositoryManager.getInstance().lookupRepositoryEntry(course, true);
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(ores, getIdent());
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(of(ores, getIdent()));
 		SessionFilter filter = SessionFilterFactory.createSelectDone(survey);
 		Form form = evaluationFormManager.loadForm(survey.getFormEntry());
 		
@@ -282,7 +286,7 @@ public class SurveyCourseNode extends AbstractAccessableCourseNode {
 		
 		EvaluationFormManager evaluationFormManager = CoreSpringFactory.getImpl(EvaluationFormManager.class);
 		RepositoryEntry ores = RepositoryManager.getInstance().lookupRepositoryEntry(course, true);
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(ores, getIdent());
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(of(ores, getIdent()));
 		evaluationFormManager.deleteSurvey(survey);
 	}
 
diff --git a/src/main/java/org/olat/course/nodes/TACourseNode.java b/src/main/java/org/olat/course/nodes/TACourseNode.java
index 80b9fb9f4a3befcdbf415ad2965ece318c76131b..0755cc00da598c291fb8a7a36e0e26a24aa51cfc 100644
--- a/src/main/java/org/olat/course/nodes/TACourseNode.java
+++ b/src/main/java/org/olat/course/nodes/TACourseNode.java
@@ -38,6 +38,7 @@ import java.util.Set;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.modules.bc.FolderConfig;
 import org.olat.core.commons.services.taskexecutor.TaskExecutorManager;
@@ -54,7 +55,6 @@ import org.olat.core.id.Identity;
 import org.olat.core.id.Organisation;
 import org.olat.core.id.Roles;
 import org.olat.core.logging.OLATRuntimeException;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.ExportUtil;
 import org.olat.core.util.FileUtils;
diff --git a/src/main/java/org/olat/course/nodes/ms/MSConfigController.java b/src/main/java/org/olat/course/nodes/ms/MSConfigController.java
new file mode 100644
index 0000000000000000000000000000000000000000..823bd40b87641ecad1a0f34c581d06b47510ec23
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/ms/MSConfigController.java
@@ -0,0 +1,574 @@
+/**
+ * <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.nodes.ms;
+
+import static org.olat.core.gui.components.util.KeyValues.entry;
+import static org.olat.core.gui.translator.TranslatorHelper.translateAll;
+import static org.olat.modules.forms.handler.EvaluationFormResource.FORM_XML_FILE;
+
+import java.io.File;
+import java.util.Map;
+
+import org.olat.NewControllerFactory;
+import org.olat.core.commons.fullWebApp.LayoutMain3ColsPreviewController;
+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.elements.RichTextElement;
+import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
+import org.olat.core.gui.components.form.flexible.elements.StaticTextElement;
+import org.olat.core.gui.components.form.flexible.elements.TextElement;
+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.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.course.ICourse;
+import org.olat.course.nodes.MSCourseNode;
+import org.olat.fileresource.FileResourceManager;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.ceditor.DataStorage;
+import org.olat.modules.forms.EvaluationFormManager;
+import org.olat.modules.forms.handler.EvaluationFormResource;
+import org.olat.modules.forms.ui.EvaluationFormExecutionController;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryManager;
+import org.olat.repository.controllers.ReferencableEntriesSearchController;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 10 Jun 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public class MSConfigController extends FormBasicController {
+	
+	private static final String[] EMPTY_ARRAY = new String[]{};
+	private static final String[] ENABLED_KEYS = new String[]{"on"};
+
+	private MultipleSelectionElement evaluationFormEnabledEl;
+	private StaticTextElement evaluationFormNotChoosen;
+	private FormLink evaluationFormLink;
+	private FormLink chooseLink;
+	private FormLink replaceLink;
+	private FormLink editLink;
+	private SingleSelection scoreEl;
+	private TextElement minEl;
+	private TextElement maxEl;
+	private TextElement scaleEl;
+	private MultipleSelectionElement passedEl;
+	private SingleSelection passedTypeEl;
+	private String[] trueFalseKeys;
+	private String[] passedTypeValues;
+	private TextElement cutEl;
+	private MultipleSelectionElement commentFlagEl;
+	private MultipleSelectionElement individualAssessmentDocsFlagEl;
+	private RichTextElement infotextUserEl;
+	private RichTextElement infotextCoachEl;
+	
+	private CloseableModalController cmc;
+	private ReferencableEntriesSearchController searchCtrl;
+	private LayoutMain3ColsPreviewController previewCtr;
+	
+	private final ModuleConfiguration config;
+	private final OLATResourceable ores;
+	private final String nodeIdent;
+	private RepositoryEntry formEntry;
+	private MinMax formMinMax;
+	
+	@Autowired
+	private MSService msService;
+	@Autowired
+	private EvaluationFormManager evaluationFormManager;
+
+	public MSConfigController(UserRequest ureq, WindowControl wControl, ICourse course,
+			MSCourseNode courseNode) {
+		super(ureq, wControl, FormBasicController.LAYOUT_DEFAULT);
+		this.config = courseNode.getModuleConfiguration();
+		this.ores = RepositoryManager.getInstance().lookupRepositoryEntry(course, true);
+		this.nodeIdent = courseNode.getIdent();
+		this.formEntry = MSCourseNode.getEvaluationForm(config);
+		doCalculateMinMax();
+		
+		trueFalseKeys = new String[] { Boolean.TRUE.toString(), Boolean.FALSE.toString() };
+		passedTypeValues = new String[] { translate("form.passedtype.cutval"), translate("form.passedtype.manual") };
+		
+		initForm(ureq);
+	}
+	
+	public void setDisplayOnly(boolean displayOnly) {
+		Map<String, FormItem> formItems = flc.getFormComponents();
+		for (String formItemName : formItems.keySet()) {
+			formItems.get(formItemName).setEnabled(!displayOnly);
+		}
+	}
+	
+	@Override
+	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+		// Evaluation Form
+		evaluationFormEnabledEl = uifactory.addCheckboxesHorizontal("form.evaluation.enabled", formLayout,
+				ENABLED_KEYS, translateAll(getTranslator(), ENABLED_KEYS));
+		evaluationFormEnabledEl.addActionListener(FormEvent.ONCHANGE);
+		Boolean evalFormEnabled = config.getBooleanEntry(MSCourseNode.CONFIG_KEY_EVAL_FORM_ENABLED);
+		evaluationFormEnabledEl.select(ENABLED_KEYS[0], evalFormEnabled);
+		
+		evaluationFormNotChoosen = uifactory.addStaticTextElement("form.evaluation.not.choosen", "form.evaluation",
+				translate("form.evaluation.not.choosen"), formLayout);
+		evaluationFormLink = uifactory.addFormLink("form.evaluation", "", translate("form.evaluation"), formLayout,
+				Link.NONTRANSLATED);
+		evaluationFormLink.setIconLeftCSS("o_icon o_icon-fw o_icon_preview");
+		
+		FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
+		buttonsCont.setRootForm(mainForm);
+		formLayout.add(buttonsCont);
+		chooseLink = uifactory.addFormLink("form.evaluation.choose", buttonsCont, "btn btn-default o_xsmall");
+		replaceLink = uifactory.addFormLink("form.evaluation.replace", buttonsCont, "btn btn-default o_xsmall");
+		editLink = uifactory.addFormLink("form.evaluation.edit", buttonsCont, "btn btn-default o_xsmall");
+		
+		uifactory.addSpacerElement("spacer0", formLayout, false);
+		
+		// Points
+		scoreEl = uifactory.addDropdownSingleselect("form.score", formLayout, EMPTY_ARRAY, EMPTY_ARRAY);
+		scoreEl.addActionListener(FormEvent.ONCHANGE);
+		
+		// Scale
+		String scale = config.getStringValue(MSCourseNode.CONFIG_KEY_EVAL_FORM_SCALE);
+		scaleEl = uifactory.addTextElement("form.scale", "form.scale", 8, scale, formLayout);
+		scaleEl.addActionListener(FormEvent.ONCHANGE);
+		
+		// Minimum
+		Float min = (Float) config.get(MSCourseNode.CONFIG_KEY_SCORE_MIN);
+		min = min != null? min: MSCourseNode.CONFIG_DEFAULT_SCORE_MIN;
+		minEl = uifactory.addTextElement("form.min", "form.min", 8, min.toString(), formLayout);
+		
+		// Maximim
+		Float max = (Float) config.get(MSCourseNode.CONFIG_KEY_SCORE_MAX);
+		max = max != null? max: MSCourseNode.CONFIG_DEFAULT_SCORE_MAX;
+		maxEl = uifactory.addTextElement("form.max", "form.max", 8, max.toString(), formLayout);
+		
+		uifactory.addSpacerElement("spacer1", formLayout, false);
+		
+		// display passed / failed
+		passedEl = uifactory.addCheckboxesHorizontal("form.passed", formLayout, ENABLED_KEYS,
+				translateAll(getTranslator(), ENABLED_KEYS));
+		passedEl.addActionListener(FormEvent.ONCLICK);
+		Boolean passedField = config.getBooleanEntry(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD);
+		passedEl.select(ENABLED_KEYS[0], passedField);
+
+		// passed/failed manually or automatically
+		passedTypeEl = uifactory.addRadiosVertical("form.passed.type", formLayout, trueFalseKeys, passedTypeValues);
+		passedTypeEl.addActionListener(FormEvent.ONCLICK);
+		passedTypeEl.setElementCssClass("o_sel_course_ms_display_type");
+
+		Float cut = (Float) config.get(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
+		if (cut != null) {
+			passedTypeEl.select(trueFalseKeys[0], true);
+		} else {
+			passedTypeEl.select(trueFalseKeys[1], true);
+			cut = new Float(0.0);
+		}
+
+		// Passing grade cut value
+		cutEl = uifactory.addTextElement("form.cut", "form.cut", 8, cut.toString(), formLayout);
+
+		uifactory.addSpacerElement("spacer2", formLayout, false);
+
+		// Comments
+		commentFlagEl = uifactory.addCheckboxesHorizontal("form.comment", formLayout, ENABLED_KEYS,
+				translateAll(getTranslator(), ENABLED_KEYS));
+		Boolean commentField = config.getBooleanEntry(MSCourseNode.CONFIG_KEY_HAS_COMMENT_FIELD);
+		commentFlagEl.select(ENABLED_KEYS[0], commentField.booleanValue());
+		
+		individualAssessmentDocsFlagEl = uifactory.addCheckboxesHorizontal("form.individual.assessment.docs", formLayout, ENABLED_KEYS,
+				translateAll(getTranslator(), ENABLED_KEYS));
+		Boolean docsCf = config.getBooleanSafe(MSCourseNode.CONFIG_KEY_HAS_INDIVIDUAL_ASSESSMENT_DOCS, false);
+		individualAssessmentDocsFlagEl.select(ENABLED_KEYS[0], docsCf);
+
+		uifactory.addSpacerElement("spacer3", formLayout, false);
+
+		// Create the rich text fields.
+		String infoUser = (String) config.get(MSCourseNode.CONFIG_KEY_INFOTEXT_USER);
+		infoUser = infoUser != null? infoUser: "";
+		infotextUserEl = uifactory.addRichTextElementForStringDataMinimalistic("infotextUser", "form.infotext.user",
+				infoUser, 10, -1, formLayout, getWindowControl());
+
+		String infoCoach = (String) config.get(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH);
+		infoCoach = infoCoach != null? infoCoach: "";
+		infotextCoachEl = uifactory.addRichTextElementForStringDataMinimalistic("infotextCoach", "form.infotext.coach",
+				infoCoach, 10, -1, formLayout, getWindowControl());
+
+		uifactory.addFormSubmitButton("save", formLayout);
+		
+		updateUI();
+	}
+	
+	private void updateUI() {
+		boolean formEnabled = evaluationFormEnabledEl.isAtLeastSelected(1);
+		boolean replacePossible = !msService.hasSessions(ores, nodeIdent);
+
+		if (formEntry != null) {
+			String displayname = StringHelper.escapeHtml(formEntry.getDisplayname());
+			evaluationFormLink.setI18nKey(displayname);
+			flc.setDirty(true);
+		}
+		boolean hasFormConfig = formEntry != null;
+		evaluationFormNotChoosen.setVisible(formEnabled && !hasFormConfig);
+		chooseLink.setVisible(formEnabled && !hasFormConfig);
+		evaluationFormLink.setVisible(formEnabled && hasFormConfig);
+		replaceLink.setVisible(formEnabled && hasFormConfig && replacePossible);
+		editLink.setVisible(formEnabled && hasFormConfig);
+
+		// Score
+		String scoreKey = scoreEl.isOneSelected()
+				? scoreEl.getSelectedKey()
+				: config.getStringValue(MSCourseNode.CONFIG_KEY_SCORE);
+		KeyValues scoreKV = new KeyValues();
+		scoreKV.add(entry(MSCourseNode.CONFIG_VALUE_SCORE_NONE, translate("form.score.none")));
+		scoreKV.add(entry(MSCourseNode.CONFIG_VALUE_SCORE_MANUAL, translate("form.score.manual")));
+		if (evaluationFormEnabledEl.isAtLeastSelected(1)) {
+			scoreKV.add(entry(MSCourseNode.CONFIG_VALUE_SCORE_EVAL_FORM_SUM, translate("form.score.eval.sum")));
+			scoreKV.add(entry(MSCourseNode.CONFIG_VALUE_SCORE_EVAL_FORM_AVG, translate("form.score.eval.avg")));
+		}
+		scoreKey = scoreKV.containsKey(scoreKey) ? scoreKey : MSCourseNode.CONFIG_VALUE_SCORE_NONE;
+		scoreEl.setKeysAndValues(scoreKV.keys(), scoreKV.values(), null);
+		scoreEl.select(scoreKey, true);
+
+		// min / max
+		minEl.setEnabled(true);
+		maxEl.setEnabled(true);
+		boolean minMaxVisible = !MSCourseNode.CONFIG_VALUE_SCORE_NONE.equals(scoreKey);
+		minEl.setVisible(minMaxVisible);
+		maxEl.setVisible(minMaxVisible);
+		if (MSCourseNode.CONFIG_VALUE_SCORE_EVAL_FORM_SUM.equals(scoreKey)
+				|| MSCourseNode.CONFIG_VALUE_SCORE_EVAL_FORM_AVG.equals(scoreKey)) {
+			minEl.setValue(formMinMax.getMin().toString());
+			minEl.setEnabled(false);
+			maxEl.setValue(formMinMax.getMax().toString());
+			maxEl.setEnabled(false);
+		}
+
+		// scaling factor
+		boolean scaleVisible = MSCourseNode.CONFIG_VALUE_SCORE_EVAL_FORM_SUM.equals(scoreKey)
+				|| MSCourseNode.CONFIG_VALUE_SCORE_EVAL_FORM_AVG.equals(scoreKey);
+		scaleEl.setVisible(scaleVisible);
+
+		// passed
+		boolean scoreEnabled = !MSCourseNode.CONFIG_VALUE_SCORE_NONE.equals(scoreKey);
+		boolean passedTypeVisible = scoreEnabled && passedEl.isAtLeastSelected(1);
+		passedTypeEl.setVisible(passedTypeVisible);
+
+		// cut value
+		boolean cutVisible = passedTypeVisible && passedTypeEl.isOneSelected() && passedTypeEl.getSelected() == 0;
+		cutEl.setVisible(cutVisible);
+	}
+
+	@Override
+	protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
+		if (source == evaluationFormEnabledEl) {
+			updateUI();
+		} else if (source == chooseLink || source == replaceLink) {
+			doChooseEvaluationForm(ureq);
+		} else if (source == editLink) {
+			doEditEvaluationForm(ureq);
+		} else if (source == evaluationFormLink) {
+			doPreviewEvaluationForm(ureq);
+		} else if (source == scoreEl) {
+			doCalculateMinMax();
+			updateUI();
+		} else if (source == scaleEl) {
+			doCalculateMinMax();
+			updateUI();
+		} else if (source == passedEl) {
+			updateUI();
+		} else if (source == passedTypeEl) {
+			updateUI();
+		}
+		super.formInnerEvent(ureq, source, event);
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if (searchCtrl == source) {
+			if (event == ReferencableEntriesSearchController.EVENT_REPOSITORY_ENTRY_SELECTED) {
+				doReplaceEvaluationForm();
+			}
+			cmc.deactivate();
+			cleanUp();
+		} else if (source == previewCtr) {
+			cleanUp();
+		} else if (cmc == source) {
+			cleanUp();
+		}
+		super.event(ureq, source, event);
+	}
+
+	private void cleanUp() {
+		removeAsListenerAndDispose(previewCtr);
+		removeAsListenerAndDispose(searchCtrl);
+		removeAsListenerAndDispose(cmc);
+		previewCtr = null;
+		searchCtrl = null;
+		cmc = null;
+	}
+	
+	@Override
+	protected boolean validateFormLogic(UserRequest ureq) {
+		boolean allOk = true;
+		
+		evaluationFormNotChoosen.clearError();
+		if (evaluationFormNotChoosen.isVisible() && formEntry == null) {
+			evaluationFormNotChoosen.setErrorKey("form.legende.mandatory", null);
+			allOk = false;
+		}
+		
+		minEl.clearError();
+		maxEl.clearError();
+		boolean minIsFloat = isFloat(minEl.getValue());
+		boolean maxIsFloat = isFloat(maxEl.getValue());
+		if (minEl.isVisible() && minEl.isEnabled()) {
+			if (!minIsFloat) {
+				minEl.setErrorKey("form.error.wrongFloat", null);
+				allOk = false;
+			}
+			if (!maxIsFloat) {
+				maxEl.setErrorKey("form.error.wrongFloat", null);
+				allOk = false;
+			}
+			if (minIsFloat && maxIsFloat && isNotGreaterFloat(minEl.getValue(), maxEl.getValue())) {
+				maxEl.setErrorKey("form.error.minGreaterThanMax", null);
+				allOk = false;
+			}
+		}
+		
+		passedTypeEl.clearError();
+		if (passedTypeEl.isVisible()) {
+			if (!passedTypeEl.isOneSelected()) {
+				passedTypeEl.setErrorKey("form.legende.mandatory", null);
+				allOk = false;
+			}
+		}
+		
+		cutEl.clearError();
+		if (cutEl.isVisible()) {
+			boolean cutIsFloat = isFloat(cutEl.getValue());
+			if (!cutIsFloat) {
+				cutEl.setErrorKey("form.error.wrongFloat", null);
+				allOk = false;
+			}
+			if (cutIsFloat && minIsFloat && maxIsFloat
+					&& notInRange(minEl.getValue(), maxEl.getValue(), cutEl.getValue())) {
+				cutEl.setErrorKey("form.error.cutOutOfRange", null);
+				allOk = false;
+			}
+		}
+		
+		scaleEl.clearError();
+		if (scaleEl.isVisible()) {
+			boolean scaleIsFloat = isFloat(scaleEl.getValue());
+			if (!scaleIsFloat) {
+				scaleEl.setErrorKey("form.error.wrongFloat", null);
+				allOk = false;
+			}
+		}
+		
+		infotextCoachEl.clearError();
+		if (infotextCoachEl.getValue().length() > 4000) {
+			infotextCoachEl.setErrorKey("input.toolong", new String[] {"4000"});
+			allOk = false;
+		}
+		
+		infotextUserEl.clearError();
+		if (infotextUserEl.getValue().length() > 4000) {
+			infotextUserEl.setErrorKey("input.toolong", new String[] {"4000"});
+			allOk = false;
+		}
+		
+		return allOk & super.validateFormLogic(ureq);
+	}
+
+	private boolean isFloat(String val) {
+		if (StringHelper.containsNonWhitespace(val)) {
+			try {
+				Float.parseFloat(val);
+				return true;
+			} catch (NumberFormatException e) {
+				// 
+			}
+		}
+		return false;
+	}
+	
+	private boolean isNotGreaterFloat(String min, String max) {
+		return Float.parseFloat(min) >= Float.parseFloat(max);
+	}
+	
+	private boolean notInRange(String min, String max, String cut) {
+		return Float.parseFloat(cut) < Float.parseFloat(min)
+				|| Float.parseFloat(cut) > Float.parseFloat(max);
+	}
+
+	@Override
+	protected void formOK(UserRequest ureq) {
+		updateConfig();
+		fireEvent(ureq, Event.DONE_EVENT);
+	}
+
+	private void updateConfig() {
+		boolean evalFormEnabled = evaluationFormEnabledEl.isAtLeastSelected(1);
+		config.setBooleanEntry(MSCourseNode.CONFIG_KEY_EVAL_FORM_ENABLED, evalFormEnabled);
+		if (evalFormEnabled) {
+			MSCourseNode.setEvaluationFormReference(formEntry, config);
+		} else {
+			MSCourseNode.removeEvaluationFormReference(config);
+		}
+		
+		config.setStringValue(MSCourseNode.CONFIG_KEY_SCORE, scoreEl.getSelectedKey());
+		
+		Float minScore = minEl.isVisible()
+				? Float.parseFloat(minEl.getValue())
+				: MSCourseNode.CONFIG_DEFAULT_SCORE_MIN;
+		config.set(MSCourseNode.CONFIG_KEY_SCORE_MIN, minScore);
+		
+		Float maxScore = maxEl.isVisible()
+				? Float.parseFloat(maxEl.getValue())
+				: MSCourseNode.CONFIG_DEFAULT_SCORE_MAX;
+		config.set(MSCourseNode.CONFIG_KEY_SCORE_MAX, maxScore);
+		
+		String scale = scaleEl.isVisible()
+				? scaleEl.getValue()
+				: MSCourseNode.CONFIG_DEFAULT_EVAL_FORM_SCALE;
+		config.setStringValue(MSCourseNode.CONFIG_KEY_EVAL_FORM_SCALE, scale);
+		
+		boolean showPassed = passedEl.isAtLeastSelected(1);
+		config.set(MSCourseNode.CONFIG_KEY_HAS_PASSED_FIELD, Boolean.valueOf(showPassed));
+		
+		if (showPassed) {
+			// do cut value
+			Boolean cutAutomatically = Boolean.valueOf(passedTypeEl.getSelectedKey());
+			if (cutAutomatically.booleanValue()) {
+				config.set(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE, Float.valueOf(cutEl.getValue()));
+			} else {
+				config.remove(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
+			}
+		} else {
+			config.remove(MSCourseNode.CONFIG_KEY_PASSED_CUT_VALUE);
+		}
+		
+		Boolean commentFieldEnabled = Boolean.valueOf(commentFlagEl.isSelected(0));
+		config.set(MSCourseNode.CONFIG_KEY_HAS_COMMENT_FIELD, commentFieldEnabled);
+		
+		Boolean individualAssessmentEnabled = Boolean.valueOf(individualAssessmentDocsFlagEl.isSelected(0));
+		config.setBooleanEntry(MSCourseNode.CONFIG_KEY_HAS_INDIVIDUAL_ASSESSMENT_DOCS, individualAssessmentEnabled);
+
+		String infoTextUser = infotextUserEl.getValue();
+		if (StringHelper.containsNonWhitespace(infoTextUser)) {
+			config.set(MSCourseNode.CONFIG_KEY_INFOTEXT_USER, infoTextUser);
+		} else {
+			config.remove(MSCourseNode.CONFIG_KEY_INFOTEXT_USER);
+		}
+
+		String infoTextCoach = infotextCoachEl.getValue();
+		if (StringHelper.containsNonWhitespace(infoTextCoach)) {
+			config.set(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH, infoTextCoach);
+		} else {
+			config.remove(MSCourseNode.CONFIG_KEY_INFOTEXT_COACH);
+		}
+	}
+
+	private void doChooseEvaluationForm(UserRequest ureq) {
+		searchCtrl = new ReferencableEntriesSearchController(getWindowControl(), ureq,
+				EvaluationFormResource.TYPE_NAME, translate("form.evaluation.choose"));
+		this.listenTo(searchCtrl);
+		cmc = new CloseableModalController(getWindowControl(), translate("close"),
+				searchCtrl.getInitialComponent(), true, translate("form.evaluation.choose"));
+		cmc.activate();
+	}
+
+	private void doReplaceEvaluationForm() {
+		formEntry = searchCtrl.getSelectedEntry();
+		doCalculateMinMax();
+		updateUI();
+	}
+
+	private void doCalculateMinMax() {
+		String scoreKey = scoreEl != null && scoreEl.isOneSelected()
+				? scoreEl.getSelectedKey()
+				: config.getStringValue(MSCourseNode.CONFIG_KEY_SCORE);
+		String scale = scaleEl != null
+				? scaleEl.getValue()
+				: config.getStringValue(MSCourseNode.CONFIG_KEY_EVAL_FORM_SCALE);
+		float scalingFactor = floatOrZero(scale);
+				
+		switch (scoreKey) {
+		case MSCourseNode.CONFIG_VALUE_SCORE_EVAL_FORM_SUM:
+			formMinMax = msService.calculateMinMaxSum(formEntry, scalingFactor);
+			break;
+		case MSCourseNode.CONFIG_VALUE_SCORE_EVAL_FORM_AVG:
+			formMinMax = msService.calculateMinMaxAvg(formEntry, scalingFactor);
+			break;
+		default:
+			formMinMax = null;
+		}
+	}
+
+	private float floatOrZero(String val) {
+		try {
+			return Float.parseFloat(val);
+		} catch (NumberFormatException e) {
+			// 
+		}
+		return 0;
+	}
+
+	private void doEditEvaluationForm(UserRequest ureq) {
+		String bPath = "[RepositoryEntry:" + formEntry.getKey() + "][Editor:0]";
+		NewControllerFactory.getInstance().launch(bPath, ureq, getWindowControl());
+	}
+
+	private void doPreviewEvaluationForm(UserRequest ureq) {
+		File repositoryDir = new File(
+				FileResourceManager.getInstance().getFileResourceRoot(formEntry.getOlatResource()),
+				FileResourceManager.ZIPDIR);
+		File formFile = new File(repositoryDir, FORM_XML_FILE);
+		DataStorage storage = evaluationFormManager.loadStorage(formEntry);
+		Controller controller = new EvaluationFormExecutionController(ureq, getWindowControl(), formFile, storage);
+
+		previewCtr = new LayoutMain3ColsPreviewController(ureq, getWindowControl(), null,
+				controller.getInitialComponent(), null);
+		previewCtr.addDisposableChildController(controller);
+		previewCtr.activate();
+		listenTo(previewCtr);
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/ms/MSCourseNodeConfiguration.java b/src/main/java/org/olat/course/nodes/ms/MSCourseNodeConfiguration.java
index e0ab3f79f3fa3d26369647a4e5b3c55789440af1..ca78aa8f17c2abca8012c412b2726d3f5a1dc338 100644
--- a/src/main/java/org/olat/course/nodes/ms/MSCourseNodeConfiguration.java
+++ b/src/main/java/org/olat/course/nodes/ms/MSCourseNodeConfiguration.java
@@ -34,12 +34,7 @@ import org.olat.course.nodes.CourseNode;
 import org.olat.course.nodes.CourseNodeConfiguration;
 import org.olat.course.nodes.CourseNodeGroup;
 import org.olat.course.nodes.MSCourseNode;
-/**
- * 
- * Description:<br>
- * TODO: guido Class Description for MSCourseNodeConfiguration
- * 
- */
+
 public class MSCourseNodeConfiguration extends AbstractCourseNodeConfiguration {
 	
 	private MSCourseNodeConfiguration() {
diff --git a/src/main/java/org/olat/course/nodes/ms/MSCourseNodeEditController.java b/src/main/java/org/olat/course/nodes/ms/MSCourseNodeEditController.java
index 6c75940d658ebd1785e5a306e72e2e18084f6884..e5a0c5956e4c67f8ddb1e66d03543151077c8501 100644
--- a/src/main/java/org/olat/course/nodes/ms/MSCourseNodeEditController.java
+++ b/src/main/java/org/olat/course/nodes/ms/MSCourseNodeEditController.java
@@ -61,7 +61,7 @@ public class MSCourseNodeEditController extends ActivateableTabbableDefaultContr
 
 	private MSCourseNode msNode;
 	private VelocityContainer configurationVC;
-	private MSEditFormController modConfigController;
+	private MSConfigController configController;
 	private HighScoreEditController highScoreNodeConfigController;
 
 	private ConditionEditController accessibilityCondContr;
@@ -95,9 +95,9 @@ public class MSCourseNodeEditController extends ActivateableTabbableDefaultContr
 				AssessmentHelper.getAssessableNodes(editorModel, msNode));		
 		this.listenTo(accessibilityCondContr);
 
-		modConfigController = new MSEditFormController(ureq, wControl, msNode.getModuleConfiguration());
-		listenTo(modConfigController);
-		configurationVC.put("mseditform", modConfigController.getInitialComponent());
+		configController = new MSConfigController(ureq, wControl, course, msNode);
+		listenTo(configController);
+		configurationVC.put("mseditform", configController.getInitialComponent());
 		
 		highScoreNodeConfigController = new HighScoreEditController(ureq, wControl, msNode.getModuleConfiguration());
 		listenTo(highScoreNodeConfigController);
@@ -107,26 +107,18 @@ public class MSCourseNodeEditController extends ActivateableTabbableDefaultContr
 		hasLogEntries = auditManager.hasUserNodeLogs(msNode);
 		configurationVC.contextPut("hasLogEntries", new Boolean(hasLogEntries));
 		if (hasLogEntries) {
-			modConfigController.setDisplayOnly(true);
+			configController.setDisplayOnly(true);
 		}
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.components.Component, org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Component source, Event event) {
 		if (source == editScoringConfigButton) {
-			modConfigController.setDisplayOnly(false);
+			configController.setDisplayOnly(false);
 			configurationVC.contextPut("isOverwriting", new Boolean(true));			
 		}
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#event(org.olat.core.gui.UserRequest,
-	 *      org.olat.core.gui.control.Controller, org.olat.core.gui.control.Event)
-	 */
 	@Override
 	public void event(UserRequest ureq, Controller source, Event event) {
 		if (source == accessibilityCondContr) {
@@ -135,28 +127,11 @@ public class MSCourseNodeEditController extends ActivateableTabbableDefaultContr
 				msNode.setPreConditionAccess(cond);
 				fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
 			}
-		} else if (source == modConfigController) {
-			if (event == Event.CANCELLED_EVENT) {
-			// reset form
-				
-				if (modConfigController != null) {
-					removeAsListenerAndDispose(modConfigController);
-				}
-				modConfigController = new MSEditFormController(ureq, getWindowControl(), msNode.getModuleConfiguration());
-				listenTo(modConfigController);
-				configurationVC.put("mseditform", modConfigController.getInitialComponent());
-				if (hasLogEntries) {
-					modConfigController.setDisplayOnly(true);
-				}
-				configurationVC.contextPut("isOverwriting", new Boolean(false));
-				return;
-				
-			} else if (event == Event.DONE_EVENT) {
-				modConfigController.updateModuleConfiguration(msNode.getModuleConfiguration());
+		} else if (source == configController) {
+			if (event == Event.DONE_EVENT) {
 				fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
 			}
 			updateHighscoreTab();
-			
 		} else if (source == highScoreNodeConfigController){
 			if (event == Event.DONE_EVENT) {
 				fireEvent(ureq, NodeEditController.NODECONFIG_CHANGED_EVENT);
@@ -165,13 +140,10 @@ public class MSCourseNodeEditController extends ActivateableTabbableDefaultContr
 	}
 	
 	private void updateHighscoreTab() {
-		Boolean sf = msNode.getModuleConfiguration().getBooleanSafe(MSCourseNode.CONFIG_KEY_HAS_SCORE_FIELD,false);
-		myTabbedPane.setEnabled(4, sf);
+		myTabbedPane.setEnabled(4, msNode.hasScoreConfigured());
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.generic.tabbable.TabbableDefaultController#addTabs(org.olat.core.gui.components.TabbedPane)
-	 */
+	@Override
 	public void addTabs(TabbedPane tabbedPane) {
 		myTabbedPane = tabbedPane;
 		tabbedPane.addTab(translate(PANE_TAB_ACCESSIBILITY), accessibilityCondContr.getWrappedDefaultAccessConditionVC(translate("condition.accessibility.title")));
@@ -181,12 +153,9 @@ public class MSCourseNodeEditController extends ActivateableTabbableDefaultContr
 
 	}
 
-	/**
-	 * @see org.olat.core.gui.control.DefaultController#doDispose(boolean)
-	 */
 	@Override
 	protected void doDispose() {
-    //child controllers registered with listenTo() get disposed in BasicController
+		//
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/course/nodes/ms/MSEvaluationFormExecutionController.java b/src/main/java/org/olat/course/nodes/ms/MSEvaluationFormExecutionController.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd7a9428f9f799e8306336c8e1622d7635a3a5a5
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/ms/MSEvaluationFormExecutionController.java
@@ -0,0 +1,161 @@
+/**
+ * <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.nodes.ms;
+
+import org.olat.core.gui.UserRequest;
+import org.olat.core.gui.components.Component;
+import org.olat.core.gui.components.link.Link;
+import org.olat.core.gui.components.link.LinkFactory;
+import org.olat.core.gui.components.velocity.VelocityContainer;
+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.controller.BasicController;
+import org.olat.core.id.Identity;
+import org.olat.course.assessment.AssessmentManager;
+import org.olat.course.assessment.ui.tool.AssessmentFormCallback;
+import org.olat.course.nodes.MSCourseNode;
+import org.olat.course.run.userview.UserCourseEnvironment;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.assessment.AssessmentEntry;
+import org.olat.modules.assessment.Role;
+import org.olat.modules.assessment.model.AssessmentEntryStatus;
+import org.olat.modules.forms.EvaluationFormSession;
+import org.olat.modules.forms.EvaluationFormSessionStatus;
+import org.olat.modules.forms.ui.EvaluationFormExecutionController;
+import org.olat.repository.RepositoryEntry;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 11 Jun 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public class MSEvaluationFormExecutionController extends BasicController implements AssessmentFormCallback {
+
+	private final VelocityContainer mainVC;
+	private final Link reopenLink;
+	private EvaluationFormExecutionController executionCtrl;
+
+	private final UserCourseEnvironment assessedUserCourseEnv;
+	private final ModuleConfiguration config;
+	private final MSCourseNode msCourseNode;
+
+	private EvaluationFormSession session;
+	private boolean assessmentDone;
+
+	@Autowired
+	private MSService msService;
+
+	public MSEvaluationFormExecutionController(UserRequest ureq, WindowControl wControl,
+			UserCourseEnvironment assessedUserCourseEnv, MSCourseNode msCourseNode) {
+		super(ureq, wControl);
+		this.assessedUserCourseEnv = assessedUserCourseEnv;
+		this.msCourseNode = msCourseNode;
+		this.config = msCourseNode.getModuleConfiguration();
+		
+		RepositoryEntry formEntry = MSCourseNode.getEvaluationForm(config);
+		RepositoryEntry ores = assessedUserCourseEnv.getCourseEnvironment().getCourseGroupManager().getCourseEntry();
+		String nodeIdent = msCourseNode.getIdent();
+		Identity assessedIdentity = assessedUserCourseEnv.getIdentityEnvironment().getIdentity();
+		session =  msService.getOrCreateSession(formEntry, ores, nodeIdent, assessedIdentity);
+		
+		AssessmentManager am = assessedUserCourseEnv.getCourseEnvironment().getAssessmentManager();
+		AssessmentEntry aEntry = am.getAssessmentEntry(msCourseNode, assessedIdentity);
+		assessmentDone = aEntry != null && aEntry.getAssessmentStatus() == AssessmentEntryStatus.done;
+		
+		mainVC = createVelocityContainer("evaluation_form_execution");
+		reopenLink = LinkFactory.createButton("evaluation.execution.reopen", mainVC, this);
+		updateUI(ureq);
+		
+		putInitialPanel(mainVC);
+	}
+
+	private void updateUI(UserRequest ureq) {
+		refreshExecutionController(ureq);
+		updateUIReopen();
+	}
+
+	private void refreshExecutionController(UserRequest ureq) {
+		if (executionCtrl != null) {
+			mainVC.remove(executionCtrl.getInitialComponent());
+			removeAsListenerAndDispose(executionCtrl);
+		}
+		
+		executionCtrl = new EvaluationFormExecutionController(ureq, getWindowControl(), null, null, session, null, null, null, false, true);
+		listenTo(executionCtrl);
+		mainVC.put("execution", executionCtrl.getInitialComponent());
+	}
+
+	private void updateUIReopen() {
+		boolean reopenVisible = !assessmentDone && isSessionClosed();
+		reopenLink.setVisible(reopenVisible);
+		mainVC.setDirty(true);
+	}
+
+	private boolean isSessionClosed() {
+		return EvaluationFormSessionStatus.done.equals(session.getEvaluationFormSessionStatus());
+	}
+
+	@Override
+	public void assessmentDone(UserRequest ureq) {
+		assessmentDone = true;
+		session = msService.closeSession(session);
+		updateUI(ureq);
+	}
+
+	@Override
+	public void assessmentReopen(UserRequest ureq) {
+		assessmentDone = false;
+		session = msService.reopenSession(session);
+		updateUI(ureq);
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Component source, Event event) {
+		if (source == reopenLink) {
+			session = msService.reopenSession(session);
+			updateUI(ureq);
+		}
+	}
+
+	@Override
+	protected void event(UserRequest ureq, Controller source, Event event) {
+		if (source == executionCtrl && Event.DONE_EVENT.equals(event)) {
+			doSetAssessmentScore();
+			fireEvent(ureq, Event.CHANGED_EVENT);
+		}
+		super.event(ureq, source, event);
+	}
+
+	private void doSetAssessmentScore() {
+		session = msService.getSession(session);
+		Identity assessedIdentity = assessedUserCourseEnv.getIdentityEnvironment().getIdentity();
+		msCourseNode.updateScoreEvaluation(getIdentity(), assessedUserCourseEnv, assessedIdentity, Role.coach, session);
+		updateUIReopen();
+	}
+
+	@Override
+	protected void doDispose() {
+		//
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/ms/MSService.java b/src/main/java/org/olat/course/nodes/ms/MSService.java
new file mode 100644
index 0000000000000000000000000000000000000000..0c431c64dfc929b99c1724b53bf9f4382f56e164
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/ms/MSService.java
@@ -0,0 +1,73 @@
+/**
+ * <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.nodes.ms;
+
+import org.olat.core.id.Identity;
+import org.olat.core.id.OLATResourceable;
+import org.olat.modules.forms.EvaluationFormSession;
+import org.olat.modules.forms.EvaluationFormSessionRef;
+import org.olat.repository.RepositoryEntry;
+
+/**
+ * 
+ * Initial date: 11 Jun 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public interface MSService {
+	
+	EvaluationFormSession getOrCreateSession(RepositoryEntry formEntry, RepositoryEntry ores, String nodeIdent,
+			Identity assessedIdentity);
+
+	EvaluationFormSession getSession(EvaluationFormSessionRef sessionRef);
+
+	EvaluationFormSession closeSession(EvaluationFormSession session);
+
+	EvaluationFormSession reopenSession(EvaluationFormSession session);
+
+	boolean hasSessions(OLATResourceable ores, String nodeIdent);
+	
+	void deleteSessions(RepositoryEntry ores, String nodeIdent);
+	
+	/**
+	 * Calculates the possible minimum and maximum sum of all rubrics in the
+	 * evaluation form of the formEntry.
+	 *
+	 * @param formEntry
+	 * @return
+	 */
+	MinMax calculateMinMaxSum(RepositoryEntry formEntry, float scalingFactor);
+
+	/**
+	 * Calculates the possible minimum and maximum average of all rubrics in the
+	 * evaluation form of the formEntry.
+	 *
+	 * @param formEntry
+	 * @return
+	 */
+	MinMax calculateMinMaxAvg(RepositoryEntry formEntry, float scalingFactor);
+
+	Float calculateScoreBySum(EvaluationFormSession session);
+
+	Float calculateScoreByAvg(EvaluationFormSession session);
+
+	Float scaleScore(Float score, float scalingFactor);
+
+}
diff --git a/src/main/java/org/olat/course/nodes/ms/MinMax.java b/src/main/java/org/olat/course/nodes/ms/MinMax.java
new file mode 100644
index 0000000000000000000000000000000000000000..8ca2aff33484250b17c98077b41ebeb188bd6525
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/ms/MinMax.java
@@ -0,0 +1,60 @@
+/**
+ * <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.nodes.ms;
+
+/**
+ * 
+ * Initial date: 12 Jun 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public interface MinMax {
+	
+	Float getMin();
+	
+	Float getMax();
+	
+	public static MinMax of(Float min, Float max) {
+		return new MinMaxImpl(min, max);
+	}
+	
+	static final class MinMaxImpl implements MinMax {
+		
+		private final Float min;
+		private final Float max;
+		
+		private MinMaxImpl(Float min, Float max) {
+			this.min = min;
+			this.max = max;
+		}
+
+		@Override
+		public Float getMin() {
+			return min;
+		}
+
+		@Override
+		public Float getMax() {
+			return max;
+		}
+		
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/ms/_content/evaluation_form_execution.html b/src/main/java/org/olat/course/nodes/ms/_content/evaluation_form_execution.html
new file mode 100644
index 0000000000000000000000000000000000000000..da1daa90e7c492e09acfdb1c76058b019b80e67a
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/ms/_content/evaluation_form_execution.html
@@ -0,0 +1,6 @@
+$r.render("execution")
+#if($r.visible("evaluation.execution.reopen"))
+	<div class="o_button_group">
+		$r.render("evaluation.execution.reopen")
+	</div>
+#end
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_de.properties
index 55665ad91e9f42ffca66ed6cdbe3d195f10775e7..0a453c1d6dc86e91316daf5b3ad4e62ed160a406 100644
--- a/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_de.properties
@@ -5,6 +5,9 @@ comment.title=Kommentar
 condition.accessibility.title=Zugang
 error.missingconfig.long=\u00D6ffnen Sie den Tab "Bewertung", um "{0}" fertig zu konfigurieren.
 error.missingconfig.short=Die Bewertung f\u00FCr "{0}" ist nicht korrekt konfiguriert.
+error.repo.entry.missing=Der Fragebogen, welchen Sie anzeigen m\u00F6chten, wurde in der Zwischenzeit gel\u00F6scht.
+error.repo.entry.not.replaceable=Der Fragebogen kann nicht mehr ge\u00E4ndert werden.
+evaluation.execution.reopen=Wieder \u00F6ffnen
 form.comment=Individueller Kommentar
 form.configuration=Konfiguration der manuellen Bewertung
 form.configuration.alreadydata=Die Konfiguration kann nicht mehr ge\u00E4ndert werden, da bereits Daten gespeichert wurden.
@@ -13,6 +16,13 @@ form.error.cutButNoScore=Die <b>Art der Ausgabe</b> muss auf &laquo;Manuell durc
 form.error.cutOutOfRange=Punkteschwelle liegt nicht zwischen Punkteminimum/-maximum
 form.error.minGreaterThanMax=Punkteminimum ist gr\u00F6sser als Punktemaximum
 form.error.wrongFloat=Falsches Zahlenformat. Beispiele\: 15.0, 5.5, 10
+form.evaluation=Rubrik-Fragebogen
+form.evaluation.choose=Ausw\u00E4hlen, erstellen oder importieren
+form.evaluation.edit=Bearbeiten
+form.evaluation.enabled=Rubrik-Bewertung
+form.evaluation.not.choosen=Es ist kein Rubrik-Fragebogen ausw\u00E4hlt.
+form.evaluation.replace=Ersetzen
+form.evaluation.choose=Rubrik-Fragebogen ausw\u00E4hlen
 form.individual.assessment.docs=Individuelle Bewertungsdokumente
 form.infotext.coach=Hinweis f\u00FCr Betreuer
 form.infotext.user=Hinweis f\u00FCr alle Benutzer
@@ -23,7 +33,12 @@ form.passed=Bestanden/Nicht bestanden ausgeben
 form.passed.type=Art der Ausgabe
 form.passedtype.cutval=Automatisch durch Punkteschwelle
 form.passedtype.manual=Manuell durch Betreuer
+form.scale=Skalierungsfaktor
 form.score=Punkte vergeben
+form.score.eval.avg=Durchschnitt aus Rubrik-Fragebogen \u00FCbernehmen
+form.score.eval.sum=Summe aus Rubrik-Fragebogen \u00FCbernehmen
+form.score.manual=Punkte manuell vergeben
+form.score.none=Keine Punkte vergeben
 form.yes=Ja
 in.review=In Korrektur
 info.title=Information zur Bewertung
diff --git a/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_en.properties
index 72828bdb2fb23de912e3172346534b56ad4d5a3b..1af27e05da1da20aace03775413f32e2afb1e583 100644
--- a/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/ms/_i18n/LocalStrings_en.properties
@@ -5,6 +5,9 @@ comment.title=Comments
 condition.accessibility.title=Access
 error.missingconfig.long=Please open the tab "Assessment" in order to complete the configuration of "{0}".
 error.missingconfig.short=The assessment for "{0}" is not correctly configured.
+error.repo.entry.missing=This survey was deleted in the meantime..
+error.repo.entry.not.replaceable=The questionnaire can not be replaced anymore.
+evaluation.execution.reopen=Reopen
 form.comment=Individual comment
 form.configuration=Configuration of manual assessment
 form.configuration.alreadydata=This configuration cannot be changed since there is already user data available.
@@ -13,6 +16,13 @@ form.error.cutButNoScore=<b>Type of display</b> must be set to &laquo;Manually b
 form.error.cutOutOfRange=Cut value not between minimum and maximum score
 form.error.minGreaterThanMax=Minumum score greater than maximum score
 form.error.wrongFloat=Wrong numerical format. Examples\: 15.0, 5.5, 10
+form.evaluation=Rubric questionnaire
+form.evaluation.choose=Choose, create or import
+form.evaluation.edit=Edit
+form.evaluation.enabled=Rubric assessment
+form.evaluation.not.choosen=No rubric questionnaire chosen
+form.evaluation.replace=Replace
+form.evaluation.choose=Choose questionnaire
 form.individual.assessment.docs=Individual assessment documents
 form.infotext.coach=Notice for tutors
 form.infotext.user=Notice for all users
@@ -23,7 +33,12 @@ form.passed=Display passed/failed
 form.passed.type=Type of display 
 form.passedtype.cutval=Automatic (using cut value)
 form.passedtype.manual=Manually by tutor
+form.scale=Scaling factor
 form.score=Score granted
+form.score.eval.avg=Transfer average from rubric questionnaire
+form.score.eval.sum=Transfer sum from rubric questionnaire
+form.score.manual=Set points manually
+form.score.none=No points
 form.yes=Yes
 in.review=In review
 info.title=Assessment information
diff --git a/src/main/java/org/olat/course/nodes/ms/manager/MSServiceImpl.java b/src/main/java/org/olat/course/nodes/ms/manager/MSServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b7d4ed7cc9f3d275335b6f634dc420ac380496f
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/ms/manager/MSServiceImpl.java
@@ -0,0 +1,222 @@
+/**
+ * <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.nodes.ms.manager;
+
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
+
+import java.util.List;
+
+import org.olat.core.id.Identity;
+import org.olat.core.id.OLATResourceable;
+import org.olat.course.nodes.ms.MSService;
+import org.olat.course.nodes.ms.MinMax;
+import org.olat.modules.forms.EvaluationFormManager;
+import org.olat.modules.forms.EvaluationFormParticipation;
+import org.olat.modules.forms.EvaluationFormParticipationIdentifier;
+import org.olat.modules.forms.EvaluationFormSession;
+import org.olat.modules.forms.EvaluationFormSessionRef;
+import org.olat.modules.forms.EvaluationFormSurvey;
+import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
+import org.olat.modules.forms.RubricStatistic;
+import org.olat.modules.forms.SessionFilterFactory;
+import org.olat.modules.forms.SliderStatistic;
+import org.olat.modules.forms.model.xml.AbstractElement;
+import org.olat.modules.forms.model.xml.Form;
+import org.olat.modules.forms.model.xml.Rubric;
+import org.olat.modules.forms.model.xml.Slider;
+import org.olat.repository.RepositoryEntry;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 
+ * Initial date: 11 Jun 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+public class MSServiceImpl implements MSService {
+	
+	@Autowired
+	private EvaluationFormManager evaluationFormManager;
+	
+	@Override
+	public EvaluationFormSession getOrCreateSession(RepositoryEntry formEntry, RepositoryEntry ores, String nodeIdent,
+			Identity assessedIdentity) {
+		EvaluationFormSurveyIdentifier surveyIdent = of(ores, nodeIdent, assessedIdentity.getKey().toString());
+		EvaluationFormSurvey survey = loadOrCreateSurvey(formEntry, surveyIdent);
+		EvaluationFormParticipation participation = loadOrCreateParticipation(survey);
+		return loadOrCreateSesssion(participation);
+	}
+	
+	private EvaluationFormSurvey loadOrCreateSurvey(RepositoryEntry formEntry, EvaluationFormSurveyIdentifier surveyIdent) {
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(surveyIdent);
+		if (survey == null) {
+			survey = evaluationFormManager.createSurvey(surveyIdent, formEntry);
+		}
+		return survey;
+	}
+
+	private EvaluationFormParticipation loadOrCreateParticipation(EvaluationFormSurvey survey) {
+		// All coaches have to edit the same participation. So use the same identifier for all.
+		EvaluationFormParticipationIdentifier identifier = new EvaluationFormParticipationIdentifier("ms-course-node", "1");
+		EvaluationFormParticipation loadedParticipation = evaluationFormManager.loadParticipationByIdentifier(survey, identifier);
+		if (loadedParticipation == null) {
+			loadedParticipation = evaluationFormManager.createParticipation(survey, identifier);
+		}
+		return loadedParticipation;
+	}
+
+	private EvaluationFormSession loadOrCreateSesssion(EvaluationFormParticipation participation) {
+		EvaluationFormSession session = evaluationFormManager.loadSessionByParticipation(participation);
+		if (session == null) {
+			session = evaluationFormManager.createSession(participation);
+		}
+		return session;
+	}
+
+	@Override
+	public EvaluationFormSession getSession(EvaluationFormSessionRef sessionRef) {
+		return evaluationFormManager.loadSessionByKey(sessionRef);
+	}
+
+	@Override
+	public EvaluationFormSession closeSession(EvaluationFormSession session) {
+		return evaluationFormManager.finishSession(session);
+	}
+
+	@Override
+	public EvaluationFormSession reopenSession(EvaluationFormSession session) {
+		return evaluationFormManager.reopenSession(session);
+	}
+
+	@Override
+	public boolean hasSessions(OLATResourceable ores, String nodeIdent) {
+		return !evaluationFormManager.loadSurveys(of(ores, nodeIdent)).isEmpty();
+	}
+
+	@Override
+	public void deleteSessions(RepositoryEntry ores, String nodeIdent) {
+		List<EvaluationFormSurvey> surveys = evaluationFormManager.loadSurveys(of(ores, nodeIdent));
+		for (EvaluationFormSurvey survey : surveys) {
+			evaluationFormManager.deleteSurvey(survey);
+		}
+	}
+
+	@Override
+	public MinMax calculateMinMaxSum(RepositoryEntry formEntry, float scalingFactor) {
+		double sumMin = 0.0;
+		double sumMax = 0.0;
+		Form form = evaluationFormManager.loadForm(formEntry);
+		for (AbstractElement element : form.getElements()) {
+			if (Rubric.TYPE.equals(element.getType())) {
+				Rubric rubric = (Rubric) element;
+				int numberOfSliders = rubric.getSliders().size();
+				int steps = rubric.getSteps();
+				double min = rubric.getScaleType().getStepValue(steps, 1);
+				double max = rubric.getScaleType().getStepValue(steps, steps);
+				sumMin += numberOfSliders * min;
+				sumMax += numberOfSliders * max;
+			}
+		}
+		sumMin = scalingFactor * sumMin;
+		sumMax = scalingFactor * sumMax;
+		return MinMax.of(Float.valueOf((float)sumMin), Float.valueOf((float)sumMax));
+	}
+
+	@Override
+	public MinMax calculateMinMaxAvg(RepositoryEntry formEntry, float scalingFactor) {
+		double sumMin = 0.0;
+		double sumMax = 0.0;
+		int numberAvgs = 0;
+		Form form = evaluationFormManager.loadForm(formEntry);
+		for (AbstractElement element : form.getElements()) {
+			if (Rubric.TYPE.equals(element.getType())) {
+				Rubric rubric = (Rubric) element;
+				int numberOfSliders = rubric.getSliders().size();
+				int steps = rubric.getSteps();
+				double min = rubric.getScaleType().getStepValue(steps, 1);
+				double max = rubric.getScaleType().getStepValue(steps, steps);
+				sumMin += numberOfSliders * min;
+				sumMax += numberOfSliders * max;
+				numberAvgs += numberOfSliders;
+			}
+		}
+		if (numberAvgs > 0) {
+			double avgMin = sumMin / numberAvgs;
+			avgMin = scalingFactor * avgMin;
+			double avgMax = sumMax / numberAvgs;
+			avgMax = scalingFactor * avgMax;
+			return MinMax.of(Float.valueOf((float)avgMin), Float.valueOf((float)avgMax));
+		}
+		return MinMax.of(0.0f, 0.0f);
+	}
+
+	@Override
+	public Float calculateScoreBySum(EvaluationFormSession session) {
+		double sum = 0.0;
+		Form form = evaluationFormManager.loadForm(session.getSurvey().getFormEntry());
+		for (AbstractElement element : form.getElements()) {
+			if (Rubric.TYPE.equals(element.getType())) {
+				Rubric rubric = (Rubric) element;
+				RubricStatistic rubricStatistic = evaluationFormManager.getRubricStatistic(rubric, SessionFilterFactory.create(session));
+				Double rubricSum = rubricStatistic.getTotalStatistic().getSum();
+				if (rubricSum != null) {
+					sum += (float)rubricSum.doubleValue();
+				}
+			}
+		}
+		return Float.valueOf((float)sum);
+	}
+
+	@Override
+	public Float calculateScoreByAvg(EvaluationFormSession session) {
+		double sumAvgs = 0.0;
+		int numberAvgs = 0;
+		Form form = evaluationFormManager.loadForm(session.getSurvey().getFormEntry());
+		for (AbstractElement element : form.getElements()) {
+			if (Rubric.TYPE.equals(element.getType())) {
+				Rubric rubric = (Rubric) element;
+				RubricStatistic rubricStatistic = evaluationFormManager.getRubricStatistic(rubric, SessionFilterFactory.create(session));
+				for (Slider slider : rubric.getSliders()) {
+					SliderStatistic sliderStatistic = rubricStatistic.getSliderStatistic(slider);
+					Double sliderAvg = sliderStatistic.getAvg();
+					if (sliderAvg != null) {
+						numberAvgs++;
+						sumAvgs += sliderAvg.doubleValue();
+					}
+				}
+			}
+		}
+		if (numberAvgs > 0) {
+			double avg = sumAvgs / numberAvgs;
+			return Float.valueOf((float)avg);
+		}
+		return null;
+	}
+
+	@Override
+	public Float scaleScore(Float score, float scale) {
+		if (score == null) return null;
+		
+		return scale * score.floatValue();
+	}
+
+}
diff --git a/src/main/java/org/olat/course/nodes/survey/SurveyConfigController.java b/src/main/java/org/olat/course/nodes/survey/SurveyConfigController.java
index 6a17be42cda12f2ab5a66944d6ffcc7697bac6fc..9dba272d94a6ed4705f8de48aaaee1fd4df53139 100644
--- a/src/main/java/org/olat/course/nodes/survey/SurveyConfigController.java
+++ b/src/main/java/org/olat/course/nodes/survey/SurveyConfigController.java
@@ -51,6 +51,7 @@ import org.olat.modules.ModuleConfiguration;
 import org.olat.modules.ceditor.DataStorage;
 import org.olat.modules.forms.EvaluationFormManager;
 import org.olat.modules.forms.EvaluationFormSurvey;
+import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
 import org.olat.modules.forms.handler.EvaluationFormResource;
 import org.olat.modules.forms.ui.EvaluationFormExecutionController;
 import org.olat.repository.RepositoryEntry;
@@ -102,6 +103,7 @@ public class SurveyConfigController extends FormBasicController {
 	private final ModuleConfiguration moduleConfiguration;
 	private final OLATResourceable ores;
 	private final String subIdent;
+	private EvaluationFormSurveyIdentifier surveyIdent;
 	private EvaluationFormSurvey survey;
 	
 	@Autowired
@@ -113,7 +115,8 @@ public class SurveyConfigController extends FormBasicController {
 		this.moduleConfiguration = surveyCourseNode.getModuleConfiguration();
 		this.ores = RepositoryManager.getInstance().lookupRepositoryEntry(course, true);
 		this.subIdent = surveyCourseNode.getIdent();
-		this.survey = evaluationFormManager.loadSurvey(ores, subIdent);
+		this.surveyIdent = EvaluationFormSurveyIdentifier.of(ores, subIdent);
+		this.survey = evaluationFormManager.loadSurvey(surveyIdent);
 		initForm(ureq);
 	}
 
@@ -234,7 +237,7 @@ public class SurveyConfigController extends FormBasicController {
 		RepositoryEntry formEntry = searchCtrl.getSelectedEntry();
 		if (formEntry != null) {
 			if (survey == null) {
-				survey = evaluationFormManager.createSurvey(ores, subIdent, formEntry);
+				survey = evaluationFormManager.createSurvey(surveyIdent, formEntry);
 			} else {
 				boolean isFormUpdateable = evaluationFormManager.isFormUpdateable(survey);
 				if (isFormUpdateable) {
diff --git a/src/main/java/org/olat/course/nodes/survey/SurveyRunController.java b/src/main/java/org/olat/course/nodes/survey/SurveyRunController.java
index f3bc7cdc60122fab9aa01f3a027a0ba068f034fa..77c598a0b4ec6664ed118c1aecafa6bfaae7cac7 100644
--- a/src/main/java/org/olat/course/nodes/survey/SurveyRunController.java
+++ b/src/main/java/org/olat/course/nodes/survey/SurveyRunController.java
@@ -19,6 +19,8 @@
  */
 package org.olat.course.nodes.survey;
 
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
+
 import java.util.UUID;
 
 import org.olat.core.gui.UserRequest;
@@ -99,7 +101,7 @@ public class SurveyRunController extends BasicController {
 			mainVC.contextPut("withCmds", Boolean.TRUE);
 		}
 		
-		survey = evaluationFormManager.loadSurvey(ores, subIdent);
+		survey = evaluationFormManager.loadSurvey(of(ores, subIdent));
 		doShowView(ureq);
 	}
 
diff --git a/src/main/java/org/olat/course/nodes/survey/SurveyStatisticResourceResult.java b/src/main/java/org/olat/course/nodes/survey/SurveyStatisticResourceResult.java
index 92cc01fd4e996cfca0303680325b573f9f62ca26..06b9c5c42b855435179023200c1edea3e9eb32ba 100644
--- a/src/main/java/org/olat/course/nodes/survey/SurveyStatisticResourceResult.java
+++ b/src/main/java/org/olat/course/nodes/survey/SurveyStatisticResourceResult.java
@@ -29,12 +29,12 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.messages.SimpleMessageController;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
-import org.olat.core.id.OLATResourceable;
 import org.olat.core.util.Util;
 import org.olat.course.statistic.StatisticResourceResult;
 import org.olat.modules.forms.EvaluationFormManager;
 import org.olat.modules.forms.EvaluationFormParticipation;
 import org.olat.modules.forms.EvaluationFormSurvey;
+import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
 import org.springframework.beans.factory.annotation.Autowired;
 
 /**
@@ -45,18 +45,16 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class SurveyStatisticResourceResult implements StatisticResourceResult {
 	
-	private final OLATResourceable ores;
-	private final String subIdent;
+	private final EvaluationFormSurveyIdentifier surveyIdent;
 	private final Identity identity;
 	private final SurveyRunSecurityCallback secCallback;
 	
 	@Autowired
 	private EvaluationFormManager evaluationFormManager;
 
-	public SurveyStatisticResourceResult(OLATResourceable ores, String subIdent, Identity identity,
+	public SurveyStatisticResourceResult(EvaluationFormSurveyIdentifier surveyIdent, Identity identity,
 			SurveyRunSecurityCallback secCallback) {
-		this.ores = ores;
-		this.subIdent = subIdent;
+		this.surveyIdent = surveyIdent;
 		this.identity = identity;
 		this.secCallback = secCallback;
 		CoreSpringFactory.autowireObject(this);
@@ -70,7 +68,7 @@ public class SurveyStatisticResourceResult implements StatisticResourceResult {
 	@Override
 	public Controller getController(UserRequest ureq, WindowControl wControl, TooledStackedPanel stackPanel,
 			TreeNode selectedNode) {
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(ores, subIdent);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(surveyIdent);
 		EvaluationFormParticipation participation = evaluationFormManager.loadParticipationByExecutor(survey, identity);
 		if (secCallback.canViewReporting(participation)) {
 			return new SurveyReportingController(ureq, wControl, survey);
diff --git a/src/main/java/org/olat/modules/forms/EvaluationFormDispatcher.java b/src/main/java/org/olat/modules/forms/EvaluationFormDispatcher.java
index 27b04a78c4d8f7ae604c9dfdae2cb2a09b29c7e0..f061865bc45316ccff72e1a175b532d29294dd0b 100644
--- a/src/main/java/org/olat/modules/forms/EvaluationFormDispatcher.java
+++ b/src/main/java/org/olat/modules/forms/EvaluationFormDispatcher.java
@@ -27,6 +27,7 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.NewControllerFactory;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.fullWebApp.BaseFullWebappController;
@@ -41,7 +42,6 @@ import org.olat.core.gui.control.WindowBackOffice;
 import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.creator.ControllerCreator;
 import org.olat.core.helpers.Settings;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.UserSession;
@@ -113,7 +113,7 @@ public class EvaluationFormDispatcher implements Dispatcher {
 				.loadParticipationByIdentifier(identifier);
 		EvaluationFormStandaloneProvider standaloneProvider = CoreSpringFactory
 				.getImpl(EvaluationFormStandaloneProviderFactory.class)
-				.getProvider(participation.getSurvey().getOLATResourceable());
+				.getProvider(participation.getSurvey().getIdentifier().getOLATResourceable());
 		if (participation.getExecutor().equals(usess.getIdentity()) && standaloneProvider.hasBusinessPath(participation)) {
 			ChiefController chiefController = Windows.getWindows(usess).getChiefController();
 			WindowBackOffice windowBackOffice = chiefController.getWindow().getWindowBackOffice();
diff --git a/src/main/java/org/olat/modules/forms/EvaluationFormManager.java b/src/main/java/org/olat/modules/forms/EvaluationFormManager.java
index edfaddc90264f931ef64fc99c3cc867250ab8cd4..0b2647bd191980837ba86e6f6996f6500a02d095 100644
--- a/src/main/java/org/olat/modules/forms/EvaluationFormManager.java
+++ b/src/main/java/org/olat/modules/forms/EvaluationFormManager.java
@@ -28,7 +28,6 @@ import java.util.List;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.SortKey;
 import org.olat.core.id.Identity;
-import org.olat.core.id.OLATResourceable;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.modules.ceditor.DataStorage;
 import org.olat.modules.forms.model.jpa.EvaluationFormResponses;
@@ -50,11 +49,27 @@ public interface EvaluationFormManager {
 	
 	public DataStorage loadStorage(RepositoryEntry formEntry);
 
-	public EvaluationFormSurvey createSurvey(OLATResourceable ores, String subIdent, RepositoryEntry formEntry);
+	public EvaluationFormSurvey createSurvey(EvaluationFormSurveyIdentifier identifier, RepositoryEntry formEntry);
 	
-	public EvaluationFormSurveyRef createSurvey(OLATResourceable ores, String subIdent, EvaluationFormSurvey previous);
+	public EvaluationFormSurveyRef createSurvey(EvaluationFormSurveyIdentifier identifier, EvaluationFormSurvey previous);
 
-	public EvaluationFormSurvey loadSurvey(OLATResourceable ores, String subIdent);
+	/**
+	 * Load a unique survey with a specific identifier. If more then one surveys are
+	 * found, only the "first" one is returned.
+	 *
+	 * @param identifier
+	 * @return
+	 */
+	public EvaluationFormSurvey loadSurvey(EvaluationFormSurveyIdentifier identifier);
+	
+	/**
+	 * Load all surveys of an identifier. The purpose of this method is to load all
+	 * surveys by cut the subIdent(s).
+	 * 
+	 * @param identifier
+	 * @return
+	 */
+	public List<EvaluationFormSurvey> loadSurveys(EvaluationFormSurveyIdentifier identifier);
 
 	/**
 	 * Checks whether a form of a survey can be updated or not. The form can not be
diff --git a/src/main/java/org/olat/modules/forms/EvaluationFormSurvey.java b/src/main/java/org/olat/modules/forms/EvaluationFormSurvey.java
index 7943e1044bb90e9ac89bb111bb83d93f0cdfc21c..d320992fe94029c9e3cc365b682a41b1a313e08b 100644
--- a/src/main/java/org/olat/modules/forms/EvaluationFormSurvey.java
+++ b/src/main/java/org/olat/modules/forms/EvaluationFormSurvey.java
@@ -21,7 +21,6 @@ package org.olat.modules.forms;
 
 import org.olat.core.id.CreateInfo;
 import org.olat.core.id.ModifiedInfo;
-import org.olat.core.id.OLATResourceable;
 import org.olat.repository.RepositoryEntry;
 
 /**
@@ -32,9 +31,7 @@ import org.olat.repository.RepositoryEntry;
  */
 public interface EvaluationFormSurvey extends EvaluationFormSurveyRef, CreateInfo, ModifiedInfo {
 
-	public OLATResourceable getOLATResourceable();
-	
-	public String getSubident();
+	public EvaluationFormSurveyIdentifier getIdentifier();
 
 	/**
 	 *
diff --git a/src/main/java/org/olat/modules/forms/EvaluationFormSurveyIdentifier.java b/src/main/java/org/olat/modules/forms/EvaluationFormSurveyIdentifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..8af61c4d2ae47f395f543e1d5f7e47c905d61e01
--- /dev/null
+++ b/src/main/java/org/olat/modules/forms/EvaluationFormSurveyIdentifier.java
@@ -0,0 +1,94 @@
+/**
+ * <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.modules.forms;
+
+import org.olat.core.id.OLATResourceable;
+
+/**
+ * 
+ * Initial date: 12 Jun 2019<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public interface EvaluationFormSurveyIdentifier {
+	
+	/**
+	 * OLATResourceable which is using the survey.
+	 *
+	 * @return
+	 */
+	public OLATResourceable getOLATResourceable();
+	
+	/**
+	 * The OLATResourceable may define a subIdent, e.g. the course node.
+	 *
+	 * @return
+	 */
+	public String getSubident();
+	
+	/**
+	 * The OLATResourceable may define even a second subIdent.
+	 *
+	 * @return
+	 */
+	public String getSubident2();
+	
+	public static EvaluationFormSurveyIdentifier of(OLATResourceable ores) {
+		return of(ores, null);
+	}
+	
+	public static EvaluationFormSurveyIdentifier of(OLATResourceable ores, String resSubident) {
+		return of(ores, resSubident, null);
+	}
+	
+	public static EvaluationFormSurveyIdentifier of(OLATResourceable ores, String resSubident, String resSubident2) {
+		return new EvaluationFormSurveyIdentifierImpl(ores, resSubident, resSubident2) ;
+	}
+	
+	static class EvaluationFormSurveyIdentifierImpl implements EvaluationFormSurveyIdentifier {
+		
+		private final OLATResourceable ores;
+		private final String subident;
+		private final String subident2;
+		
+		private EvaluationFormSurveyIdentifierImpl(OLATResourceable ores, String resSubident, String resSubident2) {
+			this.ores = ores;
+			this.subident = resSubident;
+			this.subident2 = resSubident2;
+		}
+
+		@Override
+		public OLATResourceable getOLATResourceable() {
+			return ores;
+		}
+
+		@Override
+		public String getSubident() {
+			return subident;
+		}
+
+		@Override
+		public String getSubident2() {
+			return subident2;
+		}
+		
+	}
+
+}
diff --git a/src/main/java/org/olat/modules/forms/SliderStatistic.java b/src/main/java/org/olat/modules/forms/SliderStatistic.java
index 8cf7856f88467604daa55db0fceb775a026f1407..81f443cbfeda66a3146b06a0df5cb841cc821588 100644
--- a/src/main/java/org/olat/modules/forms/SliderStatistic.java
+++ b/src/main/java/org/olat/modules/forms/SliderStatistic.java
@@ -32,6 +32,8 @@ public interface SliderStatistic {
 	public Long getNumberOfNoResponses();
 
 	public Long getNumberOfResponses();
+	
+	public Double getSum();
 
 	public Double getMedian();
 
diff --git a/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java b/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
index c2031a15bda5044ae75bb2e2fc62a3db76b56a46..8aa5a829cbe8b86947fe7fc25d87a5e383169eab 100644
--- a/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
+++ b/src/main/java/org/olat/modules/forms/manager/EvaluationFormManagerImpl.java
@@ -35,7 +35,6 @@ import java.util.List;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.SortKey;
 import org.olat.core.id.Identity;
-import org.olat.core.id.OLATResourceable;
 import org.olat.core.util.vfs.VFSLeaf;
 import org.olat.core.util.xml.XStreamHelper;
 import org.olat.fileresource.FileResourceManager;
@@ -51,6 +50,7 @@ import org.olat.modules.forms.EvaluationFormSessionRef;
 import org.olat.modules.forms.EvaluationFormSessionStatus;
 import org.olat.modules.forms.EvaluationFormStatistic;
 import org.olat.modules.forms.EvaluationFormSurvey;
+import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
 import org.olat.modules.forms.EvaluationFormSurveyRef;
 import org.olat.modules.forms.RubricRating;
 import org.olat.modules.forms.RubricStatistic;
@@ -111,18 +111,27 @@ public class EvaluationFormManagerImpl implements EvaluationFormManager {
 	}
 
 	@Override
-	public EvaluationFormSurvey createSurvey(OLATResourceable ores, String subIdent, RepositoryEntry formEntry) {
-		return evaluationFormSurveyDao.createSurvey(ores, subIdent, formEntry, null);
+	public EvaluationFormSurvey createSurvey(EvaluationFormSurveyIdentifier identifier, RepositoryEntry formEntry) {
+		return evaluationFormSurveyDao.createSurvey(identifier.getOLATResourceable(), identifier.getSubident(),
+				identifier.getSubident2(), formEntry, null);
 	}
 	
 	@Override
-	public EvaluationFormSurvey createSurvey(OLATResourceable ores, String subIdent, EvaluationFormSurvey previous) {
-		return evaluationFormSurveyDao.createSurvey(ores, subIdent, previous.getFormEntry(), previous);
+	public EvaluationFormSurvey createSurvey(EvaluationFormSurveyIdentifier identifier, EvaluationFormSurvey previous) {
+		return evaluationFormSurveyDao.createSurvey(identifier.getOLATResourceable(), identifier.getSubident(),
+				identifier.getSubident2(), previous.getFormEntry(), previous);
 	}
 
 	@Override
-	public EvaluationFormSurvey loadSurvey(OLATResourceable ores, String subIdent) {
-		return evaluationFormSurveyDao.loadByResourceable(ores, subIdent);
+	public EvaluationFormSurvey loadSurvey(EvaluationFormSurveyIdentifier identifier) {
+		return evaluationFormSurveyDao.loadByResourceable(identifier.getOLATResourceable(), identifier.getSubident(),
+				identifier.getSubident2());
+	}
+	
+	@Override
+	public List<EvaluationFormSurvey> loadSurveys(EvaluationFormSurveyIdentifier identifier) {
+		return evaluationFormSurveyDao.loadSurveysByResourceable(identifier.getOLATResourceable(), identifier.getSubident(),
+				identifier.getSubident2());
 	}
 
 	@Override
diff --git a/src/main/java/org/olat/modules/forms/manager/EvaluationFormSurveyDAO.java b/src/main/java/org/olat/modules/forms/manager/EvaluationFormSurveyDAO.java
index 225d210d67ea1c697f5b0d8705ca7e16b3b5c951..9f950f64df9f635ff26eb1df7d054eee980afc82 100644
--- a/src/main/java/org/olat/modules/forms/manager/EvaluationFormSurveyDAO.java
+++ b/src/main/java/org/olat/modules/forms/manager/EvaluationFormSurveyDAO.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.forms.manager;
 
+import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
@@ -47,14 +48,15 @@ class EvaluationFormSurveyDAO {
 	@Autowired
 	private DB dbInstance;
 
-	EvaluationFormSurvey createSurvey(OLATResourceable ores, String subIdent, RepositoryEntry formEntry,
-			EvaluationFormSurvey previous) {
+	EvaluationFormSurvey createSurvey(OLATResourceable ores, String subIdent, String subIdent2,
+			RepositoryEntry formEntry, EvaluationFormSurvey previous) {
 		EvaluationFormSurveyImpl survey = new EvaluationFormSurveyImpl();
 		survey.setCreationDate(new Date());
 		survey.setLastModified(survey.getCreationDate());
 		survey.setResName(ores.getResourceableTypeName());
 		survey.setResId(ores.getResourceableId());
-		survey.setSubident(subIdent);
+		survey.setResSubident(subIdent);
+		survey.setResSubident2(subIdent2);
 		survey.setFormEntry(formEntry);
 		dbInstance.getCurrentEntityManager().persist(survey);
 		Long seriesKey = previous != null? previous.getSeriesKey(): survey.getKey();
@@ -78,10 +80,15 @@ class EvaluationFormSurveyDAO {
 		surveyImpl.setLastModified(new Date());
 		return dbInstance.getCurrentEntityManager().merge(surveyImpl);
 	}
+	
+	EvaluationFormSurvey loadByResourceable(OLATResourceable ores, String subIdent, String subIdent2) {
+		List<EvaluationFormSurvey> surveys = loadSurveysByResourceable(ores, subIdent, subIdent2);
+		return surveys.isEmpty() ? null : surveys.get(0);
+	}
 
-	EvaluationFormSurvey loadByResourceable(OLATResourceable ores, String subIdent) {
+	List<EvaluationFormSurvey> loadSurveysByResourceable(OLATResourceable ores, String subIdent, String subIdent2) {
 		if (ores == null || ores.getResourceableTypeName() == null || ores.getResourceableId() == null)
-			return null;
+			return Collections.emptyList();
 		
 		StringBuilder sb = new StringBuilder();
 		sb.append("select survey from evaluationformsurvey as survey");
@@ -90,6 +97,9 @@ class EvaluationFormSurveyDAO {
 		if (StringHelper.containsNonWhitespace(subIdent)) {
 			sb.append(" and survey.resSubident=:resSubident");
 		}
+		if (StringHelper.containsNonWhitespace(subIdent2)) {
+			sb.append(" and survey.resSubident2=:resSubident2");
+		}
 		
 		TypedQuery<EvaluationFormSurvey> query = dbInstance.getCurrentEntityManager()
 				.createQuery(sb.toString(), EvaluationFormSurvey.class)
@@ -98,8 +108,10 @@ class EvaluationFormSurveyDAO {
 		if (StringHelper.containsNonWhitespace(subIdent)) {
 			query.setParameter("resSubident", subIdent);
 		}
-		List<EvaluationFormSurvey> surveys = query.getResultList();
-		return surveys.isEmpty() ? null : surveys.get(0);
+		if (StringHelper.containsNonWhitespace(subIdent2)) {
+			query.setParameter("resSubident2", subIdent2);
+		}
+		return query.getResultList();
 	}
 
 	void delete(EvaluationFormSurveyRef survey) {
diff --git a/src/main/java/org/olat/modules/forms/model/jpa/EvaluationFormSurveyImpl.java b/src/main/java/org/olat/modules/forms/model/jpa/EvaluationFormSurveyImpl.java
index 194254fcfef6afc738adfea75278f966bbba51bc..7e37d922c1efdc4a0625881c9c2ee3fca5b5334e 100644
--- a/src/main/java/org/olat/modules/forms/model/jpa/EvaluationFormSurveyImpl.java
+++ b/src/main/java/org/olat/modules/forms/model/jpa/EvaluationFormSurveyImpl.java
@@ -19,6 +19,8 @@
  */
 package org.olat.modules.forms.model.jpa;
 
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
+
 import java.util.Date;
 
 import javax.persistence.Column;
@@ -37,6 +39,7 @@ import javax.persistence.TemporalType;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.Persistable;
 import org.olat.modules.forms.EvaluationFormSurvey;
+import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
 import org.olat.repository.RepositoryEntry;
 
 /**
@@ -69,6 +72,8 @@ public class EvaluationFormSurveyImpl implements EvaluationFormSurvey, Persistab
 	private Long resId;
 	@Column(name="e_sub_ident", nullable=true, insertable=true, updatable=false)
 	private String resSubident;
+	@Column(name="e_sub_ident2", nullable=true, insertable=true, updatable=false)
+	private String resSubident2;
 	@Column(name="e_series_key", nullable=true, insertable=true, updatable=true)
 	private Long seriesKey;
 	@Column(name="e_series_index", nullable=true, insertable=true, updatable=true)
@@ -124,9 +129,29 @@ public class EvaluationFormSurveyImpl implements EvaluationFormSurvey, Persistab
 	public void setResId(Long resId) {
 		this.resId = resId;
 	}
-	
+
+	public String getResSubident() {
+		return resSubident;
+	}
+
+	public void setResSubident(String resSubident) {
+		this.resSubident = resSubident;
+	}
+
+	public String getResSubident2() {
+		return resSubident2;
+	}
+
+	public void setResSubident2(String resSubident2) {
+		this.resSubident2 = resSubident2;
+	}
+
 	@Override
-	public OLATResourceable getOLATResourceable() {
+	public EvaluationFormSurveyIdentifier getIdentifier() {
+		return of(getOLATResourceable() , resSubident, resSubident2);
+	}
+	
+	private OLATResourceable getOLATResourceable() {
 		return new OLATResourceable() {
 			
 			@Override
@@ -141,15 +166,6 @@ public class EvaluationFormSurveyImpl implements EvaluationFormSurvey, Persistab
 		};
 	}
 
-	@Override
-	public String getSubident() {
-		return resSubident;
-	}
-
-	public void setSubident(String subident) {
-		this.resSubident = subident;
-	}
-	
 	@Override
 	public RepositoryEntry getFormEntry() {
 		return formEntry;
diff --git a/src/main/java/org/olat/modules/forms/model/jpa/RubricStatisticImpl.java b/src/main/java/org/olat/modules/forms/model/jpa/RubricStatisticImpl.java
index 612fe901e143c486d26434e6ea3d1e1723e741e3..aaacfdbf0390e820082aa42ce09f737c20da64de 100644
--- a/src/main/java/org/olat/modules/forms/model/jpa/RubricStatisticImpl.java
+++ b/src/main/java/org/olat/modules/forms/model/jpa/RubricStatisticImpl.java
@@ -93,12 +93,12 @@ public class RubricStatisticImpl implements RubricStatistic {
 			List<Long> stepCounts = getStepCounts(slider);
 			Long numOfResponses = getNumOfResponses(stepCounts);
 			Double median = getMedian(stepCounts);
-			Double average = getAverage(stepCounts);
+			SumAverage sumAverage = getSumAverage(stepCounts);
 			Double variance = getVariance(stepCounts);
 			Double stdDev = getStdDev(stepCounts);
-			RubricRating rating = RubricRatingEvaluator.rate(rubric, average);
-			SliderStatisticImpl sliderStatistic = new SliderStatisticImpl(numOfNoRespones, numOfResponses, median,
-					average, variance, stdDev, stepCounts, rating);
+			RubricRating rating = RubricRatingEvaluator.rate(rubric, sumAverage.getAverage());
+			SliderStatisticImpl sliderStatistic = new SliderStatisticImpl(numOfNoRespones, numOfResponses,
+					sumAverage.getSum(), median, sumAverage.getAverage(), variance, stdDev, stepCounts, rating);
 			sliderToStatistic.put(slider, sliderStatistic);
 		}
 	}
@@ -160,8 +160,8 @@ public class RubricStatisticImpl implements RubricStatistic {
 		return median;
 	}
 	
-	private Double getAverage(List<Long> stepCounts) {
-		int sumValues = 0;
+	private SumAverage getSumAverage(List<Long> stepCounts) {
+		double sumValues = 0;
 		int sumResponses = 0;
 		for (int step = 1; step <= rubric.getSteps(); step++) {
 			Long count = stepCounts.get(step - 1);
@@ -171,11 +171,14 @@ public class RubricStatisticImpl implements RubricStatistic {
 				sumResponses += count;
 			}
 		}
-		return sumResponses > 0? (double)sumValues / sumResponses: null;
+		return sumResponses > 0
+				? new SumAverage(sumValues, sumValues / sumResponses)
+				: new SumAverage(null, null);
 	}
 	
 	private Double getVariance(List<Long> stepCounts) {
-		Double mean = getAverage(stepCounts);
+		SumAverage sumAverage = getSumAverage(stepCounts);
+		Double mean = sumAverage.getAverage();
 		if (mean == null) return null;
 		
 		List<Double> scaledValues = getScaledValues(stepCounts);
@@ -214,12 +217,12 @@ public class RubricStatisticImpl implements RubricStatistic {
 		List<Long> totalStepCounts = getTotalStepCounts();
 		Long numOfResponses = getNumOfResponses(totalStepCounts);
 		Double median = getMedian(totalStepCounts);
-		Double average = getAverage(totalStepCounts);
+		SumAverage sumAverage = getSumAverage(totalStepCounts);
 		Double variance = getVariance(totalStepCounts);
 		Double stdDev = getStdDev(totalStepCounts);
-		RubricRating rating = RubricRatingEvaluator.rate(rubric, average);
-		totalStatistic = new SliderStatisticImpl(numberOfNoResponses, numOfResponses, median, average, variance, stdDev,
-				totalStepCounts, rating);
+		RubricRating rating = RubricRatingEvaluator.rate(rubric, sumAverage.getAverage());
+		totalStatistic = new SliderStatisticImpl(numberOfNoResponses, numOfResponses, sumAverage.getSum(), median,
+				sumAverage.getAverage(), variance, stdDev, totalStepCounts, rating);
 	}
 
 	private List<Long> getTotalStepCounts() {
@@ -235,5 +238,26 @@ public class RubricStatisticImpl implements RubricStatistic {
 		}
 		return totalStepCounts;
 	}
+	
+	private static final class SumAverage {
+		
+		private final Double sum;
+		private final Double average;
+		
+		private SumAverage(Double sum, Double average) {
+			this.sum = sum;
+			this.average = average;
+		}
+
+		private Double getSum() {
+			return sum;
+		}
+
+		private Double getAverage() {
+			return average;
+		}
+		
+		
+	}
 
 }
diff --git a/src/main/java/org/olat/modules/forms/model/jpa/SliderStatisticImpl.java b/src/main/java/org/olat/modules/forms/model/jpa/SliderStatisticImpl.java
index e4f339316534bf1346104a23e0aab91db791e843..2dd0b4a1f7a1aa8f087d3f759db66c2a6a199a54 100644
--- a/src/main/java/org/olat/modules/forms/model/jpa/SliderStatisticImpl.java
+++ b/src/main/java/org/olat/modules/forms/model/jpa/SliderStatisticImpl.java
@@ -34,6 +34,7 @@ public class SliderStatisticImpl implements SliderStatistic {
 
 	private final Long numberOfNoResponses;
 	private final Long numberOfResponses;
+	private final Double sum;
 	private final Double median;
 	private final Double avg;
 	private final Double variance;
@@ -41,11 +42,12 @@ public class SliderStatisticImpl implements SliderStatistic {
 	private final List<Long> stepCounts;
 	private final RubricRating rating;
 	
-	public SliderStatisticImpl(Long numberOfNoResponses, Long numberOfResponses, Double median, Double avg, Double variance,
-			Double stdDev, List<Long> stepCounts, RubricRating rating) {
+	public SliderStatisticImpl(Long numberOfNoResponses, Long numberOfResponses, Double sum, Double median, Double avg,
+			Double variance, Double stdDev, List<Long> stepCounts, RubricRating rating) {
 		super();
 		this.numberOfNoResponses = numberOfNoResponses;
 		this.numberOfResponses = numberOfResponses;
+		this.sum = sum;
 		this.median = median;
 		this.avg = avg;
 		this.variance = variance;
@@ -64,6 +66,11 @@ public class SliderStatisticImpl implements SliderStatistic {
 		return numberOfResponses;
 	}
 
+	@Override
+	public Double getSum() {
+		return sum;
+	}
+
 	@Override
 	public Double getMedian() {
 		return median;
diff --git a/src/main/java/org/olat/modules/forms/ui/EvaluationFormExecutionController.java b/src/main/java/org/olat/modules/forms/ui/EvaluationFormExecutionController.java
index 8338c9eddffa271d6bce27d39d09cca2158adaf6..6e35c328746b9380d7a656ba3594419e5455b63c 100644
--- a/src/main/java/org/olat/modules/forms/ui/EvaluationFormExecutionController.java
+++ b/src/main/java/org/olat/modules/forms/ui/EvaluationFormExecutionController.java
@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
@@ -41,7 +42,6 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.generic.modal.DialogBoxController;
 import org.olat.core.gui.control.generic.modal.DialogBoxUIFactory;
 import org.olat.core.id.Identity;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.CodeHelper;
 import org.olat.core.util.xml.XStreamHelper;
@@ -110,8 +110,6 @@ public class EvaluationFormExecutionController extends FormBasicController imple
 	/**
 	 * Optimized to use already loaded responses and form.
 	 * 
-	 * @param formHeader
-	 * 
 	 */
 	public EvaluationFormExecutionController(UserRequest ureq, WindowControl wControl, EvaluationFormSession session,
 			EvaluationFormResponses responses, Form form, DataStorage storage, Component header) {
diff --git a/src/main/java/org/olat/modules/forms/ui/StandaloneExecutionController.java b/src/main/java/org/olat/modules/forms/ui/StandaloneExecutionController.java
index 2327c0df2455737488a556fbbbd8879d9ebdeaaf..0611fb281c5a6e3821d9fbce24d77974543282dd 100644
--- a/src/main/java/org/olat/modules/forms/ui/StandaloneExecutionController.java
+++ b/src/main/java/org/olat/modules/forms/ui/StandaloneExecutionController.java
@@ -19,6 +19,7 @@
  */
 package org.olat.modules.forms.ui;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.Component;
 import org.olat.core.gui.components.velocity.VelocityContainer;
@@ -28,7 +29,7 @@ import org.olat.core.gui.control.WindowControl;
 import org.olat.core.gui.control.controller.BasicController;
 import org.olat.core.gui.control.generic.messages.MessageUIFactory;
 import org.olat.core.id.Identity;
-import org.apache.logging.log4j.Logger;
+import org.olat.core.id.OLATResourceable;
 import org.olat.core.logging.Tracing;
 import org.olat.modules.forms.EvaluationFormManager;
 import org.olat.modules.forms.EvaluationFormParticipation;
@@ -76,7 +77,8 @@ public class StandaloneExecutionController extends BasicController implements Co
 			doShowAlreadyDone(ureq);
 			log.debug("Participation already done: " + identifier);
 		} else {
-			EvaluationFormStandaloneProvider standaloneProvider = standaloneProviderFactory.getProvider(participation.getSurvey().getOLATResourceable());
+			OLATResourceable surveyOres = participation.getSurvey().getIdentifier().getOLATResourceable();
+			EvaluationFormStandaloneProvider standaloneProvider = standaloneProviderFactory.getProvider(surveyOres);
 			if (standaloneProvider.isExecutable(participation)) {
 				doShowExecution(ureq, participation);
 				log.debug("Execute evaluation form with " + identifier);
@@ -113,7 +115,8 @@ public class StandaloneExecutionController extends BasicController implements Co
 	}
 
 	private void doShowExecution(UserRequest ureq, EvaluationFormParticipation participation) {
-		EvaluationFormStandaloneProvider standaloneProvider = standaloneProviderFactory.getProvider(participation.getSurvey().getOLATResourceable());
+		OLATResourceable surveyOres = participation.getSurvey().getIdentifier().getOLATResourceable();
+		EvaluationFormStandaloneProvider standaloneProvider = standaloneProviderFactory.getProvider(surveyOres);
 		headerCtrl = standaloneProvider.getExecutionHeader(ureq, getWindowControl(), participation);
 		listenTo(headerCtrl);
 		mainVC.put("header", headerCtrl.getInitialComponent());
diff --git a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
index 243e5a0558d33e45845ee4e35fc40a88bb9b97c0..826483dd527c5bc7c01eb61df83d4e00bdec14e6 100644
--- a/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
+++ b/src/main/java/org/olat/modules/portfolio/manager/PortfolioServiceImpl.java
@@ -34,6 +34,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.basesecurity.Group;
 import org.olat.basesecurity.IdentityRef;
 import org.olat.basesecurity.manager.GroupDAO;
@@ -41,7 +42,6 @@ import org.olat.core.commons.persistence.DB;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
 import org.olat.core.util.FileUtils;
@@ -69,6 +69,7 @@ import org.olat.modules.forms.EvaluationFormParticipation;
 import org.olat.modules.forms.EvaluationFormParticipationRef;
 import org.olat.modules.forms.EvaluationFormSession;
 import org.olat.modules.forms.EvaluationFormSurvey;
+import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
 import org.olat.modules.forms.EvaluationFormSurveyRef;
 import org.olat.modules.portfolio.AssessmentSection;
 import org.olat.modules.portfolio.Assignment;
@@ -1185,7 +1186,7 @@ public class PortfolioServiceImpl implements PortfolioService {
 				}
 				List<Identity> owners = getOwners(page, section);
 				for (Identity owner: owners) {
-					EvaluationFormSurveyRef survey = evaluationFormManager.loadSurvey(getOLATResourceableForEvaluationForm(page.getBody()), null);
+					EvaluationFormSurveyRef survey = evaluationFormManager.loadSurvey(getSurveyIdent(page.getBody()));
 					EvaluationFormParticipationRef participation = evaluationFormManager.loadParticipationByExecutor(survey, owner);
 					EvaluationFormSession session = evaluationFormManager.loadSessionByParticipation(participation);
 					evaluationFormManager.finishSession(session);
@@ -1203,7 +1204,7 @@ public class PortfolioServiceImpl implements PortfolioService {
 				}
 				List<Identity> owners = getOwners(page, section);
 				for (Identity owner: owners) {
-					EvaluationFormSurveyRef survey = evaluationFormManager.loadSurvey(getOLATResourceableForEvaluationForm(page.getBody()), null);
+					EvaluationFormSurveyRef survey = evaluationFormManager.loadSurvey(getSurveyIdent(page.getBody()));
 					EvaluationFormParticipationRef participation = evaluationFormManager.loadParticipationByExecutor(survey, owner);
 					EvaluationFormSession session = evaluationFormManager.loadSessionByParticipation(participation);
 					evaluationFormManager.reopenSession(session);
@@ -1481,10 +1482,10 @@ public class PortfolioServiceImpl implements PortfolioService {
 	
 	@Override
 	public EvaluationFormSurvey loadOrCreateSurvey(PageBody body, RepositoryEntry formEntry) {
-		OLATResourceable ores = getOLATResourceableForEvaluationForm(body);
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(ores, null);
+		EvaluationFormSurveyIdentifier surveyIdent = getSurveyIdent(body);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(surveyIdent);
 		if (survey == null) {
-			survey = evaluationFormManager.createSurvey(ores, null, formEntry);
+			survey = evaluationFormManager.createSurvey(surveyIdent, formEntry);
 		}
 		return survey;
 	}
@@ -1510,11 +1511,15 @@ public class PortfolioServiceImpl implements PortfolioService {
 
 	@Override
 	public void deleteSurvey(PageBody body) {
-		OLATResourceable ores = getOLATResourceableForEvaluationForm(body);
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(ores, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(getSurveyIdent(body));
 		if (survey != null) {
 			evaluationFormManager.deleteSurvey(survey);
 		}
 	}
 	
+	private EvaluationFormSurveyIdentifier getSurveyIdent(PageBody body) {
+		OLATResourceable ores = getOLATResourceableForEvaluationForm(body);
+		return EvaluationFormSurveyIdentifier.of(ores);
+	}
+	
 }
diff --git a/src/main/java/org/olat/modules/quality/manager/QualityMailing.java b/src/main/java/org/olat/modules/quality/manager/QualityMailing.java
index de4e710d80fd8138cba7e5411bff903567e18361..c9100d0c2b064a59a57e99f42b1727d804ffe9cc 100644
--- a/src/main/java/org/olat/modules/quality/manager/QualityMailing.java
+++ b/src/main/java/org/olat/modules/quality/manager/QualityMailing.java
@@ -19,6 +19,8 @@
  */
 package org.olat.modules.quality.manager;
 
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -36,6 +38,7 @@ import java.util.Date;
 import java.util.List;
 import java.util.Locale;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.core.CoreSpringFactory;
 import org.olat.core.commons.services.pdf.PdfModule;
 import org.olat.core.commons.services.pdf.PdfService;
@@ -46,7 +49,6 @@ import org.olat.core.gui.util.WindowControlMocker;
 import org.olat.core.helpers.Settings;
 import org.olat.core.id.Identity;
 import org.olat.core.id.User;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.CodeHelper;
 import org.olat.core.util.FileUtils;
@@ -382,7 +384,7 @@ class QualityMailing {
 		if (!pdfModule.isEnabled()) return null;
 		if (tempDir == null || !tempDir.toFile().exists()) return null;
 		
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(of(dataCollection));
 		Form form = evaluationFormManager.loadForm(survey.getFormEntry());
 		DataStorage storage = evaluationFormManager.loadStorage(survey.getFormEntry());
 		SessionFilter filter = SessionFilterFactory.createSelectDone(survey);
diff --git a/src/main/java/org/olat/modules/quality/manager/QualityServiceImpl.java b/src/main/java/org/olat/modules/quality/manager/QualityServiceImpl.java
index cd7c946a822fdaac0a6fe5ed22a50e6e1100f22b..eae6559854ecaefc95c5370ccec5e3a7c784accf 100644
--- a/src/main/java/org/olat/modules/quality/manager/QualityServiceImpl.java
+++ b/src/main/java/org/olat/modules/quality/manager/QualityServiceImpl.java
@@ -33,6 +33,7 @@ import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 
+import org.apache.logging.log4j.Logger;
 import org.olat.basesecurity.BaseSecurityManager;
 import org.olat.basesecurity.BaseSecurityModule;
 import org.olat.basesecurity.Group;
@@ -46,11 +47,9 @@ import org.olat.basesecurity.manager.GroupDAO;
 import org.olat.core.commons.persistence.SortKey;
 import org.olat.core.gui.translator.Translator;
 import org.olat.core.id.Identity;
-import org.olat.core.id.OLATResourceable;
 import org.olat.core.id.Organisation;
 import org.olat.core.id.OrganisationRef;
 import org.olat.core.id.Roles;
-import org.apache.logging.log4j.Logger;
 import org.olat.core.logging.Tracing;
 import org.olat.modules.curriculum.Curriculum;
 import org.olat.modules.curriculum.CurriculumDataDeletable;
@@ -61,6 +60,7 @@ import org.olat.modules.forms.EvaluationFormParticipation;
 import org.olat.modules.forms.EvaluationFormParticipationRef;
 import org.olat.modules.forms.EvaluationFormParticipationStatus;
 import org.olat.modules.forms.EvaluationFormSurvey;
+import org.olat.modules.forms.EvaluationFormSurveyIdentifier;
 import org.olat.modules.forms.EvaluationFormSurveyRef;
 import org.olat.modules.forms.RubricRating;
 import org.olat.modules.forms.RubricStatistic;
@@ -181,7 +181,7 @@ public class QualityServiceImpl
 	public QualityDataCollection createDataCollection(Collection<Organisation> organisations,
 			RepositoryEntry formEntry) {
 		QualityDataCollection dataCollection = dataCollectionDao.createDataCollection();
-		evaluationFormManager.createSurvey(dataCollection, null, formEntry);
+		evaluationFormManager.createSurvey(getSurveyIdent(dataCollection), formEntry);
 		createDataCollectionReferences(organisations, formEntry, dataCollection);
 		return dataCollection;
 	}
@@ -190,7 +190,7 @@ public class QualityServiceImpl
 	public QualityDataCollection createDataCollection(Collection<Organisation> organisations, RepositoryEntry formEntry,
 			QualityGenerator generator, Long generatorProviderKey) {
 		QualityDataCollection dataCollection = createDataCollection(generator, generatorProviderKey);
-		evaluationFormManager.createSurvey(dataCollection, null, formEntry);
+		evaluationFormManager.createSurvey(getSurveyIdent(dataCollection), formEntry);
 		createDataCollectionReferences(organisations, formEntry, dataCollection);
 		return dataCollection;
 	}
@@ -199,8 +199,8 @@ public class QualityServiceImpl
 	public QualityDataCollection createDataCollection(Collection<Organisation> organisations, QualityDataCollection previous,
 			QualityGenerator generator, Long generatorProviderKey) {
 		QualityDataCollection dataCollection = createDataCollection(generator, generatorProviderKey);
-		EvaluationFormSurvey previousSurvey = evaluationFormManager.loadSurvey(previous, null);
-		evaluationFormManager.createSurvey(dataCollection, null, previousSurvey);
+		EvaluationFormSurvey previousSurvey = evaluationFormManager.loadSurvey(getSurveyIdent(previous));
+		evaluationFormManager.createSurvey(getSurveyIdent(dataCollection), previousSurvey);
 		createDataCollectionReferences(organisations, previousSurvey.getFormEntry(), dataCollection);
 		return dataCollection;
 	}
@@ -348,7 +348,7 @@ public class QualityServiceImpl
 	private List<RubricStatistic> getRubricsStatistics(QualityDataCollection dataCollection) {
 		RepositoryEntry formEntry = loadFormEntry(dataCollection);
 		Form form = evaluationFormManager.loadForm(formEntry);
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(getSurveyIdent(dataCollection));
 		SessionFilter filter = SessionFilterFactory.createSelectDone(survey);
 		
 		List<Rubric> rubrics = form.getElements().stream()
@@ -381,7 +381,7 @@ public class QualityServiceImpl
 		for (QualityContext context: contexts) {
 			deleteContext(context);
 		}
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(getSurveyIdent(dataCollection));
 		evaluationFormManager.deleteSurvey(survey);
 		deleteReferences(dataCollection);
 		resourceManager.deleteOLATResourceable(dataCollection);
@@ -394,24 +394,24 @@ public class QualityServiceImpl
 
 	@Override
 	public RepositoryEntry loadFormEntry(QualityDataCollectionLight dataCollection) {
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(getSurveyIdent(dataCollection));
 		return survey.getFormEntry() != null? survey.getFormEntry(): null;
 	}
 	
 	@Override
 	public EvaluationFormSurvey loadSurvey(QualityDataCollectionLight dataCollection) {
-		return evaluationFormManager.loadSurvey(dataCollection, null);
+		return evaluationFormManager.loadSurvey(getSurveyIdent(dataCollection));
 	}
 
 	@Override
 	public boolean isFormEntryUpdateable(QualityDataCollection dataCollection) {
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(getSurveyIdent(dataCollection));
 		return evaluationFormManager.isFormUpdateable(survey);
 	}
 
 	@Override
 	public void updateFormEntry(QualityDataCollection dataCollection, RepositoryEntry formEntry) {
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(getSurveyIdent(dataCollection));
 		deleteReferences(dataCollection);
 		
 		evaluationFormManager.updateSurveyForm(survey, formEntry);
@@ -456,7 +456,7 @@ public class QualityServiceImpl
 	@Override
 	public List<EvaluationFormParticipation> addParticipations(QualityDataCollectionLight dataCollection, Collection<Identity> executors) {
 		List<EvaluationFormParticipation> participations = new ArrayList<>();
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(getSurveyIdent(dataCollection));
 		for (Identity executor: executors) {
 			EvaluationFormParticipation participation = evaluationFormManager.loadParticipationByExecutor(survey, executor);
 			if (participation == null) {
@@ -594,8 +594,8 @@ public class QualityServiceImpl
 	private List<EvaluationFormParticipation> getParticipants(QualityReminder reminder) {
 		QualityReminderType type = reminder.getType();
 		EvaluationFormParticipationStatus status = type.getParticipationStatus();
-		OLATResourceable dataCollection = reminder.getDataCollection();
-		EvaluationFormSurveyRef survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		QualityDataCollection dataCollection = reminder.getDataCollection();
+		EvaluationFormSurveyRef survey = evaluationFormManager.loadSurvey(getSurveyIdent(dataCollection));
 		return evaluationFormManager.loadParticipations(survey, status);
 	}
 
@@ -729,4 +729,8 @@ public class QualityServiceImpl
 		return Collections.emptyList();
 	}
 	
+	private EvaluationFormSurveyIdentifier getSurveyIdent(QualityDataCollectionLight dataCollection) {
+		return EvaluationFormSurveyIdentifier.of(dataCollection);
+	}
+	
 }
diff --git a/src/main/java/org/olat/modules/quality/ui/DataCollectionReportController.java b/src/main/java/org/olat/modules/quality/ui/DataCollectionReportController.java
index e8e2bd04da757584d63a2c07a21fb5417b4e842a..2f11187bece8d1986bc4426c2dbacdbfc6ff69fa 100644
--- a/src/main/java/org/olat/modules/quality/ui/DataCollectionReportController.java
+++ b/src/main/java/org/olat/modules/quality/ui/DataCollectionReportController.java
@@ -19,6 +19,8 @@
  */
 package org.olat.modules.quality.ui;
 
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
+
 import org.olat.core.gui.UserRequest;
 import org.olat.core.gui.components.form.flexible.FormItemContainer;
 import org.olat.core.gui.components.form.flexible.impl.FormBasicController;
@@ -65,7 +67,7 @@ public class DataCollectionReportController extends FormBasicController {
 
 	@Override
 	protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
-		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurvey survey = evaluationFormManager.loadSurvey(of(dataCollection));
 		Form form = evaluationFormManager.loadForm(survey.getFormEntry());
 		DataStorage storage = evaluationFormManager.loadStorage(survey.getFormEntry());
 		SessionFilter filter = SessionFilterFactory.createSelectDone(survey);
diff --git a/src/main/resources/database/mysql/alter_13_2_x_to_14_0_0.sql b/src/main/resources/database/mysql/alter_13_2_x_to_14_0_0.sql
index 981cacfa985524fc93a091e9b44b30166ef8dee3..dcb47feec956929612b1a19a7723986332016109 100644
--- a/src/main/resources/database/mysql/alter_13_2_x_to_14_0_0.sql
+++ b/src/main/resources/database/mysql/alter_13_2_x_to_14_0_0.sql
@@ -170,3 +170,10 @@ alter table o_aconnect_user ENGINE = InnoDB;
 
 alter table o_aconnect_user add constraint aconn_ident_idx foreign key (fk_identity_id) references o_bs_identity (id);
 
+-- Evaluation form
+alter table o_eva_form_survey add e_sub_ident2 varchar(2048);
+
+drop index idx_eva_surv_ores_idx on o_eva_form_survey;
+create index idx_eva_surv_ores_idx on o_eva_form_survey (e_resid, e_resname, e_sub_ident(255), e_sub_ident2(255));
+
+
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index 5b8049b64ff8a2b9c7c3acd3de368db800b8cd51..69d49a80bb2a7dad52240cfceabdb4a74faf2a99 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -2002,6 +2002,7 @@ create table o_eva_form_survey (
    e_resname varchar(50) not null,
    e_resid bigint not null,
    e_sub_ident varchar(2048),
+   e_sub_ident2 varchar(2048),
    e_series_key bigint,
    e_series_index int,
    fk_form_entry bigint not null,
@@ -3658,7 +3659,7 @@ alter table o_pf_page_user_infos add constraint page_pfpage_idx foreign key (fk_
 
 -- evaluation form
 alter table o_eva_form_survey add constraint eva_surv_to_surv_idx foreign key (fk_series_previous) references o_eva_form_survey (id);
-create unique index idx_eva_surv_ores_idx on o_eva_form_survey (e_resid, e_resname, e_sub_ident(255));
+create index idx_eva_surv_ores_idx on o_eva_form_survey (e_resid, e_resname, e_sub_ident(255), e_sub_ident2(255));
 
 alter table o_eva_form_participation add constraint eva_part_to_surv_idx foreign key (fk_survey) references o_eva_form_survey (id);
 create unique index idx_eva_part_ident_idx on o_eva_form_participation (e_identifier_key, e_identifier_type, fk_survey);
diff --git a/src/main/resources/database/oracle/alter_13_2_x_to_14_0_0.sql b/src/main/resources/database/oracle/alter_13_2_x_to_14_0_0.sql
index 143a62b3c33cda64e62c98fec80a5c54bc9b4014..2a138c9784916ebc4ffa1ffcec8202d1f97dc2a2 100644
--- a/src/main/resources/database/oracle/alter_13_2_x_to_14_0_0.sql
+++ b/src/main/resources/database/oracle/alter_13_2_x_to_14_0_0.sql
@@ -167,3 +167,6 @@ create table o_aconnect_user (
 
 alter table o_aconnect_user add constraint aconn_ident_idx foreign key (fk_identity_id) references o_bs_identity (id);
 create index idx_aconn_ident_idx on o_aconnect_user (fk_identity_id);
+
+-- Evaluation form
+alter table o_eva_form_survey add e_sub_ident2 varchar(2048);
diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql
index b5ecbd9f754922eb3600c7fd74bf6e12fc575f70..4bd1e82ef29726e1a7b973b9a67f3b5830d8e758 100644
--- a/src/main/resources/database/oracle/setupDatabase.sql
+++ b/src/main/resources/database/oracle/setupDatabase.sql
@@ -1928,6 +1928,7 @@ create table o_eva_form_survey (
    e_resname varchar2(50) not null,
    e_resid number(20) not null,
    e_sub_ident varchar2(2048),
+   e_sub_ident2 varchar2(2048),
    e_series_key number(20),
    e_series_index number(20),
    fk_form_entry number(20) not null,
diff --git a/src/main/resources/database/postgresql/alter_13_2_x_to_14_0_0.sql b/src/main/resources/database/postgresql/alter_13_2_x_to_14_0_0.sql
index 9af68940ef9f69d573a38ec95b53f64af07e1f76..1353943c743031595e4a6b3c28e22e126300e3d2 100644
--- a/src/main/resources/database/postgresql/alter_13_2_x_to_14_0_0.sql
+++ b/src/main/resources/database/postgresql/alter_13_2_x_to_14_0_0.sql
@@ -166,3 +166,10 @@ create table o_aconnect_user (
 
 alter table o_aconnect_user add constraint aconn_ident_idx foreign key (fk_identity_id) references o_bs_identity (id);
 create index idx_aconn_ident_idx on o_aconnect_user (fk_identity_id);
+
+-- Evaluation form
+alter table o_eva_form_survey add e_sub_ident2 varchar(2048);
+
+drop index idx_eva_surv_ores_idx;
+create index idx_eva_surv_ores_idx on o_eva_form_survey (e_resid, e_resname, e_sub_ident, e_sub_ident2);
+
diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql
index 3aa82040360ee70a94eb272951b8227ad3d49d01..1219b3cf126cfe22c18b12543d8c332d9d2aa1e5 100644
--- a/src/main/resources/database/postgresql/setupDatabase.sql
+++ b/src/main/resources/database/postgresql/setupDatabase.sql
@@ -1895,6 +1895,7 @@ create table o_eva_form_survey (
    e_resname varchar(50) not null,
    e_resid bigint not null,
    e_sub_ident varchar(2048),
+   e_sub_ident2 varchar(2048),
    e_series_key bigint,
    e_series_index int,
    fk_form_entry bigint not null,
@@ -3690,7 +3691,7 @@ create index idx_wopi_ident_meta_idx on o_wopi_access(fk_identity, fk_metadata);
 
 -- evaluation form
 alter table o_eva_form_survey add constraint eva_surv_to_surv_idx foreign key (fk_series_previous) references o_eva_form_survey (id);
-create unique index idx_eva_surv_ores_idx on o_eva_form_survey (e_resid, e_resname, e_sub_ident);
+create index idx_eva_surv_ores_idx on o_eva_form_survey (e_resid, e_resname, e_sub_ident, e_sub_ident2);
 
 alter table o_eva_form_participation add constraint eva_part_to_surv_idx foreign key (fk_survey) references o_eva_form_survey (id);
 create unique index idx_eva_part_ident_idx on o_eva_form_participation (e_identifier_key, e_identifier_type, fk_survey);
diff --git a/src/test/java/org/olat/modules/forms/manager/EvaluationFormSurveyDAOTest.java b/src/test/java/org/olat/modules/forms/manager/EvaluationFormSurveyDAOTest.java
index ed354e01350840ad25a33c5d903d0fb9987b1dae..8b69c0a6cae370e98003a42f6f13810bff3247a8 100644
--- a/src/test/java/org/olat/modules/forms/manager/EvaluationFormSurveyDAOTest.java
+++ b/src/test/java/org/olat/modules/forms/manager/EvaluationFormSurveyDAOTest.java
@@ -21,6 +21,7 @@ package org.olat.modules.forms.manager;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
+import java.util.List;
 import java.util.UUID;
 
 import org.assertj.core.api.SoftAssertions;
@@ -60,17 +61,20 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 	public void shouldCreateSurvey() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		String subIdent = UUID.randomUUID().toString();
+		String subIdent2 = UUID.randomUUID().toString();
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
 		EvaluationFormSurvey previous = evaTestHelper.createSurvey();
 		dbInstance.commitAndCloseSession();
 		
-		EvaluationFormSurvey survey = sut.createSurvey(ores, subIdent, formEntry, previous);
+		EvaluationFormSurvey survey = sut.createSurvey(ores, subIdent, subIdent2, formEntry, previous);
 		dbInstance.commitAndCloseSession();
 		
 		SoftAssertions softly = new SoftAssertions();
 		softly.assertThat(survey).isNotNull();
 		softly.assertThat(survey.getCreationDate()).isNotNull();
 		softly.assertThat(survey.getLastModified()).isNotNull();
+		softly.assertThat(survey.getIdentifier().getSubident()).isEqualTo(subIdent);
+		softly.assertThat(survey.getIdentifier().getSubident2()).isEqualTo(subIdent2);
 		softly.assertThat(survey.getFormEntry()).isEqualTo(formEntry);
 		softly.assertThat(survey.getSeriesKey()).isEqualTo(previous.getSeriesKey());
 		softly.assertThat(survey.getSeriesPrevious()).isEqualTo(previous);
@@ -82,11 +86,26 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 	public void shouldLoadByResourceableWithSubident() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		String subIdent = UUID.randomUUID().toString();
+		String subIdent2 = null;
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
-		EvaluationFormSurveyRef survey = sut.createSurvey(ores, subIdent, formEntry, null);
+		EvaluationFormSurveyRef survey = sut.createSurvey(ores, subIdent, subIdent2, formEntry, null);
 		dbInstance.commitAndCloseSession();
 		
-		EvaluationFormSurvey loadedSurvey = sut.loadByResourceable(ores, subIdent);
+		EvaluationFormSurvey loadedSurvey = sut.loadByResourceable(ores, subIdent, subIdent2);
+		
+		assertThat(loadedSurvey).isEqualTo(survey);
+	}
+	
+	@Test
+	public void shouldLoadByResourceableWithSubident2() {
+		OLATResourceable ores = JunitTestHelper.createRandomResource();
+		String subIdent = UUID.randomUUID().toString();
+		String subIdent2 = UUID.randomUUID().toString();
+		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
+		EvaluationFormSurveyRef survey = sut.createSurvey(ores, subIdent, subIdent2, formEntry, null);
+		dbInstance.commitAndCloseSession();
+		
+		EvaluationFormSurvey loadedSurvey = sut.loadByResourceable(ores, subIdent, subIdent2);
 		
 		assertThat(loadedSurvey).isEqualTo(survey);
 	}
@@ -95,25 +114,48 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 	public void shouldLoadByResourceableWithoutSubident() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
-		EvaluationFormSurveyRef survey = sut.createSurvey(ores, null, formEntry, null);
+		EvaluationFormSurveyRef survey = sut.createSurvey(ores, null, null, formEntry, null);
 		dbInstance.commitAndCloseSession();
 		
-		EvaluationFormSurvey loadedSurvey = sut.loadByResourceable(ores, null);
+		EvaluationFormSurvey loadedSurvey = sut.loadByResourceable(ores, null, null);
 		
 		assertThat(loadedSurvey).isEqualTo(survey);
 	}
 	
+	@Test
+	public void shouldLoadSurveysByResourceableWithoutSubident() {
+		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
+		OLATResourceable oresA = JunitTestHelper.createRandomResource();
+		String subIdentA1 = UUID.randomUUID().toString();
+		EvaluationFormSurvey surveyA = sut.createSurvey(oresA, subIdentA1, null, formEntry, null);
+		String subIdentB1 = UUID.randomUUID().toString();
+		EvaluationFormSurvey surveyB = sut.createSurvey(oresA, subIdentB1, null, formEntry, null);
+		OLATResourceable oresOther = JunitTestHelper.createRandomResource();
+		EvaluationFormSurvey surveyOther = sut.createSurvey(oresOther, subIdentA1, null, formEntry, null);
+		dbInstance.commitAndCloseSession();
+		
+		List<EvaluationFormSurvey> surveys = sut.loadSurveysByResourceable(oresA, null, null);
+		
+		assertThat(surveys)
+				.containsExactlyInAnyOrder(
+					surveyA,
+					surveyB)
+				.doesNotContain(
+					surveyOther
+				);
+	}
+	
 	@Test
 	public void shouldDeleteSurvey() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
-		EvaluationFormSurveyRef survey = sut.createSurvey(ores, null, formEntry, null);
+		EvaluationFormSurveyRef survey = sut.createSurvey(ores, null, null, formEntry, null);
 		dbInstance.commitAndCloseSession();
 		
 		sut.delete(survey);
 		dbInstance.commitAndCloseSession();
 		
-		EvaluationFormSurvey loadedSurvey = sut.loadByResourceable(ores, null);
+		EvaluationFormSurvey loadedSurvey = sut.loadByResourceable(ores, null, null);
 		assertThat(loadedSurvey).isNull();
 	}
 	
@@ -121,9 +163,9 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 	public void shouldUpdateSeriesPrevious() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
-		EvaluationFormSurvey previous = sut.createSurvey(ores, null, formEntry, null);
-		EvaluationFormSurvey survey = sut.createSurvey(ores, null, formEntry, previous);
-		EvaluationFormSurvey newPrevious = sut.createSurvey(ores, null, formEntry, null);
+		EvaluationFormSurvey previous = sut.createSurvey(ores, null, null, formEntry, null);
+		EvaluationFormSurvey survey = sut.createSurvey(ores, null, null, formEntry, previous);
+		EvaluationFormSurvey newPrevious = sut.createSurvey(ores, null, null, formEntry, null);
 		dbInstance.commitAndCloseSession();
 		
 		survey = sut.updateSeriesPrevious(survey, newPrevious);
@@ -135,7 +177,7 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 	public void shouldCheckIfItHasNotSeriesNext() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
-		EvaluationFormSurveyRef survey = sut.createSurvey(ores, null, formEntry, null);
+		EvaluationFormSurveyRef survey = sut.createSurvey(ores, null, null, formEntry, null);
 		dbInstance.commitAndCloseSession();
 		
 		boolean hasSeriesNext = sut.hasSeriesNext(survey);
@@ -147,8 +189,8 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 	public void shouldCheckIfItHasSeriesNext() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
-		EvaluationFormSurvey survey = sut.createSurvey(ores, null, formEntry, null);
-		sut.createSurvey(ores, null, formEntry, survey);
+		EvaluationFormSurvey survey = sut.createSurvey(ores, null, null, formEntry, null);
+		sut.createSurvey(ores, null, null, formEntry, survey);
 		dbInstance.commitAndCloseSession();
 		
 		boolean hasSeriesNext = sut.hasSeriesNext(survey);
@@ -160,8 +202,8 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 	public void shouldLoadSeriesNext() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
-		EvaluationFormSurvey survey = sut.createSurvey(ores, null, formEntry, null);
-		EvaluationFormSurvey next = sut.createSurvey(ores, null, formEntry, survey);
+		EvaluationFormSurvey survey = sut.createSurvey(ores, null, null, formEntry, null);
+		EvaluationFormSurvey next = sut.createSurvey(ores, null, null, formEntry, survey);
 		dbInstance.commitAndCloseSession();
 		
 		EvaluationFormSurvey loadedNext = sut.loadSeriesNext(survey);
@@ -173,10 +215,10 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 	public void shouldReindexSeries() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		RepositoryEntry formEntry = evaTestHelper.createFormEntry();
-		EvaluationFormSurvey survey1 = sut.createSurvey(ores, "1", formEntry, null);
-		EvaluationFormSurvey survey2 = sut.createSurvey(ores, "2", formEntry, survey1);
-		EvaluationFormSurvey survey3 = sut.createSurvey(ores, "3", formEntry, survey2);
-		EvaluationFormSurvey survey4 = sut.createSurvey(ores, "4", formEntry, survey3);
+		EvaluationFormSurvey survey1 = sut.createSurvey(ores, "1", null, formEntry, null);
+		EvaluationFormSurvey survey2 = sut.createSurvey(ores, "2", null, formEntry, survey1);
+		EvaluationFormSurvey survey3 = sut.createSurvey(ores, "3", null, formEntry, survey2);
+		EvaluationFormSurvey survey4 = sut.createSurvey(ores, "4", null, formEntry, survey3);
 		dbInstance.commitAndCloseSession();
 		EvaluationFormSurvey next = sut.loadSeriesNext(survey2);
 		EvaluationFormSurvey seriesPrevious = survey2.getSeriesPrevious();
@@ -189,11 +231,11 @@ public class EvaluationFormSurveyDAOTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 		
 		SoftAssertions softly = new SoftAssertions();
-		survey1 = sut.loadByResourceable(ores, "1");
+		survey1 = sut.loadByResourceable(ores, "1", null);
 		softly.assertThat(survey1.getSeriesIndex()).isEqualTo(1);
-		survey3 = sut.loadByResourceable(ores, "3");
+		survey3 = sut.loadByResourceable(ores, "3", null);
 		softly.assertThat(survey3.getSeriesIndex()).isEqualTo(2);
-		survey4 = sut.loadByResourceable(ores, "4");
+		survey4 = sut.loadByResourceable(ores, "4", null);
 		softly.assertThat(survey4.getSeriesIndex()).isEqualTo(3);
 	}
 
diff --git a/src/test/java/org/olat/modules/forms/manager/EvaluationFormTestsHelper.java b/src/test/java/org/olat/modules/forms/manager/EvaluationFormTestsHelper.java
index 81ec8a6ec631e8a70781803ecea94d73e7a046be..4a4562bbbf31246f4521c42a4ad1c3c7b1378a85 100644
--- a/src/test/java/org/olat/modules/forms/manager/EvaluationFormTestsHelper.java
+++ b/src/test/java/org/olat/modules/forms/manager/EvaluationFormTestsHelper.java
@@ -19,6 +19,8 @@
  */
 package org.olat.modules.forms.manager;
 
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
+
 import java.util.UUID;
 
 import org.olat.core.commons.persistence.DB;
@@ -120,7 +122,7 @@ public class EvaluationFormTestsHelper {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
 		String subIdent = UUID.randomUUID().toString();
 		RepositoryEntry formEntry = createFormEntry();
-		return evaluationFormManager.createSurvey(ores, subIdent, formEntry);
+		return evaluationFormManager.createSurvey(of(ores, subIdent), formEntry);
 	}
 	
 	EvaluationFormParticipation createParticipation() {
diff --git a/src/test/java/org/olat/modules/quality/manager/QualityParticipationDAOTest.java b/src/test/java/org/olat/modules/quality/manager/QualityParticipationDAOTest.java
index 8eaceecaf24ba2cd63c0934616899b704a0b05f8..b25dedbf48d8a427c6afc50b5c5f4fd70dae21a8 100644
--- a/src/test/java/org/olat/modules/quality/manager/QualityParticipationDAOTest.java
+++ b/src/test/java/org/olat/modules/quality/manager/QualityParticipationDAOTest.java
@@ -22,6 +22,7 @@ package org.olat.modules.quality.manager;
 import static java.util.Arrays.asList;
 import static java.util.stream.Collectors.toList;
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
 import static org.olat.modules.quality.QualityDataCollectionStatus.FINISHED;
 import static org.olat.modules.quality.QualityDataCollectionStatus.PREPARATION;
 import static org.olat.modules.quality.QualityDataCollectionStatus.READY;
@@ -330,7 +331,7 @@ public class QualityParticipationDAOTest extends OlatTestCase {
 	@Test
 	public void shouldFilterExecutorParticipationsByEvaluationFormParticipation() {
 		QualityDataCollection dataCollection = qualityTestHelper.createDataCollection();
-		EvaluationFormSurveyRef survey = evaManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurveyRef survey = evaManager.loadSurvey(of(dataCollection));
 		Identity identity1 = JunitTestHelper.createAndPersistIdentityAsRndUser("quality-");
 		Identity identity2 = JunitTestHelper.createAndPersistIdentityAsRndUser("quality-");
 		Identity identity3 = JunitTestHelper.createAndPersistIdentityAsRndUser("quality-");
@@ -349,7 +350,7 @@ public class QualityParticipationDAOTest extends OlatTestCase {
 	@Test
 	public void shouldFilterExecutorParticipationsByParticipationStatus() {
 		QualityDataCollection dataCollection = qualityTestHelper.createDataCollection();
-		EvaluationFormSurveyRef survey = evaManager.loadSurvey(dataCollection, null);
+		EvaluationFormSurveyRef survey = evaManager.loadSurvey(of(dataCollection));
 		Identity identity1 = JunitTestHelper.createAndPersistIdentityAsRndUser("quality-");
 		Identity identity2 = JunitTestHelper.createAndPersistIdentityAsRndUser("quality-");
 		Identity identity3 = JunitTestHelper.createAndPersistIdentityAsRndUser("quality-");
diff --git a/src/test/java/org/olat/modules/quality/manager/QualityServiceImplTest.java b/src/test/java/org/olat/modules/quality/manager/QualityServiceImplTest.java
index 59bcd9c15210ee2cb48f53efa8f6e3f758b3c93a..4ebc7c47e5fb39a8fe32e18599f609037fe2d149 100644
--- a/src/test/java/org/olat/modules/quality/manager/QualityServiceImplTest.java
+++ b/src/test/java/org/olat/modules/quality/manager/QualityServiceImplTest.java
@@ -74,7 +74,7 @@ public class QualityServiceImplTest {
 	public void setUp() {
 		MockitoAnnotations.initMocks(this);
 		
-		when(evaluationFormManagerMock.loadSurvey(any(), any())).thenReturn(surveyMock);
+		when(evaluationFormManagerMock.loadSurvey(any())).thenReturn(surveyMock);
 	}
 	
 	@Test
diff --git a/src/test/java/org/olat/modules/quality/manager/QualityTestHelper.java b/src/test/java/org/olat/modules/quality/manager/QualityTestHelper.java
index 8c81a9e7d24edc02c14092698fc7cea75626f171..583fa715ca0583ba96de02d4a2b6d2522716902a 100644
--- a/src/test/java/org/olat/modules/quality/manager/QualityTestHelper.java
+++ b/src/test/java/org/olat/modules/quality/manager/QualityTestHelper.java
@@ -20,6 +20,7 @@
 package org.olat.modules.quality.manager;
 
 import static java.util.Collections.singletonList;
+import static org.olat.modules.forms.EvaluationFormSurveyIdentifier.of;
 
 import java.util.Calendar;
 import java.util.Collection;
@@ -203,13 +204,13 @@ public class QualityTestHelper {
 
 	EvaluationFormSurvey createSurvey(QualityDataCollection dataCollection) {
 		RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry();
-		return evaluationFormManager.createSurvey(dataCollection, null, entry);
+		return evaluationFormManager.createSurvey(of(dataCollection), entry);
 	}
 
 	EvaluationFormSurvey createRandomSurvey() {
 		OLATResource ores = JunitTestHelper.createRandomResource();
 		RepositoryEntry entry = JunitTestHelper.createAndPersistRepositoryEntry();
-		return evaluationFormManager.createSurvey(ores, null, entry);
+		return evaluationFormManager.createSurvey(of(ores), entry);
 	}
 	
 	EvaluationFormParticipation createParticipation() {