diff --git a/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml b/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
index ae60fe2af111c2b05917b3601c5301dfb7ea7863..0ec7c18fc0666c2779ac3a5f3b28f5247c17983c 100644
--- a/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
+++ b/src/main/java/org/olat/course/nodes/_spring/buildingblockContext.xml
@@ -8,7 +8,7 @@
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context.xsd">
 
-	<context:component-scan base-package="org.olat.course.nodes.en,org.olat.course.nodes.cl,org.olat.course.nodes.projectbroker.service,org.olat.course.nodes.gta.manager" />
+	<context:component-scan base-package="org.olat.course.nodes.en,org.olat.course.nodes.cl,org.olat.course.nodes.projectbroker.service,org.olat.course.nodes.gta" />
 	  
 	<!-- Course node spring config: Course Nodes are searched on the whole classpath, just place your CourceNodeConfiguration somewhere
 	on the classpath best as a jar. The xml file with ending ...Context.xml has do to be outside of the jar to get automatically loaded -->
diff --git a/src/main/java/org/olat/course/nodes/gta/GTAManager.java b/src/main/java/org/olat/course/nodes/gta/GTAManager.java
index 64030eb3691751c5d90cee0b0c8e3423fa93acc8..5859a22a63e38fdaa63a9aacedf327f6e78cf7a7 100644
--- a/src/main/java/org/olat/course/nodes/gta/GTAManager.java
+++ b/src/main/java/org/olat/course/nodes/gta/GTAManager.java
@@ -157,6 +157,9 @@ public interface GTAManager {
 	public Task nextStep(Task task, GTACourseNode cNode);
 	
 	
+
+	public List<Task> getTasks(TaskList taskList);
+	
 	/**
 	 * Return the tasks assigned to a person, individually or via a
 	 * business group.
diff --git a/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java b/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java
index 741c76cd062d44cf0ebb04dfc81ce5dc6cd831fd..746a050be9df66ffb81a24b701fa8e77e3fc47c1 100644
--- a/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java
+++ b/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java
@@ -443,6 +443,18 @@ public class GTAManagerImpl implements GTAManager {
 		return tasks.isEmpty() ? null : tasks.get(0);
 	}
 
+	@Override
+	public List<Task> getTasks(TaskList taskList) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select task from gtatask task ")
+		  .append(" inner join task.taskList tasklist ")
+		  .append(" where tasklist.key=:taskListKey ");
+		
+		return dbInstance.getCurrentEntityManager().createQuery(sb.toString(), Task.class)
+				.setParameter("taskListKey", taskList.getKey())
+				.getResultList();
+	}
+
 	@Override
 	public List<Task> getTasks(IdentityRef identity, RepositoryEntryRef entry, GTACourseNode cNode) {
 		StringBuilder sb = new StringBuilder();
diff --git a/src/main/java/org/olat/course/nodes/gta/rule/AbstractDueDateTaskRuleSPI.java b/src/main/java/org/olat/course/nodes/gta/rule/AbstractDueDateTaskRuleSPI.java
new file mode 100644
index 0000000000000000000000000000000000000000..868517dbdc2759013df742280930d318b870a16b
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/gta/rule/AbstractDueDateTaskRuleSPI.java
@@ -0,0 +1,183 @@
+/**
+ * <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.gta.rule;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.olat.basesecurity.GroupRoles;
+import org.olat.core.id.Identity;
+import org.olat.course.CourseFactory;
+import org.olat.course.ICourse;
+import org.olat.course.nodes.CourseNode;
+import org.olat.course.nodes.GTACourseNode;
+import org.olat.course.nodes.gta.GTAManager;
+import org.olat.course.nodes.gta.GTAType;
+import org.olat.course.nodes.gta.Task;
+import org.olat.course.nodes.gta.TaskList;
+import org.olat.group.BusinessGroup;
+import org.olat.group.BusinessGroupService;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.reminder.IdentitiesProviderRuleSPI;
+import org.olat.modules.reminder.ReminderRule;
+import org.olat.modules.reminder.model.ReminderRuleImpl;
+import org.olat.modules.reminder.rule.LaunchUnit;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryEntryRelationType;
+import org.olat.repository.manager.RepositoryEntryRelationDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 10.04.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public abstract class AbstractDueDateTaskRuleSPI implements IdentitiesProviderRuleSPI {
+	
+	@Autowired
+	private GTAManager gtaManager;
+	@Autowired
+	private BusinessGroupService businessGroupService;
+	@Autowired
+	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
+
+	@Override
+	public List<Identity> evaluate(RepositoryEntry entry, ReminderRule rule) {
+		List<Identity> identities = null;
+		if(rule instanceof ReminderRuleImpl) {
+			ReminderRuleImpl r = (ReminderRuleImpl)rule;
+			String nodeIdent = r.getLeftOperand();
+	
+			ICourse course = CourseFactory.loadCourse(entry.getOlatResource());
+			CourseNode courseNode = course.getRunStructure().getNode(nodeIdent);
+			if(courseNode instanceof GTACourseNode) {
+				identities = evaluateRule(entry, (GTACourseNode)courseNode, r);
+			}
+		}
+		return identities == null ? Collections.<Identity>emptyList() : identities;
+	}
+	
+	protected List<Identity> evaluateRule(RepositoryEntry entry, GTACourseNode gtaNode, ReminderRuleImpl r) {
+		List<Identity> identities = null;
+		Date dueDate = getDueDate(gtaNode);
+		if(dueDate != null) {
+			int value = Integer.parseInt(r.getRightOperand());
+			String unit = r.getRightUnit();
+			Date now = new Date();
+			if(near(dueDate, now, value, LaunchUnit.valueOf(unit))) {
+				identities = getPeopleToRemind(entry, gtaNode);
+			}
+		}
+		return identities == null ? Collections.<Identity>emptyList() : identities;
+	}
+	
+	protected abstract Date getDueDate(GTACourseNode gtaNode);
+	
+	protected List<Identity> getPeopleToRemind(RepositoryEntry entry, GTACourseNode gtaNode) {
+		ModuleConfiguration config = gtaNode.getModuleConfiguration();
+		TaskList taskList = gtaManager.getTaskList(entry, gtaNode);
+		if(GTAType.group.name().equals(config.getStringValue(GTACourseNode.GTASK_TYPE))) {
+			return getGroupsToRemind(taskList, gtaNode);
+		} else {
+			return getIndividualsToRemind(taskList, entry);
+		}
+	}
+	
+	protected List<Identity> getGroupsToRemind(TaskList taskList, GTACourseNode gtaNode) {
+		List<Task> tasks = gtaManager.getTasks(taskList);
+		Set<BusinessGroup> doneTasks = new HashSet<BusinessGroup>();
+		for(Task task:tasks) {
+			if(task.getBusinessGroup() != null) {
+				doneTasks.add(task.getBusinessGroup());
+			}
+		}
+
+		List<BusinessGroup> groups = gtaManager.getBusinessGroups(gtaNode);
+		for(Iterator<BusinessGroup> groupIt=groups.iterator(); groupIt.hasNext(); ) {
+			if(doneTasks.contains(groupIt.next())) {
+				groupIt.remove();
+			}
+		}
+
+		return businessGroupService.getMembers(groups, GroupRoles.participant.name());
+	}
+	
+	protected List<Identity> getIndividualsToRemind(TaskList taskList, RepositoryEntry entry) {
+		List<Task> tasks = gtaManager.getTasks(taskList);
+		Set<Identity> doneTasks = new HashSet<Identity>();
+		for(Task task:tasks) {
+			if(task.getIdentity() != null) {
+				doneTasks.add(task.getIdentity());
+			}
+		}
+
+		List<Identity> identities = repositoryEntryRelationDao.getMembers(entry, RepositoryEntryRelationType.both, GroupRoles.participant.name());
+		for(Iterator<Identity> identityIt=identities.iterator(); identityIt.hasNext(); ) {
+			if(doneTasks.contains(identityIt.next())) {
+				identityIt.remove();
+			}
+		}
+		
+		return identities;
+	}
+	
+	
+	private boolean near(Date date, Date now, int distance, LaunchUnit unit) {
+		double between = -1;
+		switch(unit) {
+			case day:
+				between = daysBetween(now, date);
+				break;
+			case week:
+				between = weeksBetween(now, date);
+				break;
+			case month:
+				between = monthsBetween(now, date);
+				break;
+			case year:
+				between = yearsBetween(now, date);
+				break;
+		}
+		return  between <= distance || between < 0.0;
+	}
+	
+	private double daysBetween(Date d1, Date d2) {
+        return ((d2.getTime() - d1.getTime()) / (1000d * 60d * 60d * 24d));
+	}
+	
+	private double weeksBetween(Date d1, Date d2) {
+        return ((d2.getTime() - d1.getTime()) / (1000d * 60d * 60d * 24d * 7d));
+	}
+	
+	private double monthsBetween(Date d1, Date d2) {
+        return ((d2.getTime() - d1.getTime()) / (1000d * 60d * 60d * 24d * 30d));
+	}
+	
+	private double yearsBetween(Date d1, Date d2) {
+        return ((d2.getTime() - d1.getTime()) / (1000d * 60d * 60d * 24d * 365d));
+	}
+	
+	
+}
diff --git a/src/main/java/org/olat/course/nodes/gta/rule/AssignTaskRuleSPI.java b/src/main/java/org/olat/course/nodes/gta/rule/AssignTaskRuleSPI.java
new file mode 100644
index 0000000000000000000000000000000000000000..d5ac5d5595776589fb81c92b3840b0433e8f85df
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/gta/rule/AssignTaskRuleSPI.java
@@ -0,0 +1,66 @@
+/**
+ * <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.gta.rule;
+
+import java.util.Date;
+
+import org.olat.course.nodes.GTACourseNode;
+import org.olat.course.nodes.gta.ui.BeforeDateTaskRuleEditor;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.reminder.ReminderRule;
+import org.olat.modules.reminder.RuleEditorFragment;
+import org.olat.repository.RepositoryEntry;
+import org.springframework.stereotype.Service;
+
+/**
+ * 
+ * Initial date: 10.04.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+public class AssignTaskRuleSPI extends AbstractDueDateTaskRuleSPI {
+
+	@Override
+	public String getLabelI18nKey() {
+		return "rule.assign.task";
+	}
+
+	@Override
+	public String getCategory() {
+		return "assessment";
+	}
+
+	@Override
+	public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) {
+		return new BeforeDateTaskRuleEditor(rule, entry, AssignTaskRuleSPI.class.getSimpleName());
+	}
+
+	@Override
+	protected Date getDueDate(GTACourseNode gtaNode) {
+		Date dueDate = null;
+		ModuleConfiguration config = gtaNode.getModuleConfiguration();
+		boolean assignment = config.getBooleanSafe(GTACourseNode.GTASK_ASSIGNMENT);
+		if(assignment) {
+			dueDate = config.getDateValue(GTACourseNode.GTASK_ASSIGNMENT_DEADLINE);
+		}
+		return dueDate;
+	}
+}
diff --git a/src/main/java/org/olat/course/nodes/gta/rule/SubmissionTaskRuleSPI.java b/src/main/java/org/olat/course/nodes/gta/rule/SubmissionTaskRuleSPI.java
new file mode 100644
index 0000000000000000000000000000000000000000..a22e6eae58692835b78043362bc2a98d3b1de155
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/gta/rule/SubmissionTaskRuleSPI.java
@@ -0,0 +1,77 @@
+/**
+ * <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.gta.rule;
+
+import java.util.Date;
+
+import org.olat.course.nodes.GTACourseNode;
+import org.olat.course.nodes.gta.GTAManager;
+import org.olat.course.nodes.gta.ui.BeforeDateTaskRuleEditor;
+import org.olat.group.BusinessGroupService;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.reminder.ReminderRule;
+import org.olat.modules.reminder.RuleEditorFragment;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.manager.RepositoryEntryRelationDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 
+ * Initial date: 10.04.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+@Service
+public class SubmissionTaskRuleSPI extends AbstractDueDateTaskRuleSPI {
+	
+	@Autowired
+	private GTAManager gtaManager;
+	@Autowired
+	private BusinessGroupService businessGroupService;
+	@Autowired
+	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
+
+	@Override
+	public String getLabelI18nKey() {
+		return "rule.submission.task";
+	}
+
+	@Override
+	public String getCategory() {
+		return "assessment";
+	}
+
+	@Override
+	public RuleEditorFragment getEditorFragment(ReminderRule rule, RepositoryEntry entry) {
+		return new BeforeDateTaskRuleEditor(rule, entry, SubmissionTaskRuleSPI.class.getSimpleName());
+	}
+
+	@Override
+	protected Date getDueDate(GTACourseNode gtaNode) {
+		Date dueDate = null;
+		ModuleConfiguration config = gtaNode.getModuleConfiguration();
+		boolean submit = config.getBooleanSafe(GTACourseNode.GTASK_SUBMIT);
+		if(submit) {
+			dueDate = config.getDateValue(GTACourseNode.GTASK_SUBMIT_DEADLINE);
+		}
+		return dueDate;
+	}
+}
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/BeforeDateTaskRuleEditor.java b/src/main/java/org/olat/course/nodes/gta/ui/BeforeDateTaskRuleEditor.java
new file mode 100644
index 0000000000000000000000000000000000000000..81903de8019f2c85febf1b2b5c7689b29087bc3b
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/gta/ui/BeforeDateTaskRuleEditor.java
@@ -0,0 +1,223 @@
+/**
+ * <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.gta.ui;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+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.SingleSelection;
+import org.olat.core.gui.components.form.flexible.elements.TextElement;
+import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
+import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.translator.Translator;
+import org.olat.core.util.CodeHelper;
+import org.olat.core.util.StringHelper;
+import org.olat.core.util.Util;
+import org.olat.course.CourseFactory;
+import org.olat.course.ICourse;
+import org.olat.course.nodes.CourseNode;
+import org.olat.course.nodes.GTACourseNode;
+import org.olat.course.nodes.gta.rule.AssignTaskRuleSPI;
+import org.olat.course.nodes.gta.rule.SubmissionTaskRuleSPI;
+import org.olat.modules.ModuleConfiguration;
+import org.olat.modules.reminder.ReminderRule;
+import org.olat.modules.reminder.RuleEditorFragment;
+import org.olat.modules.reminder.model.ReminderRuleImpl;
+import org.olat.modules.reminder.rule.LaunchUnit;
+import org.olat.repository.RepositoryEntry;
+
+/**
+ * 
+ * Initial date: 10.04.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class BeforeDateTaskRuleEditor extends RuleEditorFragment {
+	
+	private static final String[] unitKeys = new String[]{
+		LaunchUnit.day.name(), LaunchUnit.week.name(), LaunchUnit.month.name(), LaunchUnit.year.name()
+	};
+	
+	private TextElement valueEl;
+	private SingleSelection courseNodeEl, unitEl;
+	
+	private final String ruleType;
+	
+	private final RepositoryEntry entry;
+	
+	public BeforeDateTaskRuleEditor(ReminderRule rule, RepositoryEntry entry, String ruleType) {
+		super(rule);
+		this.entry = entry;
+		this.ruleType = ruleType;
+	}
+
+	@Override
+	public FormItem initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
+
+		String page = Util.getPackageVelocityRoot(this.getClass()) + "/date_rule.html";
+		String id = Long.toString(CodeHelper.getRAMUniqueID());
+		
+		Translator trans = Util
+				.createPackageTranslator(BeforeDateTaskRuleEditor.class, formLayout.getTranslator().getLocale(), formLayout.getTranslator());
+		FormLayoutContainer ruleCont = FormLayoutContainer
+				.createCustomFormLayout("taks.".concat(id), formLayout.getTranslator(), page);
+		ruleCont.setRootForm(formLayout.getRootForm());
+		ruleCont.setTranslator(trans);
+		formLayout.add(ruleCont);
+		
+		ICourse course = CourseFactory.loadCourse(entry.getOlatResource());
+
+		String currentValue = null;
+		String currentUnit = null;
+		String currentCourseNode = null;
+		
+		if(rule instanceof ReminderRuleImpl) {
+			ReminderRuleImpl r = (ReminderRuleImpl)rule;
+			currentUnit = r.getRightUnit();
+			currentValue = r.getRightOperand();
+			currentCourseNode = r.getLeftOperand();
+		}
+		
+		List<CourseNode> attemptableNodes = new ArrayList<>();
+		searchAttemptableNodes(course.getRunStructure().getRootNode(), attemptableNodes);
+		
+		String[] nodeKeys = new String[attemptableNodes.size()];
+		String[] nodeValues = new String[attemptableNodes.size()];
+		
+		for(int i=0; i<attemptableNodes.size(); i++) {
+			CourseNode attemptableNode = attemptableNodes.get(0);
+			nodeKeys[i] = attemptableNode.getIdent();
+			nodeValues[i] = attemptableNode.getShortTitle() + " ( " + attemptableNode.getIdent() + " )";
+		}
+		
+		courseNodeEl = uifactory.addDropdownSingleselect("coursenodes", null, ruleCont, nodeKeys, nodeValues, null);
+		courseNodeEl.setDomReplacementWrapperRequired(false);
+		boolean nodeSelected = false;
+		if(currentCourseNode != null) {
+			for(String nodeKey:nodeKeys) {
+				if(currentCourseNode.equals(nodeKey)) {
+					courseNodeEl.select(nodeKey, true);
+					nodeSelected = true;
+				}
+			}
+		}
+		if(!nodeSelected && nodeKeys.length > 0) {
+			courseNodeEl.select(nodeKeys[0], true);
+		}
+		if(StringHelper.containsNonWhitespace(currentCourseNode) && !nodeSelected) {
+			courseNodeEl.setErrorKey("error.course.node.found", null);
+		}
+
+		valueEl = uifactory.addTextElement("value", null, 128, currentValue, ruleCont);
+		valueEl.setDomReplacementWrapperRequired(false);
+		valueEl.setDisplaySize(3);
+
+		String[] unitValues = new String[] {
+				trans.translate(LaunchUnit.day.name()), trans.translate(LaunchUnit.week.name()),
+				trans.translate(LaunchUnit.month.name()), trans.translate(LaunchUnit.year.name())
+		};
+
+		unitEl = uifactory.addDropdownSingleselect("unit", null, ruleCont, unitKeys, unitValues, null);
+		unitEl.setDomReplacementWrapperRequired(false);
+		boolean selected = false;
+		if(currentUnit != null) {
+			for(String unitKey:unitKeys) {
+				if(currentUnit.equals(unitKey)) {
+					unitEl.select(unitKey, true);
+					selected = true;
+				}
+			}
+		}
+		if(!selected) {
+			unitEl.select(unitKeys[1], true);	
+		}
+		
+		return ruleCont;
+	}
+	
+	private void searchAttemptableNodes(CourseNode courseNode, List<CourseNode> nodes) {
+		if (courseNode instanceof GTACourseNode) {
+			GTACourseNode assessableCourseNode = (GTACourseNode) courseNode;
+			ModuleConfiguration config = assessableCourseNode.getModuleConfiguration();
+			
+			if(AssignTaskRuleSPI.class.getSimpleName().equals(ruleType)) {
+				boolean assignment = config.getBooleanSafe(GTACourseNode.GTASK_ASSIGNMENT);
+				Date dueDate = config.getDateValue(GTACourseNode.GTASK_ASSIGNMENT_DEADLINE);
+				if(assignment && dueDate != null) {
+					nodes.add(courseNode);
+				}
+			} else if(SubmissionTaskRuleSPI.class.getSimpleName().equals(ruleType)) {
+				boolean submit = config.getBooleanSafe(GTACourseNode.GTASK_SUBMIT);
+				Date dueDate = config.getDateValue(GTACourseNode.GTASK_SUBMIT_DEADLINE);
+				if(submit && dueDate != null) {
+					nodes.add(courseNode);
+				}
+			}
+		}
+		
+		for(int i=0; i<courseNode.getChildCount(); i++) {
+			CourseNode child = (CourseNode)courseNode.getChildAt(i);
+			searchAttemptableNodes(child, nodes);
+		}
+	}
+
+	@Override
+	public boolean validateFormLogic(UserRequest ureq) {
+		boolean allOk = true;
+		
+		courseNodeEl.clearError();
+		if(!courseNodeEl.isOneSelected()) {
+			courseNodeEl.setErrorKey("form.mandatory.hover", null);
+			allOk &= false;
+		}
+		
+		unitEl.clearError();
+		if(!unitEl.isOneSelected()) {
+			unitEl.setErrorKey("form.mandatory.hover", null);
+			allOk &= false;
+		}
+		
+		valueEl.clearError();
+		if(!StringHelper.containsNonWhitespace(valueEl.getValue())) {
+			valueEl.setErrorKey("form.mandatory.hover", null);
+			allOk &= false;
+		}
+		
+		return allOk;
+	}
+
+	@Override
+	public ReminderRule getConfiguration() {
+		ReminderRuleImpl configuredRule = null; 
+		if(courseNodeEl.isOneSelected() && unitEl.isOneSelected() && StringHelper.containsNonWhitespace(valueEl.getValue())) {
+			configuredRule = new ReminderRuleImpl();
+			configuredRule.setType(ruleType);
+			configuredRule.setLeftOperand(courseNodeEl.getSelectedKey());
+			configuredRule.setOperator("<");
+			configuredRule.setRightOperand(valueEl.getValue());
+			configuredRule.setRightUnit(unitEl.getSelectedKey());
+		}
+		return configuredRule;
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_content/date_rule.html b/src/main/java/org/olat/course/nodes/gta/ui/_content/date_rule.html
new file mode 100644
index 0000000000000000000000000000000000000000..0ed17292af8490454e9fad32b7819360db7636a2
--- /dev/null
+++ b/src/main/java/org/olat/course/nodes/gta/ui/_content/date_rule.html
@@ -0,0 +1,9 @@
+<div class='form-inline'>
+	$r.render("coursenodes") $r.render("value") $r.render("unit") <span class="form-control-static">$r.translate("before")</span>
+	#if($f.hasError("value"))
+		<br/>$r.render("value_ERROR")
+	#end
+	#if($f.hasError("coursenodes"))
+		<br/>$r.render("coursenodes_ERROR")
+	#end
+</div>
\ No newline at end of file
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties
index 8cf18bb2634bd73fdc370c8fbec7ced2082dd974..65ef7cf8a243d21015002def9d60d13a4ad7b2c3 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_de.properties
@@ -4,6 +4,7 @@ add.task=Aufgaben hochladen
 assessment.group.tool=Gruppe bewerten
 assignment.config.title=Aufgabe zuweisen
 assignment.deadline=Zuweisungstermin
+before=Vor
 bulk.review=Beurteilung herunterladen
 bulk.solutions=Musterl\u00F6sungen herunterladen
 bulk.submitted.documents=Abgegebene Dokumenten
diff --git a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties
index 62659e3c01a81e7b4bfedce02f4d46f838abcc96..dbb66927a8401f02284a3a4e1361c662892beb89 100644
--- a/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/nodes/gta/ui/_i18n/LocalStrings_en.properties
@@ -3,6 +3,7 @@ add.solution=Add solution
 add.task=Add task
 assignment.config.title=Task assignment configuration
 assignment.deadline=Assignment deadline
+before=Before
 bulk.review=Download review
 bulk.solutions=Download solutions
 bulk.submitted.documents=Download submitted documents
diff --git a/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java b/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java
index 11c2561ebd01014fb0f8e50a9ea93004928e28b8..adb5c0cef05cab3f959538ebf526f3aa359e4967 100644
--- a/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java
+++ b/src/main/java/org/olat/course/reminder/ui/CourseReminderListController.java
@@ -155,7 +155,7 @@ public class CourseReminderListController extends FormBasicController implements
 		String entryPoint = entry.getOLATResourceable().getResourceableTypeName();
 		if("SentReminders".equalsIgnoreCase(entryPoint)) {
 			Long key = entry.getOLATResourceable().getResourceableId();
-			System.out.println(key);
+			doSendReminderList(ureq, key);
 		}
 	}
 
@@ -239,14 +239,14 @@ public class CourseReminderListController extends FormBasicController implements
 		toolbarPanel.pushController(translate("new.reminder"), reminderEditCtrl);	
 	}
 	
-	private void doSendReminderList(UserRequest ureq, ReminderRow row) {
+	private void doSendReminderList(UserRequest ureq, Long reminderKey) {
 		removeAsListenerAndDispose(sendReminderListCtrl);
 		
-		OLATResourceable ores = OresHelper.createOLATResourceableInstance("SentReminders", row.getKey());
+		OLATResourceable ores = OresHelper.createOLATResourceableInstance("SentReminders", reminderKey);
 		ThreadLocalUserActivityLogger.addLoggingResourceInfo(LoggingResourceable.wrapBusinessPath(ores));
 		WindowControl bwControl = BusinessControlFactory.getInstance().createBusinessWindowControl(ores, null, getWindowControl());
 
-		Reminder reminder = reminderManager.loadByKey(row.getKey());
+		Reminder reminder = reminderManager.loadByKey(reminderKey);
 		sendReminderListCtrl = new CourseSendReminderListController(ureq, bwControl, reminder);
 		listenTo(sendReminderListCtrl);
 		addToHistory(ureq, sendReminderListCtrl);
@@ -336,7 +336,7 @@ public class CourseReminderListController extends FormBasicController implements
 				if("edit".equals(cmd)) {
 					doEdit(ureq, row);
 				} else if("show.sent".equals(cmd)) {
-					doSendReminderList(ureq, row);
+					doSendReminderList(ureq, row.getKey());
 				} else if("delete".equals(cmd)) {
 					doConfirmDelete(ureq, row);
 				} else if("duplicate".equals(cmd)) {
diff --git a/src/main/java/org/olat/course/reminder/ui/InitialAttemptsRuleEditor.java b/src/main/java/org/olat/course/reminder/ui/InitialAttemptsRuleEditor.java
index 5cbe91afeca3ee07525c55d187ed5afc3c5b1acd..55a3bf2e2f90c1a89c1e6f3dc989ab01f787fdf4 100644
--- a/src/main/java/org/olat/course/reminder/ui/InitialAttemptsRuleEditor.java
+++ b/src/main/java/org/olat/course/reminder/ui/InitialAttemptsRuleEditor.java
@@ -29,6 +29,7 @@ import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
 import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.CodeHelper;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
@@ -72,6 +73,7 @@ public class InitialAttemptsRuleEditor extends RuleEditorFragment {
 		String page = Util.getPackageVelocityRoot(this.getClass()) + "/initial_attempts.html";
 		String id = Long.toString(CodeHelper.getRAMUniqueID());
 		
+		Translator trans = formLayout.getTranslator();
 		FormLayoutContainer ruleCont = FormLayoutContainer
 				.createCustomFormLayout("attempts.".concat(id), formLayout.getTranslator(), page);
 		ruleCont.setRootForm(formLayout.getRootForm());
@@ -124,9 +126,10 @@ public class InitialAttemptsRuleEditor extends RuleEditorFragment {
 		valueEl = uifactory.addTextElement("attemptvalue", null, 128, currentValue, ruleCont);
 		valueEl.setDomReplacementWrapperRequired(false);
 		valueEl.setDisplaySize(3);
-		
+
 		String[] unitValues = new String[] {
-			LaunchUnit.day.name(), LaunchUnit.week.name(), LaunchUnit.month.name(), LaunchUnit.year.name()
+				trans.translate(LaunchUnit.day.name()), trans.translate(LaunchUnit.week.name()),
+				trans.translate(LaunchUnit.month.name()), trans.translate(LaunchUnit.year.name())
 		};
 
 		unitEl = uifactory.addDropdownSingleselect("attemptunit", null, ruleCont, unitKeys, unitValues, null);
diff --git a/src/main/java/org/olat/course/reminder/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/reminder/ui/_i18n/LocalStrings_de.properties
index 01b65c1fa9db499330a1c519910d91b1bd15046b..02208cb92f3a8e7836741e0085c7fe0b922e5bbb 100644
--- a/src/main/java/org/olat/course/reminder/ui/_i18n/LocalStrings_de.properties
+++ b/src/main/java/org/olat/course/reminder/ui/_i18n/LocalStrings_de.properties
@@ -7,6 +7,7 @@ course.role.owner=Besitzer
 course.role.ownerAndCoach=Besitzer und Coach
 course.role.participant=Teilnehmer
 course.role.participantAndCoach=Coach und Teilnehmer
+day=Tagen
 delete.rule=-
 dialog.modal.delete.text=Wollen Sie wirklich diese Errinerung "{0}" l\u00F6schen?
 duplicate=Duplizieren
@@ -15,6 +16,7 @@ email.content=E-Mail
 error.course.node.found=Kurs Element existiert nicht mehr
 failed=Failed
 logs=Logs
+month=Monaten
 new.reminder=Neue Erinnerung
 passed=Passed
 points=Punkte
@@ -23,10 +25,12 @@ reminder.id=ID
 reminder.resend=Errinerung wurde erfolgreisch geschickt.
 reminders=Errinerungen
 resend=Wieder schicken
+rule.assign.task=Grupenaufgabe Zuweisung
 rule.attempts=Attempts
 rule.initial.attempts.date=Initial attempt date
 rule.passed=Passed
 rule.score=Score
+rule.submission.task=Grupenaufgabe Dokumenten abgeben
 rules.description=When matching all of the following conditions
 send=Erinnerung jetzt schicken
 send.reminder=Geschickte Errinerungen
@@ -43,3 +47,5 @@ table.header.sendTime=Send time
 table.header.status=Status
 table.header.username=Benutzername
 tools=Werkzeug
+week=Wochen
+year=Jahren
diff --git a/src/main/java/org/olat/course/reminder/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/reminder/ui/_i18n/LocalStrings_en.properties
index 83d36ab2ec1bcb202dc87b85aff5255412fa3f7b..50e1dec8add84075c75ba4909575ec24957c21b1 100644
--- a/src/main/java/org/olat/course/reminder/ui/_i18n/LocalStrings_en.properties
+++ b/src/main/java/org/olat/course/reminder/ui/_i18n/LocalStrings_en.properties
@@ -7,6 +7,7 @@ course.role.owner=Owners
 course.role.ownerAndCoach=Owners and coachs
 course.role.participant=Participants
 course.role.participantAndCoach=Coachs and participants
+day=Days
 delete.rule=-
 dialog.modal.delete.text=Do your really want to delete this reminder "{0}"?
 duplicate=Douplicate
@@ -15,6 +16,7 @@ email.content=E-Mail
 error.course.node.found=The cours element doesn't exist
 failed=Failed
 logs=Logs
+month=Months
 new.reminder=New reminder
 passed=Passed
 points=Points
@@ -24,9 +26,11 @@ reminder.resend=Reminder was successfully sent.
 reminders=Errinerungen
 resend=Resend
 rule.attempts=Attempts
+rule.assign.task=Group task assignment
 rule.initial.attempts.date=Initial attempt date
 rule.passed=Passed
 rule.score=Score
+rule.submission.task=Group task documents submission
 rules.description=When matching all of the following conditions
 send=Send reminders now
 send.reminder=Send reminders
@@ -43,3 +47,5 @@ table.header.sendTime=Send time
 table.header.status=Status
 table.header.username=Username
 tools=Tools
+weeks=Weeks
+year=Years
diff --git a/src/main/java/org/olat/modules/reminder/IdentitiesProviderRuleSPI.java b/src/main/java/org/olat/modules/reminder/IdentitiesProviderRuleSPI.java
new file mode 100644
index 0000000000000000000000000000000000000000..90853dc55bb80067bd7ed0673dfbbebc6e9bd911
--- /dev/null
+++ b/src/main/java/org/olat/modules/reminder/IdentitiesProviderRuleSPI.java
@@ -0,0 +1,39 @@
+/**
+ * <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.reminder;
+
+import java.util.List;
+
+import org.olat.core.id.Identity;
+import org.olat.repository.RepositoryEntry;
+
+/**
+ * 
+ * Rules which deliver a list of identities to remind
+ * 
+ * Initial date: 10.04.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public interface IdentitiesProviderRuleSPI extends RuleSPI {
+	
+	public List<Identity> evaluate(RepositoryEntry entry, ReminderRule rule);
+
+}
diff --git a/src/main/java/org/olat/modules/reminder/manager/ReminderRuleEngine.java b/src/main/java/org/olat/modules/reminder/manager/ReminderRuleEngine.java
index b7cd349daef872793ac0e2dc2f535818b4b3591a..b2d7592fb40a640b9d453233c23f0d2dfb8636a9 100644
--- a/src/main/java/org/olat/modules/reminder/manager/ReminderRuleEngine.java
+++ b/src/main/java/org/olat/modules/reminder/manager/ReminderRuleEngine.java
@@ -29,6 +29,7 @@ import java.util.Set;
 import org.olat.basesecurity.GroupRoles;
 import org.olat.core.id.Identity;
 import org.olat.modules.reminder.FilterRuleSPI;
+import org.olat.modules.reminder.IdentitiesProviderRuleSPI;
 import org.olat.modules.reminder.Reminder;
 import org.olat.modules.reminder.ReminderModule;
 import org.olat.modules.reminder.ReminderRule;
@@ -122,18 +123,19 @@ public class ReminderRuleEngine {
 	}
 	
 	protected List<Identity> getIdentities(RepositoryEntry entry, Reminder reminder, List<ReminderRule> ruleList, boolean resend) {	
-		List<ReminderRule> roleRules = new ArrayList<>();
+		List<ReminderRule> identitiesProviderRules = new ArrayList<>();
 
 		for(Iterator<ReminderRule> ruleIt=ruleList.iterator(); ruleIt.hasNext(); ) {
 			ReminderRule rule = ruleIt.next();
-			if(REPO_ROLE_RULE_TYPE.equals(rule.getType()) || BUSINESSGROUP_ROLE_RULE_TYPE.equals(rule.getType())) {
-				roleRules.add(rule);
+			RuleSPI ruleSpi = reminderModule.getRuleSPIByType(rule.getType());
+			if(ruleSpi instanceof IdentitiesProviderRuleSPI) {
+				identitiesProviderRules.add(rule);
 				ruleIt.remove();
 			}
 		}
 		
 		List<Identity> identities;
-		if(roleRules.isEmpty()) {
+		if(identitiesProviderRules.isEmpty()) {
 			//all members of repository entry
 			List<Identity> duplicatedIdentities = repositoryEntryRelationDao.getMembers(entry, RepositoryEntryRelationType.both,
 					GroupRoles.owner.name(), GroupRoles.coach.name(), GroupRoles.participant.name());
@@ -141,14 +143,10 @@ public class ReminderRuleEngine {
 		} else {
 			identities = null;
 			
-			for(ReminderRule rule:roleRules) {
-				List<Identity> members = null;
-				if(REPO_ROLE_RULE_TYPE.equals(rule.getType())) {
-					members = repoRoleRuleSpi.evaluate(entry, rule);
-				} else if(BUSINESSGROUP_ROLE_RULE_TYPE.equals(rule.getType())) {
-					members = groupRoleRuleSpi.evaluate(rule);
-				}
-				
+			for(ReminderRule rule:identitiesProviderRules) {
+				RuleSPI ruleSpi = reminderModule.getRuleSPIByType(rule.getType());
+				IdentitiesProviderRuleSPI identitiesProviderRuleSpi = (IdentitiesProviderRuleSPI)ruleSpi;
+				List<Identity> members = identitiesProviderRuleSpi.evaluate(entry, rule);
 				if(identities == null) {
 					identities = members;
 				} else {
diff --git a/src/main/java/org/olat/modules/reminder/rule/AbstractLaunchDateRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/AbstractLaunchDateRuleSPI.java
index 6bb057aa230632fc7798130f86a3414644b41707..0320968df7aaf95ae5e6f57981841237ad41a5e1 100644
--- a/src/main/java/org/olat/modules/reminder/rule/AbstractLaunchDateRuleSPI.java
+++ b/src/main/java/org/olat/modules/reminder/rule/AbstractLaunchDateRuleSPI.java
@@ -73,14 +73,14 @@ public abstract class AbstractLaunchDateRuleSPI  implements FilterRuleSPI {
 				Date initialLaunchDate = initialLaunchDates.get(identity.getKey());
 				if(initialLaunchDate == null) {
 					identityIt.remove();
-				} else if(!evaluate(initialLaunchDate, now, distance, unit)) {
+				} else if(!after(initialLaunchDate, now, distance, unit)) {
 					identityIt.remove();
 				}	
 			}
 		}
 	}
 	
-	private boolean evaluate(Date date, Date now, int distance, LaunchUnit unit) {
+	private boolean after(Date date, Date now, int distance, LaunchUnit unit) {
 		double between = -1;
 		switch(unit) {
 			case day:
diff --git a/src/main/java/org/olat/modules/reminder/rule/BusinessGroupRoleRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/BusinessGroupRoleRuleSPI.java
index 8e360a466f8869368203e6d082b59bdb4c2b21a7..c869ec73b6a7c79904f614efac3a72a4d47043ea 100644
--- a/src/main/java/org/olat/modules/reminder/rule/BusinessGroupRoleRuleSPI.java
+++ b/src/main/java/org/olat/modules/reminder/rule/BusinessGroupRoleRuleSPI.java
@@ -28,9 +28,9 @@ import org.olat.core.util.StringHelper;
 import org.olat.group.BusinessGroupRef;
 import org.olat.group.manager.BusinessGroupRelationDAO;
 import org.olat.group.model.BusinessGroupRefImpl;
+import org.olat.modules.reminder.IdentitiesProviderRuleSPI;
 import org.olat.modules.reminder.ReminderRule;
 import org.olat.modules.reminder.RuleEditorFragment;
-import org.olat.modules.reminder.RuleSPI;
 import org.olat.modules.reminder.model.ReminderRuleImpl;
 import org.olat.modules.reminder.ui.BusinessGroupRoleEditor;
 import org.olat.repository.RepositoryEntry;
@@ -44,7 +44,7 @@ import org.springframework.stereotype.Service;
  *
  */
 @Service
-public class BusinessGroupRoleRuleSPI implements RuleSPI {
+public class BusinessGroupRoleRuleSPI implements IdentitiesProviderRuleSPI {
 
 	@Autowired
 	private BusinessGroupRelationDAO businessGroupRelationDao;
@@ -64,7 +64,8 @@ public class BusinessGroupRoleRuleSPI implements RuleSPI {
 		return new BusinessGroupRoleEditor(rule, entry);
 	}
 
-	public List<Identity> evaluate(ReminderRule rule) {
+	@Override
+	public List<Identity> evaluate(RepositoryEntry entry, ReminderRule rule) {
 		List<Identity> identities = null;
 		
 		if(rule instanceof ReminderRuleImpl) {
diff --git a/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryRoleRuleSPI.java b/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryRoleRuleSPI.java
index 81ed16fd6b40f60711f738deeafe650c06e8a78a..236ef2f3f0d1f0fbad62e20c472f577d7ee3f401 100644
--- a/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryRoleRuleSPI.java
+++ b/src/main/java/org/olat/modules/reminder/rule/RepositoryEntryRoleRuleSPI.java
@@ -25,9 +25,9 @@ import java.util.List;
 import org.olat.basesecurity.GroupRoles;
 import org.olat.core.id.Identity;
 import org.olat.core.util.StringHelper;
+import org.olat.modules.reminder.IdentitiesProviderRuleSPI;
 import org.olat.modules.reminder.ReminderRule;
 import org.olat.modules.reminder.RuleEditorFragment;
-import org.olat.modules.reminder.RuleSPI;
 import org.olat.modules.reminder.model.ReminderRuleImpl;
 import org.olat.modules.reminder.ui.RepositoryEntryRoleEditor;
 import org.olat.repository.RepositoryEntry;
@@ -43,7 +43,7 @@ import org.springframework.stereotype.Service;
  *
  */
 @Service
-public class RepositoryEntryRoleRuleSPI implements RuleSPI  {
+public class RepositoryEntryRoleRuleSPI implements IdentitiesProviderRuleSPI  {
 
 	@Autowired
 	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
@@ -63,7 +63,7 @@ public class RepositoryEntryRoleRuleSPI implements RuleSPI  {
 		return new RepositoryEntryRoleEditor(rule);
 	}
 
-
+	@Override
 	public List<Identity> evaluate(RepositoryEntry entry, ReminderRule rule) {
 		List<Identity> identities = null;
 		if(rule instanceof ReminderRuleImpl) {
diff --git a/src/main/java/org/olat/modules/reminder/ui/CourseLaunchRuleEditor.java b/src/main/java/org/olat/modules/reminder/ui/CourseLaunchRuleEditor.java
index 611f9e07a8bc5ab2e9d7c2126c684fa3d0eede8f..c4d916d77bbbf89ec6d473e7a00c544ff39fb0c4 100644
--- a/src/main/java/org/olat/modules/reminder/ui/CourseLaunchRuleEditor.java
+++ b/src/main/java/org/olat/modules/reminder/ui/CourseLaunchRuleEditor.java
@@ -26,6 +26,7 @@ import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
 import org.olat.core.gui.components.form.flexible.elements.TextElement;
 import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer;
 import org.olat.core.gui.control.Controller;
+import org.olat.core.gui.translator.Translator;
 import org.olat.core.util.CodeHelper;
 import org.olat.core.util.StringHelper;
 import org.olat.core.util.Util;
@@ -61,6 +62,7 @@ public class CourseLaunchRuleEditor extends RuleEditorFragment {
 		String page = Util.getPackageVelocityRoot(this.getClass()) + "/course_launch.html";
 		String id = Long.toString(CodeHelper.getRAMUniqueID());
 		
+		Translator trans = formLayout.getTranslator();
 		FormLayoutContainer ruleCont = FormLayoutContainer
 				.createCustomFormLayout("course.launch.".concat(id), formLayout.getTranslator(), page);
 		ruleCont.setRootForm(formLayout.getRootForm());
@@ -79,10 +81,10 @@ public class CourseLaunchRuleEditor extends RuleEditorFragment {
 		valueEl.setDisplaySize(3);
 		
 		String[] unitValues = new String[] {
-				LaunchUnit.day.name(), LaunchUnit.week.name(), LaunchUnit.month.name(), LaunchUnit.year.name()
+				trans.translate(LaunchUnit.day.name()), trans.translate(LaunchUnit.week.name()),
+				trans.translate(LaunchUnit.month.name()), trans.translate(LaunchUnit.year.name())
 		};
 		
-
 		unitEl = uifactory.addDropdownSingleselect("launchunit", null, ruleCont, unitKeys, unitValues, null);
 		unitEl.setDomReplacementWrapperRequired(false);
 		boolean selected = false;
diff --git a/src/test/java/org/olat/course/nodes/gta/rule/GTAReminderRuleTest.java b/src/test/java/org/olat/course/nodes/gta/rule/GTAReminderRuleTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..27de702b6b9fef27b7b3ffe6d32ae5af22075549
--- /dev/null
+++ b/src/test/java/org/olat/course/nodes/gta/rule/GTAReminderRuleTest.java
@@ -0,0 +1,308 @@
+/**
+ * <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.gta.rule;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.olat.basesecurity.GroupRoles;
+import org.olat.core.commons.persistence.DB;
+import org.olat.core.id.Identity;
+import org.olat.course.nodes.GTACourseNode;
+import org.olat.course.nodes.gta.AssignmentResponse;
+import org.olat.course.nodes.gta.GTAType;
+import org.olat.course.nodes.gta.TaskList;
+import org.olat.course.nodes.gta.manager.GTAManagerImpl;
+import org.olat.group.BusinessGroup;
+import org.olat.group.manager.BusinessGroupDAO;
+import org.olat.group.manager.BusinessGroupRelationDAO;
+import org.olat.modules.reminder.model.ReminderRuleImpl;
+import org.olat.modules.reminder.rule.LaunchUnit;
+import org.olat.modules.vitero.model.GroupRole;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.manager.RepositoryEntryRelationDAO;
+import org.olat.test.JunitTestHelper;
+import org.olat.test.OlatTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * 
+ * Initial date: 10.04.2015<br>
+ * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com
+ *
+ */
+public class GTAReminderRuleTest extends OlatTestCase {
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private GTAManagerImpl gtaManager;
+	@Autowired
+	private BusinessGroupDAO businessGroupDao;
+	@Autowired
+	private BusinessGroupRelationDAO businessGroupRelationDao;
+	@Autowired
+	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
+	
+
+	@Autowired
+	private AssignTaskRuleSPI assignTaskRuleSPI;
+	@Autowired
+	private SubmissionTaskRuleSPI submissionTaskRuleSPI;
+	
+	@Test
+	public void assignTask_individual() {
+		//prepare a course with a volatile task
+		Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-1");
+		Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-2");
+		RepositoryEntry re = JunitTestHelper.createAndPersistRepositoryEntry("", false);
+		repositoryEntryRelationDao.addRole(participant1, re, GroupRoles.participant.name());
+		repositoryEntryRelationDao.addRole(participant2, re, GroupRoles.participant.name());
+		dbInstance.commit();
+		
+		GTACourseNode node = new GTACourseNode();
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name());
+		
+		Calendar cal = Calendar.getInstance();
+		cal.add(2, Calendar.MONTH);
+		node.getModuleConfiguration().setDateValue(GTACourseNode.GTASK_ASSIGNMENT_DEADLINE, cal.getTime());
+		TaskList tasks = gtaManager.createIfNotExists(re, node);
+		File taskFile = new File("solo.txt");
+		Assert.assertNotNull(tasks);
+		dbInstance.commit();
+		
+		//select a task
+		AssignmentResponse response = gtaManager.selectTask(participant1, tasks, node, taskFile);
+		dbInstance.commitAndCloseSession();
+		Assert.assertEquals(AssignmentResponse.Status.ok, response.getStatus());
+		
+		//only remind participant 2
+		List<Identity> toRemind = assignTaskRuleSPI.getPeopleToRemind(re, node);
+		Assert.assertEquals(1, toRemind.size());
+		Assert.assertTrue(toRemind.contains(participant2));
+		
+
+		{ // check before 30 days 
+			ReminderRuleImpl rule = getAssignedTaskRules(30, LaunchUnit.day);
+			List<Identity> all = assignTaskRuleSPI.evaluateRule(re, node, rule);
+			
+			Assert.assertEquals(0, all.size());
+		}
+		
+		{ // check before 5 weeks 
+			ReminderRuleImpl rule = getAssignedTaskRules(5, LaunchUnit.week);
+			List<Identity> all = assignTaskRuleSPI.evaluateRule(re, node, rule);
+			
+			Assert.assertEquals(0, all.size());
+		}
+		
+		{ // check before 1 month 
+			ReminderRuleImpl rule = getAssignedTaskRules(1, LaunchUnit.month);
+			List<Identity> all = assignTaskRuleSPI.evaluateRule(re, node, rule);
+			
+			Assert.assertEquals(0, all.size());
+		}
+		
+		{ // check before  90 days 
+			ReminderRuleImpl rule = getAssignedTaskRules(90, LaunchUnit.day);
+			List<Identity> all = assignTaskRuleSPI.evaluateRule(re, node, rule);
+
+			Assert.assertEquals(1, all.size());
+			Assert.assertTrue(toRemind.contains(participant2));
+		}
+		
+		{ // check before  12 weeks 
+			ReminderRuleImpl rule = getAssignedTaskRules(12, LaunchUnit.week);
+			List<Identity> all = assignTaskRuleSPI.evaluateRule(re, node, rule);
+
+			Assert.assertEquals(1, all.size());
+			Assert.assertTrue(toRemind.contains(participant2));
+		}
+		
+		{ // check before  3 month 
+			ReminderRuleImpl rule = getAssignedTaskRules(3, LaunchUnit.month);
+			List<Identity> all = assignTaskRuleSPI.evaluateRule(re, node, rule);
+
+			Assert.assertEquals(1, all.size());
+			Assert.assertTrue(toRemind.contains(participant2));
+		}
+		
+		{ // check before 1 year 
+			ReminderRuleImpl rule = getAssignedTaskRules(1, LaunchUnit.year);
+			List<Identity> all = assignTaskRuleSPI.evaluateRule(re, node, rule);
+			
+			Assert.assertEquals(1, all.size());
+			Assert.assertTrue(toRemind.contains(participant2));
+		}
+	}
+	
+	private ReminderRuleImpl getAssignedTaskRules(int amount, LaunchUnit unit) {
+		ReminderRuleImpl rule = new ReminderRuleImpl();
+		rule.setType(AssignTaskRuleSPI.class.getSimpleName());
+		rule.setOperator("<");
+		rule.setRightOperand(Integer.toString(amount));
+		rule.setRightUnit(unit.name());
+		return rule;
+	}
+	
+	@Test
+	public void assignTask_businessGroup() {
+		//prepare
+		Identity coach = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-2");
+		Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-3");
+		Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-4");
+		Identity participant3 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-5");
+		Identity participant4 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-6");
+		
+		BusinessGroup businessGroup1 = businessGroupDao.createAndPersist(coach, "gdao", "gdao-desc", -1, -1, false, false, false, false, false);
+		BusinessGroup businessGroup2 = businessGroupDao.createAndPersist(coach, "gdao", "gdao-desc", -1, -1, false, false, false, false, false);
+		
+		businessGroupRelationDao.addRole(participant1, businessGroup1, GroupRole.participant.name());
+		businessGroupRelationDao.addRole(participant2, businessGroup1, GroupRole.participant.name());
+		businessGroupRelationDao.addRole(participant3, businessGroup2, GroupRole.participant.name());
+		businessGroupRelationDao.addRole(participant4, businessGroup2, GroupRole.participant.name());
+		dbInstance.commit();
+		
+		RepositoryEntry re = JunitTestHelper.createAndPersistRepositoryEntry("", false);
+		businessGroupRelationDao.addRelationToResource(businessGroup1, re);
+		businessGroupRelationDao.addRelationToResource(businessGroup2, re);
+		
+		GTACourseNode node = new GTACourseNode();
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.group.name());
+		List<Long> groupKeys = new ArrayList<>(2);
+		groupKeys.add(businessGroup1.getKey());
+		groupKeys.add(businessGroup2.getKey());
+		node.getModuleConfiguration().setList(GTACourseNode.GTASK_GROUPS, groupKeys);
+		TaskList tasks = gtaManager.createIfNotExists(re, node);
+		File taskFile = new File("bg.txt");
+		Assert.assertNotNull(tasks);
+		dbInstance.commit();
+		
+		// group 1 select a task
+		AssignmentResponse response = gtaManager.selectTask(businessGroup1, tasks, node, taskFile);
+		dbInstance.commitAndCloseSession();
+		Assert.assertEquals(AssignmentResponse.Status.ok, response.getStatus());
+		
+		// only remind group 2
+		List<Identity> toRemind = assignTaskRuleSPI.getPeopleToRemind(re, node);
+		Assert.assertEquals(2, toRemind.size());
+		Assert.assertTrue(toRemind.contains(participant3));
+		Assert.assertTrue(toRemind.contains(participant4));
+	}
+	
+	@Test
+	public void submitTask_individual() {
+		//prepare a course with a volatile task
+		Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-1");
+		Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("gta-user-2");
+		RepositoryEntry re = JunitTestHelper.createAndPersistRepositoryEntry("", false);
+		repositoryEntryRelationDao.addRole(participant1, re, GroupRoles.participant.name());
+		repositoryEntryRelationDao.addRole(participant2, re, GroupRoles.participant.name());
+		dbInstance.commit();
+		
+		GTACourseNode node = new GTACourseNode();
+		node.getModuleConfiguration().setStringValue(GTACourseNode.GTASK_TYPE, GTAType.individual.name());
+		
+		Calendar cal = Calendar.getInstance();
+		cal.add(2, Calendar.MONTH);
+		node.getModuleConfiguration().setDateValue(GTACourseNode.GTASK_SUBMIT_DEADLINE, cal.getTime());
+		TaskList tasks = gtaManager.createIfNotExists(re, node);
+		File taskFile = new File("solo.txt");
+		Assert.assertNotNull(tasks);
+		dbInstance.commit();
+		
+		//select a task
+		AssignmentResponse response = gtaManager.selectTask(participant1, tasks, node, taskFile);
+		dbInstance.commitAndCloseSession();
+		Assert.assertEquals(AssignmentResponse.Status.ok, response.getStatus());
+		
+		//only remind participant 2
+		List<Identity> toRemind = submissionTaskRuleSPI.getPeopleToRemind(re, node);
+		Assert.assertEquals(1, toRemind.size());
+		Assert.assertTrue(toRemind.contains(participant2));
+		
+
+		{ // check before 30 days 
+			ReminderRuleImpl rule = getSubmitTaskRules(30, LaunchUnit.day);
+			List<Identity> all = submissionTaskRuleSPI.evaluateRule(re, node, rule);
+			
+			Assert.assertEquals(0, all.size());
+		}
+		
+		{ // check before 5 weeks 
+			ReminderRuleImpl rule = getSubmitTaskRules(5, LaunchUnit.week);
+			List<Identity> all = submissionTaskRuleSPI.evaluateRule(re, node, rule);
+			
+			Assert.assertEquals(0, all.size());
+		}
+		
+		{ // check before 1 month 
+			ReminderRuleImpl rule = getSubmitTaskRules(1, LaunchUnit.month);
+			List<Identity> all = submissionTaskRuleSPI.evaluateRule(re, node, rule);
+			
+			Assert.assertEquals(0, all.size());
+		}
+		
+		{ // check before  90 days 
+			ReminderRuleImpl rule = getSubmitTaskRules(90, LaunchUnit.day);
+			List<Identity> all = submissionTaskRuleSPI.evaluateRule(re, node, rule);
+
+			Assert.assertEquals(1, all.size());
+			Assert.assertTrue(toRemind.contains(participant2));
+		}
+		
+		{ // check before  12 weeks 
+			ReminderRuleImpl rule = getSubmitTaskRules(12, LaunchUnit.week);
+			List<Identity> all = submissionTaskRuleSPI.evaluateRule(re, node, rule);
+
+			Assert.assertEquals(1, all.size());
+			Assert.assertTrue(toRemind.contains(participant2));
+		}
+		
+		{ // check before  3 month 
+			ReminderRuleImpl rule = getSubmitTaskRules(3, LaunchUnit.month);
+			List<Identity> all = submissionTaskRuleSPI.evaluateRule(re, node, rule);
+
+			Assert.assertEquals(1, all.size());
+			Assert.assertTrue(toRemind.contains(participant2));
+		}
+		
+		{ // check before 1 year 
+			ReminderRuleImpl rule = getSubmitTaskRules(1, LaunchUnit.year);
+			List<Identity> all = submissionTaskRuleSPI.evaluateRule(re, node, rule);
+			
+			Assert.assertEquals(1, all.size());
+			Assert.assertTrue(toRemind.contains(participant2));
+		}
+	}
+	
+	private ReminderRuleImpl getSubmitTaskRules(int amount, LaunchUnit unit) {
+		ReminderRuleImpl rule = new ReminderRuleImpl();
+		rule.setType(SubmissionTaskRuleSPI.class.getSimpleName());
+		rule.setOperator("<");
+		rule.setRightOperand(Integer.toString(amount));
+		rule.setRightUnit(unit.name());
+		return rule;
+	}
+}
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index a1e9b9d34f8aafe89dc76c69045bf10f2e4de9ef..22ba3c1efe2b803bddf8251d919ffe2caae20f74 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -125,6 +125,7 @@ import org.junit.runners.Suite;
 	org.olat.course.nodes.en.EnrollmentManagerSerialTest.class,
 	org.olat.course.nodes.en.EnrollmentManagerConcurrentTest.class,
 	org.olat.course.nodes.gta.manager.GTAManagerTest.class,
+	org.olat.course.nodes.gta.rule.GTAReminderRuleTest.class,
 	org.olat.course.assessment.AssessmentManagerTest.class,
 	org.olat.course.assessment.manager.UserCourseInformationsManagerTest.class,
 	org.olat.course.assessment.manager.AssessmentModeManagerTest.class,