diff --git a/src/main/java/org/olat/admin/user/delete/ConfirmDeleteUserController.java b/src/main/java/org/olat/admin/user/delete/ConfirmDeleteUserController.java
index 4e6130bee4fb56a866accfeacbe5ebfd940aee20..33bffffcc4daf39de5df26155623ebc5b6e714e0 100644
--- a/src/main/java/org/olat/admin/user/delete/ConfirmDeleteUserController.java
+++ b/src/main/java/org/olat/admin/user/delete/ConfirmDeleteUserController.java
@@ -78,11 +78,13 @@ public class ConfirmDeleteUserController extends FormBasicController {
 			
 			String[] confirmValues = new String[] { translate("readyToDelete.delete.confirm.check") };
 			confirmEl = uifactory.addCheckboxesHorizontal("readyToDelete.delete.confirm.check.label", layoutCont, confirmKeys, confirmValues);
+			confirmEl.setElementCssClass("o_sel_confirm_delete_user");
 			
 			FormLayoutContainer buttonsCont = FormLayoutContainer.createButtonLayout("buttons", getTranslator());
 			layoutCont.add(buttonsCont);
 			uifactory.addFormCancelButton("cancel", buttonsCont, ureq, getWindowControl());
 			deleteButton = uifactory.addFormLink("delete", buttonsCont, Link.BUTTON);
+			deleteButton.setElementCssClass("o_sel_delete_user");
 		}
 	}
 	
diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/CommentAndRatingService.java b/src/main/java/org/olat/core/commons/services/commentAndRating/CommentAndRatingService.java
index 1d25a38199d7500ee78b3597832d2cbcbb3df126..aa058036e44f9ced6a007dc812374c362ac12b59 100644
--- a/src/main/java/org/olat/core/commons/services/commentAndRating/CommentAndRatingService.java
+++ b/src/main/java/org/olat/core/commons/services/commentAndRating/CommentAndRatingService.java
@@ -117,14 +117,6 @@ public interface CommentAndRatingService {
 	 *         in the meantime and could not be updated at all.
 	 */
 	public UserRating updateRating(UserRating rating, int newRatingValue);
-
-	/**
-	 * Delete a rating
-	 * 
-	 * @param rating
-	 * @param int number of deleted ratings
-	 */
-	public abstract int deleteRating(UserRating rating);
 	
 	/**
 	 * Return the most rated resources
diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceImpl.java b/src/main/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceImpl.java
index 8a12a5ab300b2b2301053d16809695177c481c28..7632019edb79fb6b949cf373faa08791e4526944 100644
--- a/src/main/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceImpl.java
+++ b/src/main/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceImpl.java
@@ -20,6 +20,7 @@
 
 package org.olat.core.commons.services.commentAndRating.manager;
 
+import java.io.File;
 import java.util.List;
 
 import org.olat.core.commons.services.commentAndRating.CommentAndRatingService;
@@ -31,6 +32,9 @@ import org.olat.core.commons.services.notifications.NotificationsManager;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
 import org.olat.core.logging.AssertException;
+import org.olat.core.logging.OLog;
+import org.olat.core.logging.Tracing;
+import org.olat.user.UserDataDeletable;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
@@ -46,7 +50,9 @@ import org.springframework.stereotype.Service;
  * @author gnaegi
  */
 @Service
-public class CommentAndRatingServiceImpl implements CommentAndRatingService {
+public class CommentAndRatingServiceImpl implements CommentAndRatingService, UserDataDeletable {
+	
+	private static final OLog log = Tracing.createLoggerFor(CommentAndRatingServiceImpl.class);
 
 	@Autowired
 	private UserRatingsDAO userRatingsDao;
@@ -58,7 +64,7 @@ public class CommentAndRatingServiceImpl implements CommentAndRatingService {
 
 	@Override
 	public Long countRatings(OLATResourceable ores, String resSubPath) {
-		return new Long(userRatingsDao.countRatings(ores, resSubPath));
+		return Long.valueOf(userRatingsDao.countRatings(ores, resSubPath));
 	}
 
 	@Override
@@ -96,11 +102,6 @@ public class CommentAndRatingServiceImpl implements CommentAndRatingService {
 		return userRatingsDao.updateRating(rating, newRatingValue);
 	}
 
-	@Override
-	public int deleteRating(UserRating rating) {
-		return userRatingsDao.deleteRating(rating);
-	}
-
 	@Override
 	public List<OLATResourceableRating> getMostRatedResourceables(OLATResourceable ores, int maxResults) {
 		return userRatingsDao.getMostRatedResourceables(ores, maxResults);
@@ -153,9 +154,6 @@ public class CommentAndRatingServiceImpl implements CommentAndRatingService {
 		return userCommentsDao.deleteComment(comment, deleteReplies);
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.CommentAndRatingService#deleteAll()
-	 */
 	@Override
 	public int deleteAll(OLATResourceable ores, String resSubPath) {
 		if (ores == null) {
@@ -166,10 +164,6 @@ public class CommentAndRatingServiceImpl implements CommentAndRatingService {
 		return delCount;
 	}
 
-	/**
-	 *
-	 * @see org.olat.core.commons.services.commentAndRating.CommentAndRatingService#deleteAllIgnoringSubPath()
-	 */
 	@Override
 	public int deleteAllIgnoringSubPath(OLATResourceable ores) {
 		if (ores == null) {
@@ -180,6 +174,14 @@ public class CommentAndRatingServiceImpl implements CommentAndRatingService {
 		return delCount;
 	}
 
+	@Override
+	public void deleteUserData(Identity identity, String newDeletedUserName, File archivePath) {
+		int rows = userRatingsDao.deleteRatings(identity);
+		log.audit(rows + " rating deleted");
+		int comments = userCommentsDao.deleteAllComments(identity);
+		log.audit(comments + " rating erased");
+	}
+
 	private void markPublisherNews(UserComment comment) {
 		if (comment == null) return;
 
diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/manager/UserCommentsDAO.java b/src/main/java/org/olat/core/commons/services/commentAndRating/manager/UserCommentsDAO.java
index 601e3ab27a707c08e146ffbe3e3b10d40f4fc715..80d50d90d91b29b555764c6d4851ded622f3a3a6 100644
--- a/src/main/java/org/olat/core/commons/services/commentAndRating/manager/UserCommentsDAO.java
+++ b/src/main/java/org/olat/core/commons/services/commentAndRating/manager/UserCommentsDAO.java
@@ -28,6 +28,7 @@ import java.util.Set;
 import javax.persistence.EntityManager;
 import javax.persistence.TypedQuery;
 
+import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.persistence.DBFactory;
 import org.olat.core.commons.services.commentAndRating.CommentAndRatingLoggingAction;
@@ -38,8 +39,6 @@ import org.olat.core.commons.services.commentAndRating.model.UserCommentsCount;
 import org.olat.core.commons.services.commentAndRating.model.UserCommentsCountImpl;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
-import org.olat.core.logging.OLog;
-import org.olat.core.logging.Tracing;
 import org.olat.core.logging.activity.CoreLoggingResourceable;
 import org.olat.core.logging.activity.OlatResourceableType;
 import org.olat.core.logging.activity.ThreadLocalUserActivityLogger;
@@ -55,10 +54,7 @@ import org.springframework.stereotype.Service;
  */
 @Service("userCommentsDAO")
 public class UserCommentsDAO {
-	
-	private static final OLog log = Tracing.createLoggerFor(UserCommentsDAO.class);
-	
-	
+
 	@Autowired
 	private DB dbInstance;
 	
@@ -72,7 +68,7 @@ public class UserCommentsDAO {
 	public UserComment createComment(Identity creator, OLATResourceable ores, String resSubPath, String commentText) {
 		UserComment comment = new UserCommentImpl(ores, resSubPath, creator, commentText);
 		dbInstance.getCurrentEntityManager().persist(comment);
-		updateDelegateRatings(ores, resSubPath);
+		updateDelegateRatings(ores, resSubPath, true);
 		
 		// do Logging
 		ThreadLocalUserActivityLogger.log(CommentAndRatingLoggingAction.COMMENT_CREATED, getClass(),
@@ -81,19 +77,12 @@ public class UserCommentsDAO {
 	}
 
 	public UserComment reloadComment(UserComment comment) {
-		try {
-			String q = "select comment from usercomment as comment where comment.key=:commentKey";
-			List<UserComment> comments = dbInstance.getCurrentEntityManager()
-			 		.createQuery(q, UserComment.class)
-			 		.setParameter("commentKey", comment.getKey())
-			 		.getResultList();
-			return comments.isEmpty() ? null : comments.get(0);
-		} catch (Exception e) {
-			// Huh, most likely the given object does not exist anymore on the
-			// db, probably deleted by someone else
-			log.warn("Tried to reload a user comment but got an exception. Probably deleted in the meantime", e);
-			return null;
-		}		
+		String q = "select comment from usercomment as comment where comment.key=:commentKey";
+		List<UserComment> comments = dbInstance.getCurrentEntityManager()
+		 		.createQuery(q, UserComment.class)
+		 		.setParameter("commentKey", comment.getKey())
+		 		.getResultList();
+		return comments.isEmpty() ? null : comments.get(0);
 	}
 	
 	public UserComment replyTo(UserComment originalComment, Identity creator, String replyCommentText) {
@@ -107,7 +96,7 @@ public class UserCommentsDAO {
 		UserCommentImpl reply = new UserCommentImpl(ores, originalComment.getResSubPath(), creator, replyCommentText);
 		reply.setParent(originalComment);
 		dbInstance.getCurrentEntityManager().persist(reply);
-		updateDelegateRatings(ores, originalComment.getResSubPath());
+		updateDelegateRatings(ores, originalComment.getResSubPath(), true);
 		return reply;
 	}
 
@@ -172,7 +161,7 @@ public class UserCommentsDAO {
 		dbInstance.getCurrentEntityManager().remove(comment);
 		// do Logging
 		OLATResourceable ores = OresHelper.createOLATResourceableInstance(comment.getResName(), comment.getResId());
-		updateDelegateRatings(ores, comment.getResSubPath());
+		updateDelegateRatings(ores, comment.getResSubPath(), true);
 		ThreadLocalUserActivityLogger.log(CommentAndRatingLoggingAction.COMMENT_DELETED, getClass(),
 				CoreLoggingResourceable.wrap(ores, OlatResourceableType.feedItem));
 		return counter+1;
@@ -195,8 +184,8 @@ public class UserCommentsDAO {
 				.setParameter("resId", ores.getResourceableId())
 				.getResultList();
 		
-		Set<String> countMap = new HashSet<String>();
-		List<UserCommentsCount> countList = new ArrayList<UserCommentsCount>();
+		Set<String> countMap = new HashSet<>();
+		List<UserCommentsCount> countList = new ArrayList<>();
 		for(Object[] count:counts) {
 			Object subPath = count[0] == null ? "" : count[0];
 			if(!countMap.contains(subPath)) {
@@ -223,9 +212,50 @@ public class UserCommentsDAO {
 			.getSingleResult().longValue();
 	}
 	
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.UserCommentsManager#deleteAllComments()
-	 */
+	public int deleteAllComments(IdentityRef identity) {
+		Set<Long> commentWithReplyKeys = getCommentKeysWithReply(identity);
+		
+		String query = "select comment.key from usercomment comment where comment.creator.key=:creatorKey";
+		List<Long> commentKeys = dbInstance.getCurrentEntityManager()
+				.createQuery(query, Long.class)
+				.setParameter("creatorKey", identity.getKey())
+				.getResultList();
+
+		int count = 0;
+		for(Long commentKey:commentKeys) {
+			UserComment comment = dbInstance.getCurrentEntityManager()
+					.getReference(UserCommentImpl.class, commentKey);
+			if(commentWithReplyKeys.contains(commentKey)) {
+				comment.setComment("User has been deleted");
+				dbInstance.getCurrentEntityManager().merge(comment);
+			} else {
+				dbInstance.getCurrentEntityManager().remove(comment);
+			}
+			
+			if(count++ % 25 == 0) {
+				dbInstance.commitAndCloseSession();
+			} else {
+				dbInstance.commit();
+			}
+
+			OLATResourceable ores = OresHelper.createOLATResourceableInstance(comment.getResName(), comment.getResId());
+			updateDelegateRatings(ores, comment.getResSubPath(), false);
+		}
+		return commentKeys.size();
+	}
+	
+	private Set<Long> getCommentKeysWithReply(IdentityRef identity) {
+		StringBuilder sb = new StringBuilder();
+		sb.append("select comment.key from usercomment as comment")
+		  .append(" inner join usercomment as reply on (comment.key=reply.parent.key)")
+		  .append(" where comment.creator.key=:creatorKey");
+		List<Long> commentWithReplyKeyList = dbInstance.getCurrentEntityManager()
+				.createQuery(sb.toString(), Long.class)
+				.setParameter("creatorKey", identity.getKey())
+				.getResultList();
+		return new HashSet<>(commentWithReplyKeyList);
+	}
+	
 	public int deleteAllComments(OLATResourceable ores, String resSubPath) {
 		EntityManager em = dbInstance.getCurrentEntityManager();
 		// special query when sub path is null
@@ -258,7 +288,7 @@ public class UserCommentsDAO {
 				em.remove(comment);
 			}
 		}
-		updateDelegateRatings(ores, resSubPath);
+		updateDelegateRatings(ores, resSubPath, false);
 		return comments == null ? 0 : comments.size();
 	}
 
@@ -280,11 +310,11 @@ public class UserCommentsDAO {
 		for(UserCommentImpl comment:comments) {
 			em.remove(comment);
 		}
-		updateDelegateRatings(ores, null);
+		updateDelegateRatings(ores, null, false);
 		return comments.size();
 	}
 	
-	private void updateDelegateRatings(OLATResourceable ores, String resSubPath) {
+	private void updateDelegateRatings(OLATResourceable ores, String resSubPath, boolean newRating) {
 		if(delegates == null || delegates.isEmpty()) return;
 
 		for(UserCommentsDelegate delegate:delegates) {
@@ -308,7 +338,8 @@ public class UserCommentsDAO {
 		
 				Number count = query.getSingleResult();
 				if(count == null) {
-					delegate.update(ores, resSubPath, 1);
+					int val = newRating ? 1 : 0;
+					delegate.update(ores, resSubPath, val);
 				} else {
 					delegate.update(ores, resSubPath, count.intValue());
 				}
diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/manager/UserRatingsDAO.java b/src/main/java/org/olat/core/commons/services/commentAndRating/manager/UserRatingsDAO.java
index 9d679398739cc7133140f3b87269caec8e8c5ed5..eb265ee4e36f79705037db35c962486430c25bb8 100644
--- a/src/main/java/org/olat/core/commons/services/commentAndRating/manager/UserRatingsDAO.java
+++ b/src/main/java/org/olat/core/commons/services/commentAndRating/manager/UserRatingsDAO.java
@@ -25,6 +25,7 @@ import java.util.List;
 
 import javax.persistence.TypedQuery;
 
+import org.olat.basesecurity.IdentityRef;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.services.commentAndRating.UserRatingsDelegate;
 import org.olat.core.commons.services.commentAndRating.model.OLATResourceableRating;
@@ -32,8 +33,6 @@ import org.olat.core.commons.services.commentAndRating.model.UserRating;
 import org.olat.core.commons.services.commentAndRating.model.UserRatingImpl;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
-import org.olat.core.logging.OLog;
-import org.olat.core.logging.Tracing;
 import org.olat.core.util.resource.OresHelper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -46,9 +45,7 @@ import org.springframework.stereotype.Service;
  */
 @Service("userRatingsDAO")
 public class UserRatingsDAO {
-	
-	private static final OLog log = Tracing.createLoggerFor(UserRatingsDAO.class);
-	
+
 	@Autowired
 	private DB dbInstance;
 	
@@ -129,8 +126,7 @@ public class UserRatingsDAO {
 			query.setMaxResults(maxResults);
 		}
 
-		List<OLATResourceableRating> mostRated = query.getResultList();
-		return mostRated;
+		return query.getResultList();
 	}
 	
 	public int countRatings(OLATResourceable ores, String resSubPath) {
@@ -227,14 +223,12 @@ public class UserRatingsDAO {
 	}
 
 	public UserRating reloadRating(UserRating rating) {
-		try {
-			return (UserRating)dbInstance.loadObject(rating);		
-		} catch (Exception e) {
-			// Huh, most likely the given object does not exist anymore on the
-			// db, probably deleted by someone else
-			log.warn("Tried to reload a user rating but got an exception. Probably deleted in the meantime", e);
-			return null;
-		}
+		String query = "select r from userrating as r where r.key=:ratingKey";
+		List<UserRating> ratings = dbInstance.getCurrentEntityManager()
+				.createQuery(query, UserRating.class)
+				.setParameter("ratingKey", rating.getKey())
+				.getResultList();
+		return ratings != null && !ratings.isEmpty() ? ratings.get(0) : null;
 	}
 	
 	private void updateDelegateRatings(UserRating rating) {
@@ -273,24 +267,63 @@ public class UserRatingsDAO {
 				} else {
 					long numOfRatings = ((Number)stats[0]).longValue();
 					long sumOfRatings = ((Number)stats[1]).longValue();
-					double rate = (sumOfRatings + rating.getRating().intValue()) / (numOfRatings + 1);
+					double rate = (sumOfRatings + rating.getRating().intValue()) / (numOfRatings + 1.0d);
 					delegate.update(ores, rating.getResSubPath(), rate, numOfRatings + 1);
 				}
 			}
 		}
 	}
-	
-	public int deleteRating(UserRating rating) {
-		// First reload parent from cache to prevent stale object or cache issues
-		UserRating ratingRef = dbInstance.getCurrentEntityManager().getReference(UserRatingImpl.class, rating.getKey());
-		if (ratingRef == null) {
-			// Original rating has been deleted in the meantime. Don't delete it again.
-			return 0;
+
+	public int deleteRatings(IdentityRef identity) {
+		String query = "select r from userrating as r where r.creator.key=:creatorKey";
+		List<UserRating> ratings = dbInstance.getCurrentEntityManager()
+				.createQuery(query, UserRating.class)
+				.setParameter("creatorKey", identity.getKey())
+				.getResultList();
+
+		for(UserRating rating:ratings) {
+			dbInstance.getCurrentEntityManager().remove(rating);
+			dbInstance.commit();
+			OLATResourceable ores = OresHelper.createOLATResourceableInstance(rating.getResName(), rating.getResId());
+			recalculateDelegateRatings(ores, rating.getResSubPath());
 		}
-		// Delete this rating and finish
-		dbInstance.getCurrentEntityManager().remove(ratingRef);
-		return 1;
+		return ratings.size();
+	}
+	
+	private void recalculateDelegateRatings(OLATResourceable ores, String resSubPath) {
+		if(delegates == null || delegates.isEmpty()) return;
+
+		for(UserRatingsDelegate delegate:delegates) {
+			if(delegate.accept(ores, resSubPath)) {
+				StringBuilder sb = new StringBuilder();
+				sb.append("select count(rating.key), sum(rating.rating) from userrating as rating")
+				  .append(" where rating.resName=:resname and rating.resId=:resId");
+				if(resSubPath == null) {
+					sb.append(" and rating.resSubPath is null");
+				} else {
+					sb.append(" and rating.resSubPath=:resSubPath");
+				}
+	
+				TypedQuery<Object[]> query = dbInstance.getCurrentEntityManager()
+					.createQuery(sb.toString(), Object[].class)
+				     .setParameter("resname", ores.getResourceableTypeName())
+				     .setParameter("resId", ores.getResourceableId());
 
+				if(resSubPath != null) {
+					query.setParameter("resSubPath", resSubPath);
+				}
+		
+				Object[] stats = query.getSingleResult();
+				if(stats == null || stats[0] == null || stats[1] == null) {
+					delegate.update(ores, resSubPath, 0.0d, 0l);
+				} else {
+					long numOfRatings = ((Number)stats[0]).longValue();
+					long sumOfRatings = ((Number)stats[1]).longValue();
+					double rate = sumOfRatings / (double)numOfRatings;
+					delegate.update(ores, resSubPath, rate, numOfRatings);
+				}
+			}
+		}
 	}
 
 	public int deleteAllRatings(OLATResourceable ores, String resSubPath) {
diff --git a/src/main/java/org/olat/core/commons/services/commentAndRating/model/UserCommentImpl.java b/src/main/java/org/olat/core/commons/services/commentAndRating/model/UserCommentImpl.java
index 247b0ca07852ca2d1448cd6f123c51c6035f5a65..c48063e1ca210659aa33759f672bc260fa74f710 100644
--- a/src/main/java/org/olat/core/commons/services/commentAndRating/model/UserCommentImpl.java
+++ b/src/main/java/org/olat/core/commons/services/commentAndRating/model/UserCommentImpl.java
@@ -114,7 +114,8 @@ public class UserCommentImpl implements Persistable, CreateInfo, UserComment {
 		this.resId = ores.getResourceableId();
 		this.resSubPath = subpath;
 	}
-	
+
+	@Override
 	public Long getKey() {
 		return key;
 	}
@@ -123,53 +124,36 @@ public class UserCommentImpl implements Persistable, CreateInfo, UserComment {
 		this.key = key;
 	}
 
+	@Override
 	public Date getCreationDate() {
 		return creationDate;
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#getCreator()
-	 */
 	@Override
 	public Identity getCreator() {
 		return creator;
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#getComment()
-	 */
 	@Override
 	public String getComment() {
 		return comment;
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#getResId()
-	 */
 	@Override
 	public Long getResId() {
 		return this.resId;
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#getResName()
-	 */
 	@Override
 	public String getResName() {
 		return this.resName;
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#getResSubPath()
-	 */
 	@Override
 	public String getResSubPath() {
 		return this.resSubPath;
 	}
-	
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#getParent()
-	 */
+
 	@Override
 	public UserComment getParent() {
 		return parent;
@@ -199,23 +183,17 @@ public class UserCommentImpl implements Persistable, CreateInfo, UserComment {
 		this.resId = resId;
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#setCreator(org.olat.core.id.Identity)
-	 */
+	@Override
 	public void setCreator(Identity creator) {
 		this.creator = creator;
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#setComment(java.lang.String)
-	 */
+	@Override
 	public void setComment(String commentText) {
 		this.comment = commentText;
 	}
 
-	/**
-	 * @see org.olat.core.commons.services.commentAndRating.model.UserComment#setParent(org.olat.core.commons.services.commentAndRating.model.UserComment)
-	 */
+	@Override
 	public void setParent(UserComment parentComment) {
 		this.parent = parentComment;
 	}
diff --git a/src/test/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceImplTest.java b/src/test/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceTest.java
similarity index 99%
rename from src/test/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceImplTest.java
rename to src/test/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceTest.java
index 601b6d56787f09ce2695cd28d2164ae997b678dd..0403c989bd825cd2f010af10b41fc6ae59f97078 100644
--- a/src/test/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceImplTest.java
+++ b/src/test/java/org/olat/core/commons/services/commentAndRating/manager/CommentAndRatingServiceTest.java
@@ -39,7 +39,7 @@ import org.olat.resource.OLATResource;
  * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
  *
  */
-public class CommentAndRatingServiceImplTest {
+public class CommentAndRatingServiceTest {
 
 	private static final String RESOURCEABLE_TYPE_NAME = "resurcable type name";
 	private static final Long RESOURCABLE_ID = 5L;
diff --git a/src/test/java/org/olat/core/commons/services/commentAndRating/manager/UserCommentsDAOTest.java b/src/test/java/org/olat/core/commons/services/commentAndRating/manager/UserCommentsDAOTest.java
index e8bafd9f3a8c0fcd1e274aaa25a09b983588033d..fcaa72e9406d64a9ee4990feed2afcb8d43e8a0d 100644
--- a/src/test/java/org/olat/core/commons/services/commentAndRating/manager/UserCommentsDAOTest.java
+++ b/src/test/java/org/olat/core/commons/services/commentAndRating/manager/UserCommentsDAOTest.java
@@ -22,14 +22,17 @@ package org.olat.core.commons.services.commentAndRating.manager;
 import static org.junit.Assert.assertEquals;
 
 import java.util.List;
-import java.util.UUID;
 
 import org.junit.Assert;
 import org.junit.Test;
-import org.olat.core.commons.services.commentAndRating.manager.UserCommentsDAO;
+import org.olat.admin.user.delete.service.UserDeletionManager;
+import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.services.commentAndRating.model.UserComment;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryService;
+import org.olat.repository.model.RepositoryEntryStatistics;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,8 +48,14 @@ import org.springframework.beans.factory.annotation.Autowired;
  */
 public class UserCommentsDAOTest extends OlatTestCase {
 	
+	@Autowired
+	private DB dbInstance;
 	@Autowired
 	private UserCommentsDAO userCommentsDao;
+	@Autowired
+	private RepositoryService repositoryService;
+	@Autowired
+	private UserDeletionManager userDeletionManager;
 
 	
 	@Test
@@ -58,8 +67,8 @@ public class UserCommentsDAOTest extends OlatTestCase {
 	public void testCRUDComment() {
 		//init 
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
-		Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-1-" + UUID.randomUUID().toString());
-		Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-2-" + UUID.randomUUID().toString());
+		Identity ident1 = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-1");
+		Identity ident2 = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-2");
 				
 
 		//check if there is any comments
@@ -135,4 +144,49 @@ public class UserCommentsDAOTest extends OlatTestCase {
 		assertEquals(0, userCommentsDao.countComments(ores, null));
 		assertEquals(0, userCommentsDao.countComments(ores, "blubli"));
 	}
+	
+	@Test
+	public void deleteUser() {
+		Identity identToDelete = JunitTestHelper.createAndPersistIdentityAsRndUser("ucom-del");
+		Identity ident = JunitTestHelper.createAndPersistIdentityAsRndUser("ucom-ndel");
+		RepositoryEntry course = JunitTestHelper.deployBasicCourse(ident);
+
+		// add comments
+		UserComment comment_del_1 = userCommentsDao.createComment(identToDelete, course, null, "Hello");
+		UserComment comment_ndel_2 = userCommentsDao.createComment(ident, course, null, "Hello ");
+		// add comments and replies
+		UserComment comment_ndel_3 = userCommentsDao.createComment(ident, course, null, "Reply");
+		UserComment comment_del_4 = userCommentsDao.replyTo(comment_ndel_3, identToDelete, "Hello, I reply");
+		// more
+		UserComment comment_del_5 = userCommentsDao.createComment(identToDelete, course, null, "To reply");
+		UserComment comment_ndel_6 = userCommentsDao.replyTo(comment_del_5, ident, "I replied");
+		dbInstance.commitAndCloseSession();
+		
+		// delete the first user
+		userDeletionManager.deleteIdentity(identToDelete);
+		dbInstance.commitAndCloseSession();
+		
+		// delete comments from first identity, and replace the comment if it has a reply
+		UserComment deletedComment_del_1 = userCommentsDao.reloadComment(comment_del_1);
+		Assert.assertNull(deletedComment_del_1);
+		UserComment reloadedComment_ndel_2 = userCommentsDao.reloadComment(comment_ndel_2);
+		Assert.assertNotNull(reloadedComment_ndel_2);
+
+		// 4 was a reply -> delete it
+		UserComment deletedComment_del_4 = userCommentsDao.reloadComment(comment_del_4);
+		Assert.assertNull(deletedComment_del_4);
+		UserComment reloadedComment_ndel_3 = userCommentsDao.reloadComment(comment_ndel_3);
+		Assert.assertNotNull(reloadedComment_ndel_3);
+
+		// 5 has a reply, don't delete it
+		UserComment deletedComment_del_5 = userCommentsDao.reloadComment(comment_del_5);
+		Assert.assertNotNull(deletedComment_del_5);
+		UserComment reloadedComment_ndel_6 = userCommentsDao.reloadComment(comment_ndel_6);
+		Assert.assertNotNull(reloadedComment_ndel_6);
+		
+		// check repository statistics
+		RepositoryEntry reloadedEntry = repositoryService.loadByKey(course.getKey());
+		RepositoryEntryStatistics entryStatistics = reloadedEntry.getStatistics();
+		Assert.assertEquals(4, entryStatistics.getNumOfComments());
+	}
 }
diff --git a/src/test/java/org/olat/core/commons/services/commentAndRating/manager/UserRatingsDAOTest.java b/src/test/java/org/olat/core/commons/services/commentAndRating/manager/UserRatingsDAOTest.java
index 2185c6b2395db34fc742b4b9184b8310118c4bcf..5c1dcd8ce7f396eef06ca05be13115f7a1a93f30 100644
--- a/src/test/java/org/olat/core/commons/services/commentAndRating/manager/UserRatingsDAOTest.java
+++ b/src/test/java/org/olat/core/commons/services/commentAndRating/manager/UserRatingsDAOTest.java
@@ -22,16 +22,17 @@ package org.olat.core.commons.services.commentAndRating.manager;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
-import java.util.UUID;
-
 import org.junit.Assert;
 import org.junit.Test;
+import org.olat.admin.user.delete.service.UserDeletionManager;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.commons.services.commentAndRating.CommentAndRatingService;
-import org.olat.core.commons.services.commentAndRating.manager.UserRatingsDAO;
 import org.olat.core.commons.services.commentAndRating.model.UserRating;
 import org.olat.core.id.Identity;
 import org.olat.core.id.OLATResourceable;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryService;
+import org.olat.repository.model.RepositoryEntryStatistics;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -50,6 +51,10 @@ public class UserRatingsDAOTest extends OlatTestCase {
 	private UserRatingsDAO userRatingsDao;
 	@Autowired
 	private CommentAndRatingService service;
+	@Autowired
+	private RepositoryService repositoryService;
+	@Autowired
+	private UserDeletionManager userDeletionManager;
 	
 	@Test
 	public void should_service_present() {
@@ -60,7 +65,7 @@ public class UserRatingsDAOTest extends OlatTestCase {
 	@Test
 	public void createRating() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
-		Identity id = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-1-" + UUID.randomUUID().toString());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-1");
 		dbInstance.commitAndCloseSession();
 
 		//create
@@ -80,7 +85,7 @@ public class UserRatingsDAOTest extends OlatTestCase {
 	@Test
 	public void createUpdateRating() {
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
-		Identity id = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-1-" + UUID.randomUUID().toString());
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-1");
 		dbInstance.commitAndCloseSession();
 
 		//create
@@ -106,13 +111,13 @@ public class UserRatingsDAOTest extends OlatTestCase {
 	public void testCRUDRating() {
 		//init
 		OLATResourceable ores = JunitTestHelper.createRandomResource();
-		Identity ident1 = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-1-" + UUID.randomUUID().toString());
-		Identity ident2 = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-2-" + UUID.randomUUID().toString());
-		Identity ident3 = JunitTestHelper.createAndPersistIdentityAsUser("ucar-crud-3-" + UUID.randomUUID().toString());
+		Identity ident1 = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-1");
+		Identity ident2 = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-2");
+		Identity ident3 = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-3");
 
 		
-		assertEquals(0, userRatingsDao.getRatingAverage(ores, null), 0.01);
-		assertEquals(0, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01);
+		assertEquals(0.0f, userRatingsDao.getRatingAverage(ores, null), 0.01f);
+		assertEquals(0.0f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01f);
 		assertEquals(0l, userRatingsDao.countRatings(ores, null));
 		assertEquals(0l, userRatingsDao.countRatings(ores, "blubli"));
 		
@@ -120,8 +125,8 @@ public class UserRatingsDAOTest extends OlatTestCase {
 		Assert.assertNotNull(r1);
 		UserRating r2 = userRatingsDao.createRating(ident1, ores, "blubli", 2);
 		Assert.assertNotNull(r2);
-		assertEquals(2, userRatingsDao.getRatingAverage(ores, null), 0.01);
-		assertEquals(2, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01);
+		assertEquals(2.0f, userRatingsDao.getRatingAverage(ores, null), 0.01f);
+		assertEquals(2.0f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01f);
 		assertEquals(1l, userRatingsDao.countRatings(ores, null));
 		assertEquals(1l, userRatingsDao.countRatings(ores, "blubli"));
 		//
@@ -129,8 +134,8 @@ public class UserRatingsDAOTest extends OlatTestCase {
 		Assert.assertNotNull(r3);
 		UserRating r4 = userRatingsDao.createRating(ident2, ores, "blubli", 4);
 		Assert.assertNotNull(r4);
-		assertEquals(3, userRatingsDao.getRatingAverage(ores, null), 0.01);
-		assertEquals(3, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01);
+		assertEquals(3.0f, userRatingsDao.getRatingAverage(ores, null), 0.01f);
+		assertEquals(3.0f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01f);
 		assertEquals(2l, userRatingsDao.countRatings(ores, null));
 		assertEquals(2l, userRatingsDao.countRatings(ores, "blubli"));
 		// 
@@ -138,8 +143,8 @@ public class UserRatingsDAOTest extends OlatTestCase {
 		Assert.assertNotNull(r5);
 		UserRating r6 = userRatingsDao.createRating(ident3, ores, "blubli", 1);
 		Assert.assertNotNull(r6);
-		assertEquals(2.33f, userRatingsDao.getRatingAverage(ores, null), 0.01);
-		assertEquals(2.33f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01);
+		assertEquals(2.33f, userRatingsDao.getRatingAverage(ores, null), 0.01f);
+		assertEquals(2.33f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01f);
 		assertEquals(3l, userRatingsDao.countRatings(ores, null));
 		assertEquals(3l, userRatingsDao.countRatings(ores, "blubli"));
 		//
@@ -149,30 +154,84 @@ public class UserRatingsDAOTest extends OlatTestCase {
 		// can !!not!! create two ratings per person
 		r1 = userRatingsDao.createRating(ident1, ores, null, 2);
 		r2 = userRatingsDao.createRating(ident1, ores, "blubli", 2);
-		assertEquals(2.25f, userRatingsDao.getRatingAverage(ores, null), 0.01);
-		assertEquals(2.25f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01);
+		assertEquals(2.25f, userRatingsDao.getRatingAverage(ores, null), 0.01f);
+		assertEquals(2.25f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01f);
 		//can create 2 ratings
 		assertEquals(4l, userRatingsDao.countRatings(ores, null));
 		assertEquals(4l, userRatingsDao.countRatings(ores, "blubli"));
 		
 		// Delete ratings without subpath
 		userRatingsDao.deleteAllRatings(ores, null);
-		assertEquals(0f, userRatingsDao.getRatingAverage(ores, null), 0.01);
-		assertEquals(2.25f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01);
+		assertEquals(0f, userRatingsDao.getRatingAverage(ores, null), 0.01f);
+		assertEquals(2.25f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01f);
 		assertEquals(0l, userRatingsDao.countRatings(ores, null));
 		assertEquals(4l, userRatingsDao.countRatings(ores, "blubli"));
 
 		// Recreate and delete ignoring subpath
 		r1 = userRatingsDao.createRating(ident1, ores, null, 2);
 		r2 = userRatingsDao.createRating(ident1, ores, "blubli", 2);
-		assertEquals(2f, userRatingsDao.getRatingAverage(ores, null), 0.01);
-		assertEquals(2.2f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01);
+		assertEquals(2f, userRatingsDao.getRatingAverage(ores, null), 0.01f);
+		assertEquals(2.2f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01f);
 		assertEquals(1, userRatingsDao.countRatings(ores, null));
 		assertEquals(5l, userRatingsDao.countRatings(ores, "blubli"));
 		userRatingsDao.deleteAllRatingsIgnoringSubPath(ores);
-		assertEquals(0f, userRatingsDao.getRatingAverage(ores, null), 0.01);
-		assertEquals(0f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01);
+		assertEquals(0f, userRatingsDao.getRatingAverage(ores, null), 0.01f);
+		assertEquals(0f, userRatingsDao.getRatingAverage(ores, "blubli"), 0.01f);
 		assertEquals(0l, userRatingsDao.countRatings(ores, null));
 		assertEquals(0l, userRatingsDao.countRatings(ores, "blubli"));
 	}
+	
+	@Test
+	public void deleteUser() {
+		Identity identToDelete = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-4");
+		Identity ident2 = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-5");
+		Identity ident3 = JunitTestHelper.createAndPersistIdentityAsRndUser("ucar-crud-6");
+		OLATResourceable randomOres = JunitTestHelper.createRandomResource();
+		RepositoryEntry entry = JunitTestHelper.deployBasicCourse(ident2);
+		dbInstance.commitAndCloseSession();
+
+		// make some rating
+		UserRating r1 = userRatingsDao.createRating(identToDelete, randomOres, "rate", 2);
+		UserRating r2 = userRatingsDao.createRating(identToDelete, entry, null, 2);
+		UserRating r3 = userRatingsDao.createRating(ident2, randomOres, "rate", 4);
+		UserRating r4 = userRatingsDao.createRating(ident2, entry, null, 4);
+		userRatingsDao.createRating(ident3, randomOres, "rate", 3);
+		userRatingsDao.createRating(ident3, entry, null, 3);
+		dbInstance.commitAndCloseSession();
+		// check average before deletion
+		float randomAverage = userRatingsDao.getRatingAverage(randomOres, "rate");
+		Assert.assertEquals(3.0f, randomAverage, 0.001f);
+		float courseAverage = userRatingsDao.getRatingAverage(entry, null);
+		Assert.assertEquals(3.0f, courseAverage, 0.001f);
+
+		// delete first user
+		userDeletionManager.deleteIdentity(identToDelete);
+		dbInstance.commitAndCloseSession();
+		
+		//check that rating of the first user are deleted
+		UserRating deletedRating1 = userRatingsDao.reloadRating(r1);
+		Assert.assertNull(deletedRating1);
+		UserRating deletedRating2 = userRatingsDao.reloadRating(r2);
+		Assert.assertNull(deletedRating2);
+		// but not the rating of the other users
+		UserRating reloadedRating3 = userRatingsDao.reloadRating(r3);
+		Assert.assertNotNull(reloadedRating3);
+		UserRating reloadedRating4 = userRatingsDao.reloadRating(r4);
+		Assert.assertNotNull(reloadedRating4);
+
+		// check averages
+		float afterRandomAverage = userRatingsDao.getRatingAverage(randomOres, "rate");
+		Assert.assertEquals(3.5f, afterRandomAverage, 0.001f);
+		float afterCourseAverage = userRatingsDao.getRatingAverage(entry, null);
+		Assert.assertEquals(3.5f, afterCourseAverage, 0.001f);
+		
+		// check repository
+		RepositoryEntry reloadedEntry = repositoryService.loadByKey(entry.getKey());
+		RepositoryEntryStatistics entryStatistics = reloadedEntry.getStatistics();
+		Assert.assertEquals(2l, entryStatistics.getNumOfRatings());
+		Assert.assertEquals(3.5d, entryStatistics.getRating().doubleValue(), 0.001d);
+	}
+	
+	
+	
 }
\ No newline at end of file
diff --git a/src/test/java/org/olat/selenium/page/user/UserAdminPage.java b/src/test/java/org/olat/selenium/page/user/UserAdminPage.java
index a7456fc006400b10d0cf058f0c174c08faf26e41..dfd5e1b85e38b4f819556ac3b115eadfb977369a 100644
--- a/src/test/java/org/olat/selenium/page/user/UserAdminPage.java
+++ b/src/test/java/org/olat/selenium/page/user/UserAdminPage.java
@@ -115,14 +115,16 @@ public class UserAdminPage {
 		OOGraphene.waitModalDialog(browser);
 		
 		//confirm
-		By usernameBy = By.xpath("//div[contains(@class,'modal-dialog')]//p[text()[contains(.,'" + lastName + "')]]");
+		By usernameBy = By.xpath("//div[contains(@class,'modal-dialog')]//div[@class='o_error']/strong[text()[contains(.,'" + lastName + "')]]");
 		List<WebElement> confirmUserEls = browser.findElements(usernameBy);
 		Assert.assertFalse(confirmUserEls.isEmpty());
 		
-		By buttonsBy = By.cssSelector("div.modal-dialog div.modal-footer a.btn.btn-default");
-		List<WebElement> buttonEls = browser.findElements(buttonsBy);
-		Assert.assertEquals(2, buttonEls.size());
-		buttonEls.get(0).click();
+		By confirmCheckBy = By.cssSelector("div.o_sel_confirm_delete_user input[type='checkbox']");
+		WebElement confirmCheckEl = browser.findElement(confirmCheckBy);
+		OOGraphene.check(confirmCheckEl, Boolean.TRUE);
+		
+		By buttonsBy = By.cssSelector("div.modal-dialog div.modal-body a.btn.o_sel_delete_user");
+		browser.findElement(buttonsBy).click();
 		OOGraphene.waitBusy(browser);
 		OOGraphene.waitAndCloseBlueMessageWindow(browser);
 		return this;
diff --git a/src/test/java/org/olat/test/AllTestsJunit4.java b/src/test/java/org/olat/test/AllTestsJunit4.java
index acf2aec79686273d731db3abfae8dc5e931ab880..a1035bda32cd92cf81454464a7d79081fac290ec 100644
--- a/src/test/java/org/olat/test/AllTestsJunit4.java
+++ b/src/test/java/org/olat/test/AllTestsJunit4.java
@@ -351,7 +351,7 @@ import org.junit.runners.Suite;
 	/**
 	 * Pure JUnit test without need of framework
 	 */
-	org.olat.core.commons.services.commentAndRating.manager.CommentAndRatingServiceImplTest.class,
+	org.olat.core.commons.services.commentAndRating.manager.CommentAndRatingServiceTest.class,
 	org.olat.core.commons.services.license.ui.LicenseSelectionConfigTest.class,
 	org.olat.core.gui.components.form.flexible.impl.elements.richText.TextModeTest.class,
 	org.olat.core.gui.components.form.flexible.impl.elements.SelectboxSelectionImplTest.class,