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