From 702db132b91d8c6e1fe51c1d68589dff560a848a Mon Sep 17 00:00:00 2001
From: uhensler <urs.hensler@frentix.com>
Date: Mon, 27 Apr 2020 16:39:19 +0200
Subject: [PATCH] OO-4657: Show score/passed in my courses even if no
 efficiency statement is available

---
 ...icateAndEfficiencyStatementController.java |  4 +-
 ...eAndEfficiencyStatementListController.java |  2 +-
 ...mLearningPathRepositoryListController.java | 12 +--
 .../CurriculumLearningPathRepositoryRow.java  |  4 +-
 .../assessment/AssessmentEntryScoring.java    | 32 +++++++
 .../modules/assessment/AssessmentService.java |  2 +-
 .../manager/AssessmentEntryDAO.java           | 15 +++-
 .../manager/AssessmentServiceImpl.java        |  3 +-
 .../model/AssessmentEntryScoringImpl.java     | 88 +++++++++++++++++++
 .../coach/ui/StudentCoursesController.java    |  8 +-
 .../RepositoryEntryMyCourseQueries.java       | 80 ++++++++---------
 .../model/RepositoryEntryMyCourseImpl.java    | 24 ++---
 .../DefaultRepositoryEntryDataSource.java     |  2 +-
 .../manager/AssessmentEntryDAOTest.java       |  7 +-
 ...rriculumElementViewsRowComparatorTest.java | 24 ++---
 .../RepositoryEntryMyCourseQueriesTest.java   | 63 +++++++++++++
 16 files changed, 282 insertions(+), 88 deletions(-)
 create mode 100644 src/main/java/org/olat/modules/assessment/AssessmentEntryScoring.java
 create mode 100644 src/main/java/org/olat/modules/assessment/model/AssessmentEntryScoringImpl.java

diff --git a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementController.java b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementController.java
index 1751ebdae39..d8805739db0 100644
--- a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementController.java
+++ b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementController.java
@@ -74,7 +74,7 @@ import org.olat.course.certificate.CertificatesManager;
 import org.olat.group.BusinessGroup;
 import org.olat.group.BusinessGroupService;
 import org.olat.group.model.SearchBusinessGroupParams;
-import org.olat.modules.assessment.AssessmentEntry;
+import org.olat.modules.assessment.AssessmentEntryScoring;
 import org.olat.modules.assessment.AssessmentService;
 import org.olat.modules.co.ContactFormController;
 import org.olat.modules.portfolio.PortfolioV2Module;
@@ -270,7 +270,7 @@ public class CertificateAndEfficiencyStatementController extends BasicController
 			}
 		}
 		
-		List<AssessmentEntry> completions = Collections.emptyList();
+		List<AssessmentEntryScoring> completions = Collections.emptyList();
 		if(courseRepoEntry != null) {
 			completions = assessmentService.loadRootAssessmentEntriesByAssessedIdentity(statementOwner,
 				Collections.singletonList(courseRepoEntry.getKey()));
diff --git a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java
index 5116adb6012..8859da1c3e1 100644
--- a/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java
+++ b/src/main/java/org/olat/course/certificate/ui/CertificateAndEfficiencyStatementListController.java
@@ -228,7 +228,7 @@ public class CertificateAndEfficiencyStatementListController extends FormBasicCo
 				.loadRootAssessmentEntriesByAssessedIdentity(assessedIdentity, courseEntryKeys).stream()
 				.filter(ae -> ae.getCompletion() != null)
 				.collect(Collectors.toMap(
-						ae -> ae.getRepositoryEntry().getKey(),
+						ae -> ae.getRepositoryEntryKey(),
 						ae -> ae.getCompletion()
 					));
 		
diff --git a/src/main/java/org/olat/course/learningpath/ui/CurriculumLearningPathRepositoryListController.java b/src/main/java/org/olat/course/learningpath/ui/CurriculumLearningPathRepositoryListController.java
index d1662a20930..f9d40716613 100644
--- a/src/main/java/org/olat/course/learningpath/ui/CurriculumLearningPathRepositoryListController.java
+++ b/src/main/java/org/olat/course/learningpath/ui/CurriculumLearningPathRepositoryListController.java
@@ -54,7 +54,7 @@ import org.olat.course.learningpath.ui.CurriculumLearningPathRepositoryDataModel
 import org.olat.course.run.environment.CourseEnvironment;
 import org.olat.course.run.userview.UserCourseEnvironment;
 import org.olat.course.run.userview.UserCourseEnvironmentImpl;
-import org.olat.modules.assessment.AssessmentEntry;
+import org.olat.modules.assessment.AssessmentEntryScoring;
 import org.olat.modules.assessment.AssessmentService;
 import org.olat.modules.assessment.ui.ScoreCellRenderer;
 import org.olat.modules.assessment.ui.component.LearningProgressCompletionCellRenderer;
@@ -127,15 +127,15 @@ public class CurriculumLearningPathRepositoryListController extends FormBasicCon
 				.map(RepositoryEntry::getKey)
 				.collect(Collectors.toList());
 		
-		List<AssessmentEntry> assessmentEntries = assessmentService.loadRootAssessmentEntriesByAssessedIdentity(participant, entryKeys);
-		Map<Long, AssessmentEntry> identityKeyToCompletion = new HashMap<>();
-		for (AssessmentEntry assessmentEntry : assessmentEntries) {
-			identityKeyToCompletion.put(assessmentEntry.getRepositoryEntry().getKey(), assessmentEntry);
+		List<AssessmentEntryScoring> assessmentEntries = assessmentService.loadRootAssessmentEntriesByAssessedIdentity(participant, entryKeys);
+		Map<Long, AssessmentEntryScoring> identityKeyToCompletion = new HashMap<>();
+		for (AssessmentEntryScoring assessmentEntry : assessmentEntries) {
+			identityKeyToCompletion.put(assessmentEntry.getRepositoryEntryKey(), assessmentEntry);
 		}
 		
 		List<CurriculumLearningPathRepositoryRow> rows = new ArrayList<>(repoEntries.size());
 		for (RepositoryEntry repositoryEntry : repoEntries) {
-			AssessmentEntry assessmentEntry = identityKeyToCompletion.get(repositoryEntry.getKey());
+			AssessmentEntryScoring assessmentEntry = identityKeyToCompletion.get(repositoryEntry.getKey());
 			CurriculumLearningPathRepositoryRow row = new CurriculumLearningPathRepositoryRow(repositoryEntry, assessmentEntry);
 			rows.add(row);
 			forgeLinks(row);
diff --git a/src/main/java/org/olat/course/learningpath/ui/CurriculumLearningPathRepositoryRow.java b/src/main/java/org/olat/course/learningpath/ui/CurriculumLearningPathRepositoryRow.java
index 363edf7dd7b..3534854a179 100644
--- a/src/main/java/org/olat/course/learningpath/ui/CurriculumLearningPathRepositoryRow.java
+++ b/src/main/java/org/olat/course/learningpath/ui/CurriculumLearningPathRepositoryRow.java
@@ -22,7 +22,7 @@ package org.olat.course.learningpath.ui;
 import java.math.BigDecimal;
 
 import org.olat.core.gui.components.form.flexible.elements.FormLink;
-import org.olat.modules.assessment.AssessmentEntry;
+import org.olat.modules.assessment.AssessmentEntryScoring;
 import org.olat.repository.RepositoryEntry;
 
 /**
@@ -40,7 +40,7 @@ public class CurriculumLearningPathRepositoryRow {
 	
 	private FormLink learningPathLink;
 
-	public CurriculumLearningPathRepositoryRow(RepositoryEntry repositoryEntry, AssessmentEntry assessmentEntry) {
+	public CurriculumLearningPathRepositoryRow(RepositoryEntry repositoryEntry, AssessmentEntryScoring assessmentEntry) {
 		this.repositoryEntry = repositoryEntry;
 		this.completion = assessmentEntry != null ? assessmentEntry.getCompletion(): null;
 		this.passed = assessmentEntry != null ? assessmentEntry.getPassed(): null;
diff --git a/src/main/java/org/olat/modules/assessment/AssessmentEntryScoring.java b/src/main/java/org/olat/modules/assessment/AssessmentEntryScoring.java
new file mode 100644
index 00000000000..3793c911d88
--- /dev/null
+++ b/src/main/java/org/olat/modules/assessment/AssessmentEntryScoring.java
@@ -0,0 +1,32 @@
+/**
+ * <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.assessment;
+
+/**
+ * 
+ * Initial date: 27 Apr 2020<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public interface AssessmentEntryScoring extends AssessmentEntryLight, AssessmentEntryCompletion {
+	
+	public Long getRepositoryEntryKey();
+	
+}
diff --git a/src/main/java/org/olat/modules/assessment/AssessmentService.java b/src/main/java/org/olat/modules/assessment/AssessmentService.java
index 4a511596931..4f92ab66720 100644
--- a/src/main/java/org/olat/modules/assessment/AssessmentService.java
+++ b/src/main/java/org/olat/modules/assessment/AssessmentService.java
@@ -82,7 +82,7 @@ public interface AssessmentService {
 	
 	public List<AssessmentEntry> loadAssessmentEntriesByAssessedIdentity(Identity assessedIdentity, RepositoryEntry entry);
 	
-	public List<AssessmentEntry> loadRootAssessmentEntriesByAssessedIdentity(Identity assessedIdentity, Collection<Long> entryKeys);
+	public List<AssessmentEntryScoring> loadRootAssessmentEntriesByAssessedIdentity(Identity assessedIdentity, Collection<Long> entryKeys);
 	
 	public List<AssessmentEntry> loadAssessmentEntries(BusinessGroup assessedGroup, RepositoryEntry entry, String subIdent);
 
diff --git a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java
index 792ef2e9fca..23985c1d1fc 100644
--- a/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java
+++ b/src/main/java/org/olat/modules/assessment/manager/AssessmentEntryDAO.java
@@ -34,6 +34,7 @@ import org.olat.core.commons.persistence.QueryBuilder;
 import org.olat.core.id.Identity;
 import org.olat.modules.assessment.AssessmentEntry;
 import org.olat.modules.assessment.AssessmentEntryCompletion;
+import org.olat.modules.assessment.AssessmentEntryScoring;
 import org.olat.modules.assessment.Overridable;
 import org.olat.modules.assessment.model.AssessmentEntryImpl;
 import org.olat.modules.assessment.model.AssessmentEntryStatus;
@@ -407,18 +408,26 @@ public class AssessmentEntryDAO {
 				.getResultList();
 	}
 
-	public List<AssessmentEntry> loadRootAssessmentEntriesByAssessedIdentity(Identity assessedIdentity, Collection<Long> entryKeys) {
+	public List<AssessmentEntryScoring> loadRootAssessmentEntriesByAssessedIdentity(Identity assessedIdentity, Collection<Long> entryKeys) {
 		if (assessedIdentity == null || entryKeys == null || entryKeys.isEmpty()) return Collections.emptyList();
 		
 		QueryBuilder sb = new QueryBuilder();
-		sb.append("select ae");
+		sb.append("select new org.olat.modules.assessment.model.AssessmentEntryScoringImpl(");
+		sb.append("       ae.key");
+		sb.append("     , ae.repositoryEntry.key");
+		sb.append("     , ae.completion");
+		sb.append("     , ae.score");
+		sb.append("     , ae.passed");
+		sb.append("     , ae.passedOriginal");
+		sb.append("     , ae.passedModificationDate");
+		sb.append("     )");
 		sb.append("  from assessmententry ae");
 		sb.and().append(" ae.entryRoot = true");
 		sb.and().append(" ae.identity.key = :identityKey");
 		sb.and().append(" ae.repositoryEntry.key in (:entryKeys)");
 		
 		return dbInstance.getCurrentEntityManager()
-				.createQuery(sb.toString(), AssessmentEntry.class)
+				.createQuery(sb.toString(), AssessmentEntryScoring.class)
 				.setParameter("identityKey", assessedIdentity.getKey())
 				.setParameter("entryKeys", entryKeys)
 				.getResultList();
diff --git a/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java b/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java
index f30cd2fbce1..19ec304374d 100644
--- a/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java
+++ b/src/main/java/org/olat/modules/assessment/manager/AssessmentServiceImpl.java
@@ -33,6 +33,7 @@ import org.olat.core.logging.Tracing;
 import org.olat.group.BusinessGroup;
 import org.olat.modules.assessment.AssessmentEntry;
 import org.olat.modules.assessment.AssessmentEntryCompletion;
+import org.olat.modules.assessment.AssessmentEntryScoring;
 import org.olat.modules.assessment.AssessmentService;
 import org.olat.modules.assessment.model.AssessmentEntryStatus;
 import org.olat.modules.curriculum.CurriculumElement;
@@ -131,7 +132,7 @@ public class AssessmentServiceImpl implements AssessmentService, UserDataDeletab
 	}
 
 	@Override
-	public List<AssessmentEntry> loadRootAssessmentEntriesByAssessedIdentity(Identity assessedIdentity, Collection<Long> entryKeys) {
+	public List<AssessmentEntryScoring> loadRootAssessmentEntriesByAssessedIdentity(Identity assessedIdentity, Collection<Long> entryKeys) {
 		return assessmentEntryDao.loadRootAssessmentEntriesByAssessedIdentity(assessedIdentity, entryKeys);
 	}
 	
diff --git a/src/main/java/org/olat/modules/assessment/model/AssessmentEntryScoringImpl.java b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryScoringImpl.java
new file mode 100644
index 00000000000..f192f9fa7f1
--- /dev/null
+++ b/src/main/java/org/olat/modules/assessment/model/AssessmentEntryScoringImpl.java
@@ -0,0 +1,88 @@
+/**
+ * <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.assessment.model;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import org.olat.modules.assessment.AssessmentEntryScoring;
+import org.olat.modules.assessment.Overridable;
+
+/**
+ * 
+ * Initial date: 24 Apr 2020<br>
+ * @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
+ *
+ */
+public class AssessmentEntryScoringImpl implements AssessmentEntryScoring {
+	
+	private final Long key;
+	private final Long repositoryEntryKey;
+	private final Double completion;
+	private final BigDecimal score;
+	private transient Overridable<Boolean> passedOverridable;
+	private final Boolean passed;
+	private final Boolean passedOriginal;
+	private final Date passedModificationDate;
+	
+	public AssessmentEntryScoringImpl(Long key, Long repositoryEntryKey, Double completion, BigDecimal score,
+			Boolean passed, Boolean passedOriginal, Date passedModificationDate) {
+		this.key = key;
+		this.repositoryEntryKey = repositoryEntryKey;
+		this.completion = completion;
+		this.score = score;
+		this.passed = passed;
+		this.passedOriginal = passedOriginal;
+		this.passedModificationDate = passedModificationDate;
+	}
+
+	@Override
+	public Long getKey() {
+		return key;
+	}
+	
+	@Override
+	public Long getRepositoryEntryKey() {
+		return repositoryEntryKey;
+	}
+
+	@Override
+	public Double getCompletion() {
+		return completion;
+	}
+	
+	private Overridable<Boolean> getPassedOverridable() {
+		if (passedOverridable == null) {
+			passedOverridable = new OverridableImpl<>(passed, passedOriginal, null, passedModificationDate);
+		}
+		return passedOverridable;
+	}
+
+	@Override
+	public Boolean getPassed() {
+		return getPassedOverridable().getCurrent();
+	}
+
+	@Override
+	public BigDecimal getScore() {
+		return score;
+	}
+	
+}
diff --git a/src/main/java/org/olat/modules/coach/ui/StudentCoursesController.java b/src/main/java/org/olat/modules/coach/ui/StudentCoursesController.java
index cb76c40c8c1..901ef3d29f4 100644
--- a/src/main/java/org/olat/modules/coach/ui/StudentCoursesController.java
+++ b/src/main/java/org/olat/modules/coach/ui/StudentCoursesController.java
@@ -70,7 +70,7 @@ import org.olat.course.certificate.CertificateEvent;
 import org.olat.course.certificate.CertificateLight;
 import org.olat.course.certificate.CertificatesManager;
 import org.olat.course.certificate.ui.DownloadCertificateCellRenderer;
-import org.olat.modules.assessment.AssessmentEntry;
+import org.olat.modules.assessment.AssessmentEntryScoring;
 import org.olat.modules.assessment.AssessmentService;
 import org.olat.modules.assessment.ui.ScoreCellRenderer;
 import org.olat.modules.assessment.ui.component.LearningProgressCompletionCellRenderer;
@@ -294,10 +294,10 @@ public class StudentCoursesController extends FormBasicController implements Act
 		
 		ConcurrentMap<IdentityRepositoryEntryKey, Double> completionsMap = new ConcurrentHashMap<>();
 		List<Long> courseEntryKeys = courses.stream().map(RepositoryEntry::getKey).collect(Collectors.toList());
-		List<AssessmentEntry> assessmentEntries = assessmentService.loadRootAssessmentEntriesByAssessedIdentity(student, courseEntryKeys);
-		for (AssessmentEntry assessmentEntry : assessmentEntries) {
+		List<AssessmentEntryScoring> assessmentEntries = assessmentService.loadRootAssessmentEntriesByAssessedIdentity(student, courseEntryKeys);
+		for (AssessmentEntryScoring assessmentEntry : assessmentEntries) {
 			if (assessmentEntry.getCompletion() != null) {
-				IdentityRepositoryEntryKey key = new IdentityRepositoryEntryKey(student.getKey(), assessmentEntry.getRepositoryEntry().getKey());
+				IdentityRepositoryEntryKey key = new IdentityRepositoryEntryKey(student.getKey(), assessmentEntry.getRepositoryEntryKey());
 				completionsMap.put(key, assessmentEntry.getCompletion());
 			}
 		}
diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryMyCourseQueries.java b/src/main/java/org/olat/repository/manager/RepositoryEntryMyCourseQueries.java
index 7aa02bfac31..bf979b05f3b 100644
--- a/src/main/java/org/olat/repository/manager/RepositoryEntryMyCourseQueries.java
+++ b/src/main/java/org/olat/repository/manager/RepositoryEntryMyCourseQueries.java
@@ -19,12 +19,13 @@
  */
 package org.olat.repository.manager;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import javax.persistence.FlushModeType;
@@ -42,10 +43,10 @@ import org.olat.core.id.Identity;
 import org.olat.core.id.Roles;
 import org.olat.core.logging.Tracing;
 import org.olat.core.util.StringHelper;
-import org.olat.course.assessment.manager.EfficiencyStatementManager;
 import org.olat.course.assessment.model.UserEfficiencyStatementImpl;
-import org.olat.course.assessment.model.UserEfficiencyStatementLight;
 import org.olat.fileresource.types.VideoFileResource;
+import org.olat.modules.assessment.AssessmentEntryScoring;
+import org.olat.modules.assessment.AssessmentService;
 import org.olat.modules.curriculum.CurriculumRef;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryMyView;
@@ -56,7 +57,6 @@ import org.olat.repository.model.RepositoryEntryStatistics;
 import org.olat.repository.model.SearchMyRepositoryEntryViewParams;
 import org.olat.repository.model.SearchMyRepositoryEntryViewParams.Filter;
 import org.olat.repository.model.SearchMyRepositoryEntryViewParams.OrderBy;
-import org.olat.resource.OLATResource;
 import org.olat.resource.OLATResourceImpl;
 import org.olat.user.UserImpl;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -82,7 +82,7 @@ public class RepositoryEntryMyCourseQueries {
 	@Autowired
 	private RepositoryModule repositoryModule;
 	@Autowired
-	private EfficiencyStatementManager efficiencyStatementManager;
+	private AssessmentService assessmentService;
 	
 	public int countViews(SearchMyRepositoryEntryViewParams params) {
 		if(params.getIdentity() == null) {
@@ -116,10 +116,9 @@ public class RepositoryEntryMyCourseQueries {
 		boolean needStats = repositoryModule.isRatingEnabled() || repositoryModule.isCommentEnabled() ||
 				(params.getResourceTypes() != null && params.getResourceTypes().contains(VideoFileResource.TYPE_NAME));
 		
-		List<Long> effKeys = new ArrayList<>();
+		List<Long> repoKeys = new ArrayList<>();
 		List<Object[]> objects = query.getResultList();
-		List<RepositoryEntryMyView> views = new ArrayList<>(objects.size());
-		Map<OLATResource,RepositoryEntryMyCourseImpl> viewsMap = new HashMap<>();
+		List<RepositoryEntryMyCourseImpl> viewImpls = new ArrayList<>(objects.size());
 		for(Object[] object:objects) {
 			RepositoryEntry re = (RepositoryEntry)object[0];
 			Number numOfMarks = (Number)object[1];
@@ -127,7 +126,6 @@ public class RepositoryEntryMyCourseQueries {
 			Number numOffers = (Number)object[2];
 			long offers = numOffers == null ? 0l : numOffers.longValue();
 			Integer myRating = (Integer)object[3];
-			Double completion = (Double)object[4];
 			
 			RepositoryEntryStatistics stats;
 			if (needStats) {
@@ -135,25 +133,26 @@ public class RepositoryEntryMyCourseQueries {
 			} else {
 				stats = null;
 			}
-			RepositoryEntryMyCourseImpl view = new RepositoryEntryMyCourseImpl(re, stats, hasMarks, offers, myRating, completion);
-			views.add(view);
-			viewsMap.put(re.getOlatResource(), view);
-
-			Long effKey = (Long)object[5];
-			if(effKey != null) {
-				effKeys.add(effKey);
-			}
+			RepositoryEntryMyCourseImpl view = new RepositoryEntryMyCourseImpl(re, stats, hasMarks, offers, myRating);
+			viewImpls.add(view);
+			repoKeys.add(re.getKey());
 		}
 		
-		if(!effKeys.isEmpty()) {
-			List<UserEfficiencyStatementLight> efficiencyStatements =
-					efficiencyStatementManager.findEfficiencyStatementsLight(effKeys);
-			for(UserEfficiencyStatementLight efficiencyStatement:efficiencyStatements) {
-				if(viewsMap.containsKey(efficiencyStatement.getResource())) {
-					viewsMap.get(efficiencyStatement.getResource()).setEfficiencyStatement(efficiencyStatement);
-				}
+		Map<Long, AssessmentEntryScoring> repoKeyToAssessmentEntry = assessmentService
+				.loadRootAssessmentEntriesByAssessedIdentity(params.getIdentity(), repoKeys).stream()
+				.collect(Collectors.toMap(ae -> ae.getRepositoryEntryKey(), Function.identity()));
+		List<RepositoryEntryMyView> views = new ArrayList<>(viewImpls.size());
+		for (RepositoryEntryMyCourseImpl view: viewImpls) {
+			AssessmentEntryScoring assessmentEntry = repoKeyToAssessmentEntry.getOrDefault(view.getKey(), null);
+			if (assessmentEntry != null) {
+				BigDecimal score = assessmentEntry.getScore();
+				view.setScore(score != null? Float.valueOf(score.floatValue()): null);
+				view.setPassed(assessmentEntry.getPassed());
+				view.setCompletion(assessmentEntry.getCompletion());
 			}
+			views.add(view);
 		}
+
 		return views;
 	}
 
@@ -197,15 +196,7 @@ public class RepositoryEntryMyCourseQueries {
 				sb.append(" 0 as myrating");
 			}
 			needIdentityKey = true;
-			sb.append(" ,(select ae.completion")
-			  .append("     from assessmententry as ae")
-			  .append("    where ae.repositoryEntry.key = v.key")
-			  .append("      and ae.entryRoot = true")
-			  .append("      and ae.identity.key=:identityKey")
-			  .append("  ) as completion");
-			sb.append(" ,(select eff.key from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as eff")
-			  .append("    where eff.resource=res and eff.identity.key=:identityKey")
-			  .append(" ) as effKey");
+			
 			needIdentityKey |= appendOrderByInSelect(params, sb);
 			sb.append(" from repositoryentry as v")
 			  .append(" inner join ").append(oracle ? "" : "fetch").append(" v.olatResource as res");
@@ -214,8 +205,6 @@ public class RepositoryEntryMyCourseQueries {
 			}
 			sb.append(" left join fetch v.lifecycle as lifecycle ");
 		}
-		//user course informations
-		//efficiency statements
 		
 		if(params.getParentEntry() != null) {
 			sb.append(" inner join catalogentry as cei on (v.key = cei.repositoryEntry.key)");
@@ -463,20 +452,20 @@ public class RepositoryEntryMyCourseQueries {
 				break;
 			case passed:
 				needIdentityKey = true;
-				sb.append(" and exists (select eff2.key from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as eff2")
-				  .append("    where eff2.resource=res and eff2.identity.key=:identityKey and eff2.passed=true")
+				sb.append(" and exists (select ae2.key from assessmententry as ae2")
+				  .append("    where ae2.repositoryEntry.key = v.key and ae2.passed=true and ae2.entryRoot = true and ae2.identity.key=:identityKey")
 				  .append(" )");
 				break;
 			case notPassed:
 				needIdentityKey = true;
-				sb.append(" and exists (select eff3.key from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as eff3")
-				  .append("    where eff3.resource=res and eff3.identity.key=:identityKey and eff3.passed=false")
+				sb.append(" and exists (select ae3.key from assessmententry as ae3")
+				  .append("    where ae3.repositoryEntry.key = v.key and ae3.entryRoot = true and ae3.identity.key=:identityKey and ae3.passed=false")
 				  .append(" )");
 				break;
 			case withoutPassedInfos:
 				needIdentityKey = true;
-				sb.append(" and exists (select eff4.key from ").append(UserEfficiencyStatementImpl.class.getName()).append(" as eff4")
-				  .append("    where eff4.resource=res and eff4.identity.key=:identityKey and eff4.passed is null")
+				sb.append(" and exists (select ae4.key from assessmententry as ae4")
+				  .append("    where ae4.repositoryEntry.key = v.key  and ae4.entryRoot = true and ae4.identity.key=:identityKey and ae4.passed is null")
 				  .append(" )");
 				break;
 			default: {}
@@ -516,6 +505,15 @@ public class RepositoryEntryMyCourseQueries {
 					  .append("    where eff4.resource=res and eff4.identity.key=:identityKey")
 					  .append(" ) as score");
 					break;
+				case completion:
+					needIdentityKey = true;
+					sb.append(" ,(select ae.completion")
+					  .append("     from assessmententry as ae")
+					  .append("    where ae.repositoryEntry.key = v.key")
+					  .append("      and ae.entryRoot = true")
+					  .append("      and ae.identity.key=:identityKey")
+					  .append("  ) as completion");
+					break;
 				default: //do nothing
 			}
 		}
diff --git a/src/main/java/org/olat/repository/model/RepositoryEntryMyCourseImpl.java b/src/main/java/org/olat/repository/model/RepositoryEntryMyCourseImpl.java
index d07758b5a49..83419ffdf49 100644
--- a/src/main/java/org/olat/repository/model/RepositoryEntryMyCourseImpl.java
+++ b/src/main/java/org/olat/repository/model/RepositoryEntryMyCourseImpl.java
@@ -23,7 +23,6 @@ import java.util.Date;
 
 import org.olat.core.id.CreateInfo;
 import org.olat.core.id.ModifiedInfo;
-import org.olat.course.assessment.model.UserEfficiencyStatementLight;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryMyView;
 import org.olat.repository.RepositoryEntryStatusEnum;
@@ -74,7 +73,7 @@ public class RepositoryEntryMyCourseImpl implements RepositoryEntryMyView, Creat
 	private final long offersAvailable;
 	
 	public RepositoryEntryMyCourseImpl(RepositoryEntry re, RepositoryEntryStatistics stats,
-			boolean marked, long offersAvailable, Integer myRating, Double completion) {
+			boolean marked, long offersAvailable, Integer myRating) {
 		key = re.getKey();
 		externalId = re.getExternalId();
 		externalRef = re.getExternalRef();
@@ -93,10 +92,8 @@ public class RepositoryEntryMyCourseImpl implements RepositoryEntryMyView, Creat
 		olatResource = re.getOlatResource();
 		lifecycle = re.getLifecycle();
 	
-
 		this.marked = marked;
 		this.myRating = myRating;
-		this.completion = completion;
 
 		if(stats != null) {
 			averageRating = stats.getRating();
@@ -112,13 +109,6 @@ public class RepositoryEntryMyCourseImpl implements RepositoryEntryMyView, Creat
 		
 		this.offersAvailable = offersAvailable;
 	}
-	
-	public void setEfficiencyStatement(UserEfficiencyStatementLight efficiencyStatment) {
-		if(efficiencyStatment != null) {
-			score = efficiencyStatment.getScore();
-			passed = efficiencyStatment.getPassed();
-		}
-	}
 
 	@Override
 	public Long getKey() {
@@ -226,16 +216,28 @@ public class RepositoryEntryMyCourseImpl implements RepositoryEntryMyView, Creat
 		return score;
 	}
 
+	public void setScore(Float score) {
+		this.score = score;
+	}
+
 	@Override
 	public Boolean getPassed() {
 		return passed;
 	}
+
+	public void setPassed(Boolean passed) {
+		this.passed = passed;
+	}
 	
 	@Override
 	public Double getCompletion() {
 		return completion;
 	}
 
+	public void setCompletion(Double completion) {
+		this.completion = completion;
+	}
+
 	@Override
 	public boolean isMarked() {
 		return marked;
diff --git a/src/main/java/org/olat/repository/ui/list/DefaultRepositoryEntryDataSource.java b/src/main/java/org/olat/repository/ui/list/DefaultRepositoryEntryDataSource.java
index d829a2c60ca..1c8b34377ff 100644
--- a/src/main/java/org/olat/repository/ui/list/DefaultRepositoryEntryDataSource.java
+++ b/src/main/java/org/olat/repository/ui/list/DefaultRepositoryEntryDataSource.java
@@ -53,7 +53,7 @@ import org.olat.resource.accesscontrol.ui.PriceFormat;
  *
  */
 public class DefaultRepositoryEntryDataSource implements FlexiTableDataSourceDelegate<RepositoryEntryRow> {
-	
+
 	private final RepositoryEntryDataSourceUIFactory uifactory;
 	private final SearchMyRepositoryEntryViewParams searchParams;
 	
diff --git a/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java b/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java
index 5167a405ff4..755611f8ea0 100644
--- a/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java
+++ b/src/test/java/org/olat/modules/assessment/manager/AssessmentEntryDAOTest.java
@@ -47,6 +47,7 @@ import org.olat.group.manager.BusinessGroupDAO;
 import org.olat.group.manager.BusinessGroupRelationDAO;
 import org.olat.modules.assessment.AssessmentEntry;
 import org.olat.modules.assessment.AssessmentEntryCompletion;
+import org.olat.modules.assessment.AssessmentEntryScoring;
 import org.olat.modules.assessment.Overridable;
 import org.olat.modules.assessment.model.AssessmentEntryImpl;
 import org.olat.modules.assessment.model.AssessmentEntryStatus;
@@ -704,11 +705,11 @@ public class AssessmentEntryDAOTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 		
 		List<Long> entryKeys = Arrays.asList(entry1.getKey(), entry2.getKey());
-		List<AssessmentEntry> assessmentEnries = assessmentEntryDao.loadRootAssessmentEntriesByAssessedIdentity(assessedIdentity, entryKeys);
+		List<AssessmentEntryScoring> assessmentEnries = assessmentEntryDao.loadRootAssessmentEntriesByAssessedIdentity(assessedIdentity, entryKeys);
 		
 		Assert.assertEquals(2, assessmentEnries.size());
-		Map<Long, AssessmentEntry> keysToCompletion = assessmentEnries.stream()
-				.collect(Collectors.toMap(ae -> ae.getRepositoryEntry().getKey(), Function.identity()));
+		Map<Long, AssessmentEntryScoring> keysToCompletion = assessmentEnries.stream()
+				.collect(Collectors.toMap(ae -> ae.getRepositoryEntryKey(), Function.identity()));
 		Assert.assertEquals(1, keysToCompletion.get(entry1.getKey()).getCompletion().intValue());
 		Assert.assertEquals(0, keysToCompletion.get(entry2.getKey()).getCompletion().intValue());
 	}
diff --git a/src/test/java/org/olat/modules/curriculum/ui/component/CurriculumElementViewsRowComparatorTest.java b/src/test/java/org/olat/modules/curriculum/ui/component/CurriculumElementViewsRowComparatorTest.java
index 05cb25683ed..4ade9fe496c 100644
--- a/src/test/java/org/olat/modules/curriculum/ui/component/CurriculumElementViewsRowComparatorTest.java
+++ b/src/test/java/org/olat/modules/curriculum/ui/component/CurriculumElementViewsRowComparatorTest.java
@@ -127,13 +127,13 @@ public class CurriculumElementViewsRowComparatorTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 		
 		CurriculumElementWithViewsRow row1 = new CurriculumElementWithViewsRow(element, null,
-				new RepositoryEntryMyCourseImpl(entry1, null, false, 0, 0, null), false);
+				new RepositoryEntryMyCourseImpl(entry1, null, false, 0, 0), false);
 		CurriculumElementWithViewsRow row2 = new CurriculumElementWithViewsRow(element, null,
-				new RepositoryEntryMyCourseImpl(entry2, null, false, 0, 0, null), false);
+				new RepositoryEntryMyCourseImpl(entry2, null, false, 0, 0), false);
 		CurriculumElementWithViewsRow row3 = new CurriculumElementWithViewsRow(element, null,
-				new RepositoryEntryMyCourseImpl(entry3, null, false, 0, 0, null), false);
+				new RepositoryEntryMyCourseImpl(entry3, null, false, 0, 0), false);
 		CurriculumElementWithViewsRow row4 = new CurriculumElementWithViewsRow(element, null,
-				new RepositoryEntryMyCourseImpl(entry4, null, false, 0, 0, null), false);
+				new RepositoryEntryMyCourseImpl(entry4, null, false, 0, 0), false);
 
 		List<CurriculumElementWithViewsRow> rows = new ArrayList<>();
 		rows.add(row1);
@@ -174,16 +174,16 @@ public class CurriculumElementViewsRowComparatorTest extends OlatTestCase {
 		CurriculumElementWithViewsRow parent = new CurriculumElementWithViewsRow(element, null, 4);
 		
 		CurriculumElementWithViewsRow row1 = new CurriculumElementWithViewsRow(element, null,
-				new RepositoryEntryMyCourseImpl(entry1, null, false, 0, 0, null), false);
+				new RepositoryEntryMyCourseImpl(entry1, null, false, 0, 0), false);
 		row1.setParent(parent);
 		CurriculumElementWithViewsRow row2 = new CurriculumElementWithViewsRow(element, null,
-				new RepositoryEntryMyCourseImpl(entry2, null, false, 0, 0, null), false);
+				new RepositoryEntryMyCourseImpl(entry2, null, false, 0, 0), false);
 		row2.setParent(parent);
 		CurriculumElementWithViewsRow row3 = new CurriculumElementWithViewsRow(element, null,
-				new RepositoryEntryMyCourseImpl(entry3, null, false, 0, 0, null), false);
+				new RepositoryEntryMyCourseImpl(entry3, null, false, 0, 0), false);
 		row3.setParent(parent);
 		CurriculumElementWithViewsRow row4 = new CurriculumElementWithViewsRow(element, null,
-				new RepositoryEntryMyCourseImpl(entry4, null, false, 0, 0, null), false);
+				new RepositoryEntryMyCourseImpl(entry4, null, false, 0, 0), false);
 		row4.setParent(parent);
 
 		List<CurriculumElementWithViewsRow> rows = new ArrayList<>();
@@ -236,13 +236,13 @@ public class CurriculumElementViewsRowComparatorTest extends OlatTestCase {
 		dbInstance.commitAndCloseSession();
 
 		CurriculumElementWithViewsRow row1 = new CurriculumElementWithViewsRow(element1, null,
-				new RepositoryEntryMyCourseImpl(entry1, null, false, 0, 0, null), true);
+				new RepositoryEntryMyCourseImpl(entry1, null, false, 0, 0), true);
 		CurriculumElementWithViewsRow row2 = new CurriculumElementWithViewsRow(element2, null,
-				new RepositoryEntryMyCourseImpl(entry2, null, false, 0, 0, null), true);
+				new RepositoryEntryMyCourseImpl(entry2, null, false, 0, 0), true);
 		CurriculumElementWithViewsRow row3 = new CurriculumElementWithViewsRow(element3, null,
-				new RepositoryEntryMyCourseImpl(entry3, null, false, 0, 0, null), true);
+				new RepositoryEntryMyCourseImpl(entry3, null, false, 0, 0), true);
 		CurriculumElementWithViewsRow row4 = new CurriculumElementWithViewsRow(element4, null,
-				new RepositoryEntryMyCourseImpl(entry4, null, false, 0, 0, null), true);
+				new RepositoryEntryMyCourseImpl(entry4, null, false, 0, 0), true);
 
 		List<CurriculumElementWithViewsRow> rows = new ArrayList<>();
 		rows.add(row1);
diff --git a/src/test/java/org/olat/repository/manager/RepositoryEntryMyCourseQueriesTest.java b/src/test/java/org/olat/repository/manager/RepositoryEntryMyCourseQueriesTest.java
index 695f840ac56..6596af6fe69 100644
--- a/src/test/java/org/olat/repository/manager/RepositoryEntryMyCourseQueriesTest.java
+++ b/src/test/java/org/olat/repository/manager/RepositoryEntryMyCourseQueriesTest.java
@@ -19,9 +19,15 @@
  */
 package org.olat.repository.manager;
 
+import static org.olat.test.JunitTestHelper.random;
+
+import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import org.assertj.core.api.SoftAssertions;
+import org.assertj.core.data.Offset;
 import org.junit.Assert;
 import org.junit.Test;
 import org.olat.basesecurity.BaseSecurity;
@@ -29,11 +35,14 @@ import org.olat.basesecurity.GroupRoles;
 import org.olat.core.commons.persistence.DB;
 import org.olat.core.id.Identity;
 import org.olat.core.id.Roles;
+import org.olat.modules.assessment.AssessmentEntry;
+import org.olat.modules.assessment.AssessmentService;
 import org.olat.repository.RepositoryEntry;
 import org.olat.repository.RepositoryEntryMyView;
 import org.olat.repository.RepositoryEntryStatusEnum;
 import org.olat.repository.RepositoryManager;
 import org.olat.repository.model.SearchMyRepositoryEntryViewParams;
+import org.olat.repository.model.SearchMyRepositoryEntryViewParams.Filter;
 import org.olat.repository.model.SearchMyRepositoryEntryViewParams.OrderBy;
 import org.olat.test.JunitTestHelper;
 import org.olat.test.OlatTestCase;
@@ -56,6 +65,8 @@ public class RepositoryEntryMyCourseQueriesTest extends OlatTestCase {
 	@Autowired
 	private RepositoryManager repositoryManager;
 	@Autowired
+	private AssessmentService assessmentService;
+	@Autowired
 	private RepositoryEntryRelationDAO repositoryEntryRelationDao;
 	@Autowired
 	private RepositoryEntryMyCourseQueries repositoryEntryMyCourseViewQueries;
@@ -99,6 +110,27 @@ public class RepositoryEntryMyCourseQueriesTest extends OlatTestCase {
 		}
 	}
 	
+	/**
+	 * Check only the syntax of the filter statements..
+	 */
+	@Test
+	public void searchViews_filter() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("mycourses-view-2-");
+		dbInstance.commit();
+		Roles roles = securityManager.getRoles(id);
+		
+		SearchMyRepositoryEntryViewParams params
+			= new SearchMyRepositoryEntryViewParams(id, roles);
+		params.setMarked(Boolean.TRUE);
+		
+		for(Filter filter:Filter.values()) {
+			params.setFilters(Arrays.asList(filter));
+			List<RepositoryEntryMyView> viewAsc = repositoryEntryMyCourseViewQueries.searchViews(params, 0, 10);
+			Assert.assertNotNull(viewAsc);
+		}
+	}
+
+	
 	/**
 	 * Check the search parameter mandatory membership.
 	 */
@@ -449,6 +481,37 @@ public class RepositoryEntryMyCourseQueriesTest extends OlatTestCase {
 		Assert.assertFalse(contains(reNotCoach, views));
 	}
 	
+	@Test
+	public void searchViews_assessment_values() {
+		Identity id = JunitTestHelper.createAndPersistIdentityAsRndUser("mycourses-view-11-");
+		RepositoryEntry re = JunitTestHelper.createAndPersistRepositoryEntry(true);
+		repositoryManager.setAccess(re, RepositoryEntryStatusEnum.published, false, false);
+		repositoryEntryRelationDao.addRole(id, re, GroupRoles.participant.name());
+		
+		AssessmentEntry rootAE = assessmentService.getOrCreateAssessmentEntry(id, null, re, random(), Boolean.TRUE, null);
+		rootAE.setPassed(Boolean.TRUE);
+		rootAE.setScore(BigDecimal.valueOf(0.9));
+		rootAE.setCompletion(Double.valueOf(0.8));
+		rootAE = assessmentService.updateAssessmentEntry(rootAE);
+		AssessmentEntry childAE = assessmentService.getOrCreateAssessmentEntry(id, null, re, random(), Boolean.FALSE, null);
+		childAE.setPassed(Boolean.TRUE);
+		childAE.setScore(BigDecimal.valueOf(0.3));
+		childAE.setCompletion(Double.valueOf(0.2));
+		childAE = assessmentService.updateAssessmentEntry(childAE);
+		dbInstance.closeSession();
+		
+		SearchMyRepositoryEntryViewParams params = new SearchMyRepositoryEntryViewParams(id, Roles.userRoles());
+		params.setIdAndRefs(re.getKey().toString());
+		
+		List<RepositoryEntryMyView> views = repositoryEntryMyCourseViewQueries.searchViews(params, 0, -1);
+		RepositoryEntryMyView view = views.get(0);
+		SoftAssertions softly = new SoftAssertions();
+		softly.assertThat(view.getPassed()).isTrue();
+		softly.assertThat(view.getScore()).isEqualTo(0.9f, Offset.offset(0.001f));
+		softly.assertThat(view.getCompletion()).isEqualTo(0.8, Offset.offset(0.001));
+		softly.assertAll();
+	}
+	
 	private final boolean contains(RepositoryEntry re, List<RepositoryEntryMyView> views) {
 		for(RepositoryEntryMyView view:views) {
 			if(re.getKey().equals(view.getKey())) {
-- 
GitLab