From 8f57716b03003ad55103c04915a86a564f5fd24b Mon Sep 17 00:00:00 2001 From: uhensler <urs.hensler@frentix.com> Date: Tue, 18 Dec 2018 14:51:57 +0100 Subject: [PATCH] OO-3778: Filter quality analysis by curriculum element type --- .../analysis/AnalysisSearchParameter.java | 14 +++ .../quality/analysis/AvailableAttributes.java | 10 +- .../analysis/QualityAnalysisService.java | 3 + .../analysis/manager/AnalysisFilterDAO.java | 23 ++++ .../manager/QualityAnalysisServiceImpl.java | 6 + .../quality/analysis/ui/FilterController.java | 52 ++++++++- .../ui/_i18n/LocalStrings_de.properties | 1 + .../ui/_i18n/LocalStrings_en.properties | 1 + .../modules/quality/ui/QualityUIFactory.java | 26 +++++ .../manager/AnalysisFilterDAOTest.java | 110 ++++++++++++++++++ 10 files changed, 241 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/olat/modules/quality/analysis/AnalysisSearchParameter.java b/src/main/java/org/olat/modules/quality/analysis/AnalysisSearchParameter.java index 1bdcac3d573..b01c07f8088 100644 --- a/src/main/java/org/olat/modules/quality/analysis/AnalysisSearchParameter.java +++ b/src/main/java/org/olat/modules/quality/analysis/AnalysisSearchParameter.java @@ -27,6 +27,7 @@ import java.util.List; import org.olat.basesecurity.IdentityRef; import org.olat.core.id.OrganisationRef; import org.olat.modules.curriculum.CurriculumElementRef; +import org.olat.modules.curriculum.CurriculumElementTypeRef; import org.olat.modules.curriculum.CurriculumRef; import org.olat.modules.quality.QualityContextRole; import org.olat.modules.taxonomy.TaxonomyLevelRef; @@ -53,6 +54,7 @@ public class AnalysisSearchParameter { private List<? extends OrganisationRef> contextOrganisationRefs; // of the executor private Collection<? extends CurriculumRef> contextCurriculumRefs; private List<? extends CurriculumElementRef> contextCurriculumElementRefs; + private Collection<? extends CurriculumElementTypeRef> contextCurriculumElementTypeRefs; private List<? extends OrganisationRef> contextCurriculumOrganisationRefs; private List<? extends TaxonomyLevelRef> contextTaxonomyLevelRefs; private Collection<Integer> seriesIndexes; @@ -164,6 +166,15 @@ public class AnalysisSearchParameter { this.contextCurriculumElementRefs = contextCurriculumElementRefs; } + public Collection<? extends CurriculumElementTypeRef> getContextCurriculumElementTypeRefs() { + return contextCurriculumElementTypeRefs; + } + + public void setContextCurriculumElementTypeRefs( + Collection<? extends CurriculumElementTypeRef> contextCurriculumElementTypeRefs) { + this.contextCurriculumElementTypeRefs = contextCurriculumElementTypeRefs; + } + public List<? extends TaxonomyLevelRef> getContextTaxonomyLevelRefs() { return contextTaxonomyLevelRefs; } @@ -229,6 +240,9 @@ public class AnalysisSearchParameter { clone.contextCurriculumElementRefs = this.contextCurriculumElementRefs != null ? new ArrayList<>(this.contextCurriculumElementRefs) : null; + clone.contextCurriculumElementTypeRefs = this.contextCurriculumElementTypeRefs != null + ? new ArrayList<>(this.contextCurriculumElementTypeRefs) + : null; clone.contextTaxonomyLevelRefs = this.contextTaxonomyLevelRefs != null ? new ArrayList<>(this.contextTaxonomyLevelRefs) : null; diff --git a/src/main/java/org/olat/modules/quality/analysis/AvailableAttributes.java b/src/main/java/org/olat/modules/quality/analysis/AvailableAttributes.java index d8ac2208071..d4ff85b8fa2 100644 --- a/src/main/java/org/olat/modules/quality/analysis/AvailableAttributes.java +++ b/src/main/java/org/olat/modules/quality/analysis/AvailableAttributes.java @@ -36,6 +36,7 @@ public class AvailableAttributes { private final boolean contextExecutorOrganisation; private final boolean contextCurriculum; private final boolean contextCurriculumElement; + private final boolean contextCurriculumElementType; private final boolean contextCurriculumOrganisation; private final boolean contextTaxonomyLevel; private final boolean seriesIndex; @@ -44,8 +45,8 @@ public class AvailableAttributes { public AvailableAttributes(boolean topicIdentity, boolean topicRepository, boolean topicOrganisation, boolean topicCurriculum, boolean topicCurriculumElement, Boolean contextLocation, boolean contextExecutorOrganisation, boolean contextCurriculum, boolean contextCurriculumElement, - boolean contextCurriculumOrganisation, boolean contextTaxonomyLevel, boolean seriesIndex, - boolean dataCollection) { + boolean contextCurriculumElementType, boolean contextCurriculumOrganisation, boolean contextTaxonomyLevel, + boolean seriesIndex, boolean dataCollection) { this.topicIdentity = topicIdentity; this.topicRepository = topicRepository; this.topicOrganisation = topicOrganisation; @@ -55,6 +56,7 @@ public class AvailableAttributes { this.contextExecutorOrganisation = contextExecutorOrganisation; this.contextCurriculum = contextCurriculum; this.contextCurriculumElement = contextCurriculumElement; + this.contextCurriculumElementType = contextCurriculumElementType; this.contextCurriculumOrganisation = contextCurriculumOrganisation; this.contextTaxonomyLevel = contextTaxonomyLevel; this.seriesIndex = seriesIndex; @@ -97,6 +99,10 @@ public class AvailableAttributes { return contextCurriculumElement; } + public boolean isContextCurriculumElementType() { + return contextCurriculumElementType; + } + public boolean isContextCurriculumOrganisation() { return contextCurriculumOrganisation; } diff --git a/src/main/java/org/olat/modules/quality/analysis/QualityAnalysisService.java b/src/main/java/org/olat/modules/quality/analysis/QualityAnalysisService.java index 367e306d48f..d0d0390a3e4 100644 --- a/src/main/java/org/olat/modules/quality/analysis/QualityAnalysisService.java +++ b/src/main/java/org/olat/modules/quality/analysis/QualityAnalysisService.java @@ -26,6 +26,7 @@ import org.olat.basesecurity.IdentityShort; import org.olat.core.id.Organisation; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementType; import org.olat.modules.forms.SessionFilter; import org.olat.modules.forms.model.xml.Rubric; import org.olat.modules.quality.QualityContextRole; @@ -77,6 +78,8 @@ public interface QualityAnalysisService { public List<CurriculumElement> loadContextCurriculumElements(AnalysisSearchParameter searchParams, boolean withParents); + public List<CurriculumElementType> loadContextCurriculumElementTypes(AnalysisSearchParameter searchParams); + public List<Organisation> loadContextCurriculumOrganisations(AnalysisSearchParameter searchParams, boolean withParents); public List<TaxonomyLevel> loadContextTaxonomyLevels(AnalysisSearchParameter searchParams, boolean withParents); diff --git a/src/main/java/org/olat/modules/quality/analysis/manager/AnalysisFilterDAO.java b/src/main/java/org/olat/modules/quality/analysis/manager/AnalysisFilterDAO.java index bd9b2c9ea22..e592da4a345 100644 --- a/src/main/java/org/olat/modules/quality/analysis/manager/AnalysisFilterDAO.java +++ b/src/main/java/org/olat/modules/quality/analysis/manager/AnalysisFilterDAO.java @@ -35,6 +35,8 @@ import org.olat.core.id.OrganisationRef; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementRef; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeRef; import org.olat.modules.curriculum.CurriculumRef; import org.olat.modules.quality.QualityContextRole; import org.olat.modules.quality.QualityDataCollection; @@ -74,6 +76,7 @@ public class AnalysisFilterDAO { sb.append(" , count(contextToOrganisation.organisation.key) > 0"); sb.append(" , count(contextCurriculum.key) > 0"); sb.append(" , count(contextCurriculumElement.key) > 0"); + sb.append(" , count(contextCurriculumElement.type.key) > 0"); sb.append(" , count(contextCurriculumOrganisation.key) > 0"); sb.append(" , count(contextToTaxonomyLevel.taxonomyLevel.key) > 0"); sb.append(" , CASE WHEN max(survey.seriesIndex) is not null THEN max(survey.seriesIndex) ELSE 0 END >= 2"); @@ -194,6 +197,19 @@ public class AnalysisFilterDAO { return query.getResultList(); } + List<CurriculumElementType> loadContextCurriculumElementsTypes(AnalysisSearchParameter searchParams) { + QueryBuilder sb = new QueryBuilder(); + sb.append("select distinct contextCurriculumElement.type"); + appendFrom(sb, searchParams); + appendWhere(sb, searchParams); + sb.and().append("contextCurriculumElement.type is not null"); + + TypedQuery<CurriculumElementType> query = dbInstance.getCurrentEntityManager() + .createQuery(sb.toString(), CurriculumElementType.class); + appendParameters(query, searchParams); + return query.getResultList(); + } + List<String> loadContextTaxonomyLevelPathes(AnalysisSearchParameter searchParams) { QueryBuilder sb = new QueryBuilder(); sb.append("select distinct taxonomyLevel.materializedPathKeys"); @@ -502,6 +518,9 @@ public class AnalysisFilterDAO { } } } + if (searchParams.getContextCurriculumElementTypeRefs() != null && !searchParams.getContextCurriculumElementTypeRefs().isEmpty()) { + sb.and().append("contextCurriculumElement.type.key in :contextCurriculumElementTypeKeys"); + } if (searchParams.getContextCurriculumOrganisationRefs() != null && !searchParams.getContextCurriculumOrganisationRefs().isEmpty()) { // load the organisations and all children sb.and(); @@ -605,6 +624,10 @@ public class AnalysisFilterDAO { query.setParameter(parameter, value); } } + if (searchParams.getContextCurriculumElementTypeRefs() != null && !searchParams.getContextCurriculumElementTypeRefs().isEmpty()) { + List<Long> keys = searchParams.getContextCurriculumElementTypeRefs().stream().map(CurriculumElementTypeRef::getKey).collect(toList()); + query.setParameter("contextCurriculumElementTypeKeys", keys); + } if (searchParams.getContextCurriculumOrganisationRefs() != null && !searchParams.getContextCurriculumOrganisationRefs().isEmpty()) { for (int i = 0; i < searchParams.getContextCurriculumOrganisationRefs().size(); i++) { String parameter = new StringBuilder(40).append("contextCurriculumOrganisationPath").append(i).toString(); diff --git a/src/main/java/org/olat/modules/quality/analysis/manager/QualityAnalysisServiceImpl.java b/src/main/java/org/olat/modules/quality/analysis/manager/QualityAnalysisServiceImpl.java index 20e0580a770..cf053e2985e 100644 --- a/src/main/java/org/olat/modules/quality/analysis/manager/QualityAnalysisServiceImpl.java +++ b/src/main/java/org/olat/modules/quality/analysis/manager/QualityAnalysisServiceImpl.java @@ -32,6 +32,7 @@ import org.olat.core.id.Organisation; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementRef; +import org.olat.modules.curriculum.CurriculumElementType; import org.olat.modules.curriculum.CurriculumRef; import org.olat.modules.curriculum.CurriculumService; import org.olat.modules.curriculum.model.CurriculumElementRefImpl; @@ -218,6 +219,11 @@ public class QualityAnalysisServiceImpl implements QualityAnalysisService { } return elementsOfCurriculums; } + + @Override + public List<CurriculumElementType> loadContextCurriculumElementTypes(AnalysisSearchParameter searchParams) { + return filterDao.loadContextCurriculumElementsTypes(searchParams); + } @Override public List<Organisation> loadContextCurriculumOrganisations(AnalysisSearchParameter searchParams, boolean withParents) { diff --git a/src/main/java/org/olat/modules/quality/analysis/ui/FilterController.java b/src/main/java/org/olat/modules/quality/analysis/ui/FilterController.java index 3ecdbe9814b..4719e3f264b 100644 --- a/src/main/java/org/olat/modules/quality/analysis/ui/FilterController.java +++ b/src/main/java/org/olat/modules/quality/analysis/ui/FilterController.java @@ -51,6 +51,8 @@ import org.olat.core.id.OrganisationRef; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementRef; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeRef; import org.olat.modules.curriculum.CurriculumModule; import org.olat.modules.curriculum.CurriculumRef; import org.olat.modules.curriculum.ui.CurriculumTreeModel; @@ -92,6 +94,7 @@ public class FilterController extends FormBasicController { private MultipleSelectionElement contextExecutorOrganisationEl; private MultipleSelectionElement contextCurriculumEl; private MultipleSelectionElement contextCurriculumElementEl; + private MultipleSelectionElement contextCurriculumElementTypeEl; private MultipleSelectionElement contextCurriculumOrganisationEl; private MultipleSelectionElement contextTaxonomyLevelEl; private MultipleSelectionElement contextLocationEl; @@ -167,6 +170,9 @@ public class FilterController extends FormBasicController { contextCurriculumElementEl = uifactory.addCheckboxesDropdown("filter.context.curriculum.elements", formLayout); contextCurriculumElementEl.addActionListener(FormEvent.ONCLICK); + contextCurriculumElementTypeEl = uifactory.addCheckboxesDropdown("filter.context.curriculum.element.types", formLayout); + contextCurriculumElementTypeEl.addActionListener(FormEvent.ONCLICK); + contextCurriculumOrganisationEl = uifactory.addCheckboxesDropdown("filter.context.curriculum.organisations", formLayout); contextCurriculumOrganisationEl.addActionListener(FormEvent.ONCLICK); @@ -199,6 +205,7 @@ public class FilterController extends FormBasicController { setContextExecutorOrganisationValues(); setContextCurriculumValues(); setContextCurriculumElementValues(); + setContextCurriculumElementTypeValues(); setContextCurriculumOrganisationValues(); setContextTaxonomyLevelValues(); setContextLocationValues(); @@ -263,7 +270,7 @@ public class FilterController extends FormBasicController { private void setTopicCurriculumElementValues() { if (!availableAttributes.isTopicCurriculumElement() || !curriculumModule.isEnabled()) { - contextCurriculumElementEl.setVisible(false); + topicCurriculumElementEl.setVisible(false); return; } @@ -330,7 +337,6 @@ public class FilterController extends FormBasicController { AnalysisSearchParameter curriculumSearchParams = searchParams.clone(); curriculumSearchParams.setContextCurriculumRefs(null); - curriculumSearchParams.setContextCurriculumElementRefs(null); List<Curriculum> curriculums = analysisService.loadContextCurriculums(curriculumSearchParams); KeysValues keysValues = QualityUIFactory.getCurriculumKeysValues(curriculums, null); contextCurriculumEl.setKeysAndValues(keysValues.getKeys(), keysValues.getValues()); @@ -345,7 +351,7 @@ public class FilterController extends FormBasicController { return; } - Collection<String> selectedKeys = contextCurriculumEl.getSelectedKeys(); + Collection<String> selectedKeys = contextCurriculumElementEl.getSelectedKeys(); AnalysisSearchParameter curriculumElementSearchParams = searchParams.clone(); Collection<String> curriculumKeys = contextCurriculumEl.isAtLeastSelected(1) @@ -367,6 +373,32 @@ public class FilterController extends FormBasicController { } } + private void setContextCurriculumElementTypeValues() { + if (!availableAttributes.isContextCurriculumElementType() || !curriculumModule.isEnabled()) { + contextCurriculumElementTypeEl.setVisible(false); + return; + } + + Collection<String> selectedKeys = contextCurriculumElementTypeEl.getSelectedKeys(); + + AnalysisSearchParameter clonedSearchParams = searchParams.clone(); + Collection<String> curriculumKeys = contextCurriculumEl.isAtLeastSelected(1) + ? contextCurriculumEl.getSelectedKeys() + : contextCurriculumEl.getKeys(); + List<? extends CurriculumRef> curriculumRefs = curriculumKeys.stream() + .map(key -> QualityUIFactory.getCurriculumRef(key)).collect(toList()); + clonedSearchParams.setContextCurriculumRefs(curriculumRefs); + clonedSearchParams.setContextCurriculumElementTypeRefs(null); + List<CurriculumElementType> curriculumElementTypes = analysisService + .loadContextCurriculumElementTypes(clonedSearchParams); + + KeysValues keysValues = QualityUIFactory.getCurriculumElementTypeKeysValues(curriculumElementTypes); + contextCurriculumElementTypeEl.setKeysAndValues(keysValues.getKeys(), keysValues.getValues()); + for (String key : selectedKeys) { + contextCurriculumElementEl.select(key, true); + } + } + private void setContextCurriculumOrganisationValues() { if (!availableAttributes.isContextCurriculumOrganisation() || !organisationModule.isEnabled() || !curriculumModule.isEnabled()) { @@ -380,6 +412,7 @@ public class FilterController extends FormBasicController { searchParamsClone.setContextCurriculumOrganisationRefs(null); searchParamsClone.setContextCurriculumRefs(null); searchParamsClone.setContextCurriculumElementRefs(null); + searchParamsClone.setContextCurriculumElementTypeRefs(null); List<Organisation> organisations = analysisService.loadContextCurriculumOrganisations(searchParamsClone, true); OrganisationTreeModel organisationModel = new OrganisationTreeModel(); organisationModel.loadTreeModel(organisations); @@ -521,6 +554,8 @@ public class FilterController extends FormBasicController { doFiltered(ureq); } else if (source == contextCurriculumElementEl) { doFiltered(ureq); + } else if (source == contextCurriculumElementTypeEl) { + doFiltered(ureq); } else if (source == contextCurriculumOrganisationEl) { doFiltered(ureq); } else if (source == contextTaxonomyLevelEl) { @@ -554,6 +589,7 @@ public class FilterController extends FormBasicController { getSearchParamContextExecutorOrganisations(); getSearchParamContextCurriculums(); getSearchParamContextCurriculumElements(); + getSearchParamContextCurriculumElementTypes(); getSearchParamContextCurriculumOrganisations(); getSearchParamContextTaxonomyLevels(); getSearchParamContextLocations(); @@ -665,6 +701,16 @@ public class FilterController extends FormBasicController { } } + private void getSearchParamContextCurriculumElementTypes() { + if (contextCurriculumElementTypeEl.isVisible() && contextCurriculumElementTypeEl.isAtLeastSelected(1)) { + List<CurriculumElementTypeRef> curriculumElementTypeRefs = contextCurriculumElementTypeEl.getSelectedKeys().stream() + .map(key -> QualityUIFactory.getCurriculumElementTypeRef(key)).collect(toList()); + searchParams.setContextCurriculumElementTypeRefs(curriculumElementTypeRefs); + } else { + searchParams.setContextCurriculumElementTypeRefs(null); + } + } + private void getSearchParamContextCurriculumOrganisations() { if (contextCurriculumOrganisationEl.isVisible() && contextCurriculumOrganisationEl.isAtLeastSelected(1)) { List<OrganisationRef> organisationRefs = contextCurriculumOrganisationEl.getSelectedKeys().stream() diff --git a/src/main/java/org/olat/modules/quality/analysis/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/quality/analysis/ui/_i18n/LocalStrings_de.properties index 34ddeefc55a..654262a7c17 100644 --- a/src/main/java/org/olat/modules/quality/analysis/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/quality/analysis/ui/_i18n/LocalStrings_de.properties @@ -8,6 +8,7 @@ analysis.table.form.created=Erstellt analysis.table.form.title=Fragebogen analysis.table.open=\u00D6ffnen analysis.table.participations.number=Teilnahmen +filter.context.curriculum.element.types=Typ Curriculumelement filter.context.curriculum.elements=Curriculumelement filter.context.curriculum.organisations=Organisation des Curriculum filter.context.curriculums=Curriculum diff --git a/src/main/java/org/olat/modules/quality/analysis/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/quality/analysis/ui/_i18n/LocalStrings_en.properties index 1ac42ca04db..99949e590de 100644 --- a/src/main/java/org/olat/modules/quality/analysis/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/quality/analysis/ui/_i18n/LocalStrings_en.properties @@ -8,6 +8,7 @@ analysis.table.form.created=Created analysis.table.form.title=Questionnaire analysis.table.open=Open analysis.table.participations.number=Participations +filter.context.curriculum.element.types=Type of curriculum element filter.context.curriculum.elements=Curriculum element filter.context.curriculum.organisations=Organisation of curriculum filter.context.curriculums=Curriculum diff --git a/src/main/java/org/olat/modules/quality/ui/QualityUIFactory.java b/src/main/java/org/olat/modules/quality/ui/QualityUIFactory.java index f0952b9b6b2..728bb09b468 100644 --- a/src/main/java/org/olat/modules/quality/ui/QualityUIFactory.java +++ b/src/main/java/org/olat/modules/quality/ui/QualityUIFactory.java @@ -54,9 +54,12 @@ import org.olat.core.util.nodes.INode; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumElement; import org.olat.modules.curriculum.CurriculumElementRef; +import org.olat.modules.curriculum.CurriculumElementType; +import org.olat.modules.curriculum.CurriculumElementTypeRef; import org.olat.modules.curriculum.CurriculumModule; import org.olat.modules.curriculum.CurriculumRef; import org.olat.modules.curriculum.model.CurriculumElementRefImpl; +import org.olat.modules.curriculum.model.CurriculumElementTypeRefImpl; import org.olat.modules.curriculum.model.CurriculumRefImpl; import org.olat.modules.curriculum.ui.CurriculumTreeModel; import org.olat.modules.quality.QualityDataCollectionTopicType; @@ -264,6 +267,29 @@ public class QualityUIFactory { return null; } + public static KeysValues getCurriculumElementTypeKeysValues(List<CurriculumElementType> types) { + String[] keys = new String[types.size()]; + String[] values = new String[types.size()]; + for (int i = types.size(); i-->0; ) { + CurriculumElementType type = types.get(i); + keys[i] = Long.toString(type.getKey()); + values[i] = type.getDisplayName(); + } + return new KeysValues(keys, values); + } + + public static CurriculumElementTypeRef getCurriculumElementTypeRef(String typeKey) { + if (StringHelper.containsNonWhitespace(typeKey)) { + try { + Long key = Long.valueOf(typeKey); + return new CurriculumElementTypeRefImpl(key); + } catch (Exception e) { + // + } + } + return null; + } + public static KeysValues getOrganisationFlatKeysValues(List<Organisation> organisations, Organisation current) { List<Organisation> orgs = new ArrayList<>(organisations); if (current != null && !orgs.contains(current)) { diff --git a/src/test/java/org/olat/modules/quality/analysis/manager/AnalysisFilterDAOTest.java b/src/test/java/org/olat/modules/quality/analysis/manager/AnalysisFilterDAOTest.java index 0f3f2c651d5..debdacc9b93 100644 --- a/src/test/java/org/olat/modules/quality/analysis/manager/AnalysisFilterDAOTest.java +++ b/src/test/java/org/olat/modules/quality/analysis/manager/AnalysisFilterDAOTest.java @@ -22,6 +22,7 @@ package org.olat.modules.quality.analysis.manager; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.olat.modules.curriculum.CurriculumCalendars.disabled; import static org.olat.modules.quality.analysis.GroupBy.CONTEXT_CURRICULUM; import static org.olat.modules.quality.analysis.GroupBy.CONTEXT_ORGANISATION; import static org.olat.modules.quality.analysis.GroupBy.CONTEXT_TAXONOMY_LEVEL; @@ -46,6 +47,7 @@ import org.olat.core.id.Organisation; import org.olat.modules.curriculum.Curriculum; import org.olat.modules.curriculum.CurriculumCalendars; import org.olat.modules.curriculum.CurriculumElement; +import org.olat.modules.curriculum.CurriculumElementType; import org.olat.modules.curriculum.CurriculumService; import org.olat.modules.forms.EvaluationFormManager; import org.olat.modules.forms.EvaluationFormParticipation; @@ -210,6 +212,7 @@ public class AnalysisFilterDAOTest extends OlatTestCase { assertThat(attributes.isContextExecutorOrganisation()).isFalse(); assertThat(attributes.isContextCurriculum()).isFalse(); assertThat(attributes.isContextCurriculumElement()).isFalse(); + assertThat(attributes.isContextCurriculumElementType()).isFalse(); assertThat(attributes.isContextCurriculumOrganisation()).isFalse(); assertThat(attributes.isContextTaxonomyLevel()).isFalse(); assertThat(attributes.isSeriesIndex()).isFalse(); @@ -359,6 +362,27 @@ public class AnalysisFilterDAOTest extends OlatTestCase { assertThat(attributes.isContextCurriculumElement()).isTrue(); } + @Test + public void shouldGetAvailableAttributeForContextCurriculumElementType() { + QualityDataCollection dataCollection = createFinishedDataCollection(); + Identity executor = JunitTestHelper.createAndPersistIdentityAsRndUser(""); + CurriculumElement element = qualityTestHelper.createCurriculumElement(); + CurriculumElementType type = curriculumService.createCurriculumElementType("t", "s", null, null); + element.setType(type); + element = curriculumService.updateCurriculumElement(element); + List<EvaluationFormParticipation> participations = qualityService.addParticipations(dataCollection, + singletonList(executor)); + qualityService.createContextBuilder(dataCollection, participations.get(0)) + .addCurriculumElement(element) + .build(); + dbInstance.commitAndCloseSession(); + + AnalysisSearchParameter searchParams = new AnalysisSearchParameter(); + AvailableAttributes attributes = sut.getAvailableAttributes(searchParams); + + assertThat(attributes.isContextCurriculumElementType()).isTrue(); + } + @Test public void shouldGetAvailableAttributeForContextCurriculumOrganisation() { QualityDataCollection dataCollection = createFinishedDataCollection(); @@ -768,6 +792,45 @@ public class AnalysisFilterDAOTest extends OlatTestCase { .containsExactlyInAnyOrder(element1.getCurriculum().getKey(), element2.getCurriculum().getKey()) .doesNotContainNull(); } + + @Test + public void shouldLoadDistinctContextCurriculumElementTypes() { + RepositoryEntry formEntry = JunitTestHelper.createAndPersistRepositoryEntry(); + Identity executor = JunitTestHelper.createAndPersistIdentityAsUser(""); + Organisation dcOrganisation = qualityTestHelper.createOrganisation(); + CurriculumElementType type1 = curriculumService.createCurriculumElementType("a", "b", null, null); + CurriculumElementType type2 = curriculumService.createCurriculumElementType("a", "b", null, null); + Curriculum curriculum = qualityTestHelper.createCurriculum(); + CurriculumElement element1 = curriculumService.createCurriculumElement("", "", null, null, null, type1, disabled, curriculum); + CurriculumElement element2 = curriculumService.createCurriculumElement("", "", null, null, null, type2, disabled, curriculum);; + // Participation with curriculum element of type1 + QualityDataCollection dc1 = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + List<EvaluationFormParticipation> participations1 = qualityService.addParticipations(dc1, Collections.singletonList(executor)); + QualityContextBuilder contextBuilder1 = qualityService.createContextBuilder(dc1, participations1.get(0)); + contextBuilder1.addCurriculumElement(element1).build(); + // Participation with curriculum element of type2 + QualityDataCollection dc2 = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + List<EvaluationFormParticipation> participations2 = qualityService.addParticipations(dc2, Collections.singletonList(executor)); + QualityContextBuilder contextBuilder2 = qualityService.createContextBuilder(dc2, participations2.get(0)); + contextBuilder2.addCurriculumElement(element2).build(); + // Second participation with curriculum element of type1 (to test distinct) + QualityDataCollection dcDistinct = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + List<EvaluationFormParticipation> participationsDistinct = qualityService.addParticipations(dcDistinct, Collections.singletonList(executor)); + QualityContextBuilder contextBuilderDistinct = qualityService.createContextBuilder(dcDistinct, participationsDistinct.get(0)); + contextBuilderDistinct.addCurriculumElement(element1).build(); + // Participation without curriculum (to test no nulls) + QualityDataCollection dcNull = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + qualityService.addParticipations(dcNull, Collections.singletonList(executor)); + finish(asList(dc1, dc2, dcDistinct, dcNull)); + dbInstance.commitAndCloseSession(); + + AnalysisSearchParameter searchParams = new AnalysisSearchParameter(); + List<CurriculumElementType> filtered = sut.loadContextCurriculumElementsTypes(searchParams); + + assertThat(filtered) + .containsExactlyInAnyOrder(type1, type2) + .doesNotContainNull(); + } @Test public void shouldLoadDistinctContextOrganisationPath() { @@ -1458,6 +1521,53 @@ public class AnalysisFilterDAOTest extends OlatTestCase { assertThat(count).isEqualTo(expected); } + @Test + public void shouldFilterByContextCurriculumElementTypes() { + RepositoryEntry formEntry = JunitTestHelper.createAndPersistRepositoryEntry(); + Identity executor = JunitTestHelper.createAndPersistIdentityAsUser(""); + Organisation dcOrganisation = qualityTestHelper.createOrganisation(); + CurriculumElementType type = curriculumService.createCurriculumElementType("a", "b", null, null); + CurriculumElementType typeOther = curriculumService.createCurriculumElementType("y", "z", null, null); + Curriculum curriculum = qualityTestHelper.createCurriculum(); + CurriculumElement element1 = curriculumService.createCurriculumElement("", "", null, null, null, type, disabled, curriculum); + CurriculumElement element2 = curriculumService.createCurriculumElement("", "", null, null, null, type, disabled, curriculum);; + CurriculumElement elementNull = curriculumService.createCurriculumElement("", "", null, null, null, null, disabled, curriculum); + CurriculumElement elementOther = curriculumService.createCurriculumElement("", "", null, null, null, typeOther, disabled, curriculum); + // Participation with curriculum element of type + QualityDataCollection dc1 = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + List<EvaluationFormParticipation> participations1 = qualityService.addParticipations(dc1, Collections.singletonList(executor)); + QualityContextBuilder contextBuilder1 = qualityService.createContextBuilder(dc1, participations1.get(0)); + contextBuilder1.addCurriculumElement(element1).build(); + // Participation with another curriculum element of type + QualityDataCollection dc2 = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + List<EvaluationFormParticipation> participations2 = qualityService.addParticipations(dc2, Collections.singletonList(executor)); + QualityContextBuilder contextBuilder2 = qualityService.createContextBuilder(dc2, participations2.get(0)); + contextBuilder2.addCurriculumElement(element2).build(); + // Participation with other curriculum element of other type + QualityDataCollection dcOther = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + List<EvaluationFormParticipation> participationsOther = qualityService.addParticipations(dcOther, Collections.singletonList(executor)); + QualityContextBuilder contextBuilderOther = qualityService.createContextBuilder(dcOther, participationsOther.get(0)); + contextBuilderOther.addCurriculumElement(elementOther).build(); + // Participation with curriculum element without type + QualityDataCollection dcTypeNull = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + List<EvaluationFormParticipation> participationsTypeNull = qualityService.addParticipations(dcTypeNull, Collections.singletonList(executor)); + QualityContextBuilder contextBuilderTypeNull = qualityService.createContextBuilder(dcTypeNull, participationsTypeNull.get(0)); + contextBuilderTypeNull.addCurriculumElement(elementNull).build(); + // Participation without curriculum + QualityDataCollection dcNull = qualityService.createDataCollection(asList(dcOrganisation), formEntry); + qualityService.addParticipations(dcNull, Collections.singletonList(executor)); + finish(asList(dc1, dc2, dcTypeNull, dcNull, dcOther)); + dbInstance.commitAndCloseSession(); + + AnalysisSearchParameter searchParams = new AnalysisSearchParameter(); + searchParams.setContextCurriculumElementTypeRefs(asList(type)); + List<QualityDataCollection> dataCollections = sut.loadDataCollection(searchParams); + + assertThat(dataCollections) + .containsExactlyInAnyOrder(dc1, dc2) + .doesNotContain(dcTypeNull, dcNull, dcOther); + } + @Test public void shouldFilterByContextCurriculumOrganisations() { RepositoryEntry formEntry = JunitTestHelper.createAndPersistRepositoryEntry(); -- GitLab