diff --git a/src/main/java/org/olat/course/assessment/UserEfficiencyStatement.java b/src/main/java/org/olat/course/assessment/UserEfficiencyStatement.java index 226ba10359ce0fddacc45e3f8b96d80d18a7cb3f..14333d671c9eb63ce73d324d06e315c713ed5076 100644 --- a/src/main/java/org/olat/course/assessment/UserEfficiencyStatement.java +++ b/src/main/java/org/olat/course/assessment/UserEfficiencyStatement.java @@ -25,39 +25,15 @@ package org.olat.course.assessment; -import java.util.Date; - import org.olat.core.id.Identity; /** * * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ -public interface UserEfficiencyStatement { - - public Long getKey(); +public interface UserEfficiencyStatement extends UserEfficiencyStatementShort { - public Identity getIdentity(); - - public Date getLastModified(); - - public Date getLastUserModified(); - - public Date getLastCoachModified(); - - public Date getCreationDate(); - - public Long getCourseRepoKey(); - - public String getShortTitle(); - - public Float getScore(); - - public Boolean getPassed(); - - public Integer getTotalNodes(); - public Integer getAttemptedNodes(); + public Identity getIdentity(); - public Integer getPassedNodes(); } diff --git a/src/main/java/org/olat/course/assessment/UserEfficiencyStatementShort.java b/src/main/java/org/olat/course/assessment/UserEfficiencyStatementShort.java new file mode 100644 index 0000000000000000000000000000000000000000..fd9d6d5326799c5852c81d98bd752d2c1ffbfb10 --- /dev/null +++ b/src/main/java/org/olat/course/assessment/UserEfficiencyStatementShort.java @@ -0,0 +1,55 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.assessment; + +import java.util.Date; + +/** + * + * Initial date: 24 juin 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +public interface UserEfficiencyStatementShort { + + public Long getKey(); + + public Date getLastModified(); + + public Date getLastUserModified(); + + public Date getLastCoachModified(); + + public Date getCreationDate(); + + public Long getCourseRepoKey(); + + public String getShortTitle(); + + public Float getScore(); + + public Boolean getPassed(); + + public Integer getTotalNodes(); + + public Integer getAttemptedNodes(); + + public Integer getPassedNodes(); +} diff --git a/src/main/java/org/olat/course/assessment/manager/EfficiencyStatementManager.java b/src/main/java/org/olat/course/assessment/manager/EfficiencyStatementManager.java index c7a37272f0d130b0d8a850ae09ca2eb3700294c7..aae901eead04143a32611e4a863db6f3203cc8b6 100644 --- a/src/main/java/org/olat/course/assessment/manager/EfficiencyStatementManager.java +++ b/src/main/java/org/olat/course/assessment/manager/EfficiencyStatementManager.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import org.olat.basesecurity.GroupRoles; import org.olat.basesecurity.IdentityRef; import org.olat.core.commons.persistence.DB; import org.olat.core.commons.persistence.DBFactory; @@ -56,12 +57,14 @@ import org.olat.course.assessment.EfficiencyStatement; import org.olat.course.assessment.UserEfficiencyStatement; import org.olat.course.assessment.model.AssessmentNodeData; import org.olat.course.assessment.model.AssessmentNodesLastModified; +import org.olat.course.assessment.model.UserEfficiencyStatementForCoaching; import org.olat.course.assessment.model.UserEfficiencyStatementImpl; import org.olat.course.assessment.model.UserEfficiencyStatementLight; import org.olat.course.assessment.model.UserEfficiencyStatementStandalone; import org.olat.course.config.CourseConfig; import org.olat.course.run.environment.CourseEnvironment; import org.olat.course.run.userview.UserCourseEnvironment; +import org.olat.group.BusinessGroup; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryEntryRef; import org.olat.repository.model.RepositoryEntryRefImpl; @@ -455,38 +458,29 @@ public class EfficiencyStatementManager implements UserDataDeletable, UserDataEx .getResultList(); } - public List<UserEfficiencyStatement> getUserEfficiencyStatementLight(RepositoryEntry course) { - if(course == null) { - return Collections.emptyList(); - } + public List<UserEfficiencyStatementForCoaching> getUserEfficiencyStatementForCoaching(RepositoryEntry course) { + if(course == null) return Collections.emptyList(); - StringBuilder sb = new StringBuilder(); - sb.append("select statement from effstatementlight as statement") - .append(" inner join fetch statement.resource as resource") - .append(" where resource.key=:resourcesKey"); + Long resourceKey = course.getOlatResource().getKey(); + return dbInstance.getCurrentEntityManager() - .createQuery(sb.toString(), UserEfficiencyStatement.class) - .setParameter("resourcesKey",course.getOlatResource().getKey()) + .createNamedQuery("efficiencyStatemtForCoachingByResourceKeys", UserEfficiencyStatementForCoaching.class) + .setParameter("courseResourceKey", resourceKey) .getResultList(); } - public List<UserEfficiencyStatement> getUserEfficiencyStatementLight(List<RepositoryEntry> courses) { - if(courses == null || courses.isEmpty()) { - return Collections.emptyList(); - } - - List<Long> resourcesKey = new ArrayList<>(); - for(RepositoryEntry course:courses) { - resourcesKey.add(course.getOlatResource().getKey()); - } - - StringBuilder sb = new StringBuilder(); - sb.append("select statement from effstatementlight as statement ") - .append(" inner join fetch statement.resource as resource") - .append(" where resource.key in (:courseResourcesKey)"); + public List<UserEfficiencyStatementForCoaching> getUserEfficiencyStatementForCoaching(BusinessGroup group) { + StringBuilder sb = new StringBuilder(512); + sb.append("select distinct statement from effstatementcoaching as statement") + .append(" inner join repositoryentry as v on (v.olatResource.key=statement.resourceKey)") + .append(" inner join v.groups as relGroup ") + .append(" inner join relGroup.group as baseGroup") + .append(" inner join baseGroup.members as membership on membership.role='").append(GroupRoles.participant.name()).append("'") + .append(" where baseGroup.key=:bGroupKey and statement.identityKey=membership.identity.key"); + return dbInstance.getCurrentEntityManager() - .createQuery(sb.toString(), UserEfficiencyStatement.class) - .setParameter("courseResourcesKey", resourcesKey) + .createQuery(sb.toString(), UserEfficiencyStatementForCoaching.class) + .setParameter("bGroupKey", group.getBaseGroup().getKey()) .getResultList(); } @@ -507,15 +501,13 @@ public class EfficiencyStatementManager implements UserDataDeletable, UserDataEx } public EfficiencyStatement getUserEfficiencyStatementByKey(Long key) { - StringBuilder sb = new StringBuilder(); - sb.append("select statement from effstatement as statement ") - .append(" where statement.key=:key"); + String query = "select statement from effstatement as statement where statement.key=:key"; List<UserEfficiencyStatementImpl> statement = dbInstance.getCurrentEntityManager() - .createQuery(sb.toString(), UserEfficiencyStatementImpl.class) + .createQuery(query, UserEfficiencyStatementImpl.class) .setParameter("key", key) .getResultList(); - if(statement.isEmpty()) { + if(statement.isEmpty() || !StringHelper.containsNonWhitespace(statement.get(0).getStatementXml())) { return null; } return (EfficiencyStatement)xstream.fromXML(statement.get(0).getStatementXml()); diff --git a/src/main/java/org/olat/course/assessment/model/UserEfficiencyStatementForCoaching.java b/src/main/java/org/olat/course/assessment/model/UserEfficiencyStatementForCoaching.java new file mode 100644 index 0000000000000000000000000000000000000000..cf10295d3c993861271265849d17d0f6575ed7db --- /dev/null +++ b/src/main/java/org/olat/course/assessment/model/UserEfficiencyStatementForCoaching.java @@ -0,0 +1,257 @@ +/** + * <a href="http://www.openolat.org"> + * OpenOLAT - Online Learning and Training</a><br> + * <p> + * Licensed under the Apache License, Version 2.0 (the "License"); <br> + * you may not use this file except in compliance with the License.<br> + * You may obtain a copy of the License at the + * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> + * <p> + * Unless required by applicable law or agreed to in writing,<br> + * software distributed under the License is distributed on an "AS IS" BASIS, <br> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> + * See the License for the specific language governing permissions and <br> + * limitations under the License. + * <p> + * Initial code contributed and copyrighted by<br> + * frentix GmbH, http://www.frentix.com + * <p> + */ +package org.olat.course.assessment.model; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.NamedQuery; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.Version; + +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Parameter; +import org.olat.core.id.ModifiedInfo; +import org.olat.core.id.Persistable; +import org.olat.course.assessment.UserEfficiencyStatementShort; + +/** + * This is a reduced version of the user efficiency statement with only + * the prmiray keys to identity and OLAT resource. All fields are flags + * as read only. + * + * Initial date: 24 juin 2019<br> + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com + * + */ +@Entity(name="effstatementcoaching") +@Table(name="o_as_eff_statement") +@NamedQuery(name="efficiencyStatemtForCoachingByResourceKeys", query="select statement from effstatementcoaching as statement where resourceKey=:courseResourceKey") +public class UserEfficiencyStatementForCoaching implements Persistable, UserEfficiencyStatementShort, ModifiedInfo { + + private static final long serialVersionUID = 2996458434418813284L; + + @Id + @GeneratedValue(generator = "system-uuid") + @GenericGenerator(name = "system-uuid", strategy = "enhanced-sequence", parameters={ + @Parameter(name="sequence_name", value="hibernate_unique_key"), + @Parameter(name="force_table_use", value="true"), + @Parameter(name="optimizer", value="legacy-hilo"), + @Parameter(name="value_column", value="next_hi"), + @Parameter(name="increment_size", value="32767"), + @Parameter(name="initial_value", value="32767") + }) + @Column(name="id", nullable=false, unique=true, insertable=true, updatable=false) + private Long key; + @Version + private int version = 0; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="creationdate", nullable=false, insertable=false, updatable=false) + private Date creationDate; + @Temporal(TemporalType.TIMESTAMP) + @Column(name="lastmodified", nullable=false, insertable=false, updatable=false) + private Date lastModified; + + @Column(name="score", nullable=true, insertable=false, updatable=false) + private Float score; + @Column(name="passed", nullable=true, insertable=false, updatable=false) + private Boolean passed; + @Column(name="total_nodes", nullable=true, insertable=false, updatable=false) + private Integer totalNodes; + @Column(name="attempted_nodes", nullable=true, insertable=true, updatable=true) + private Integer attemptedNodes; + @Column(name="passed_nodes", nullable=true, insertable=false, updatable=false) + private Integer passedNodes; + + @Column(name="course_short_title", nullable=true, insertable=false, updatable=false) + private String shortTitle; + @Column(name="course_repo_key", nullable=true, insertable=false, updatable=false) + private Long courseRepoKey; + + @Temporal(TemporalType.TIMESTAMP) + @Column(name="lastusermodified", nullable=true, insertable=false, updatable=false) + private Date lastUserModified; + @Temporal(TemporalType.TIMESTAMP) + @Column(name="lastcoachmodified", nullable=true, insertable=false, updatable=false) + private Date lastCoachModified; + + @Column(name="fk_identity", nullable=false, insertable=false, updatable=false) + private Long identityKey; + @Column(name="fk_resource_id", nullable=true, insertable=false, updatable=false) + private Long resourceKey; + + @Override + public Long getKey() { + return key; + } + + public void setKey(Long key) { + this.key = key; + } + + @Override + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + + @Override + public Date getLastModified() { + return lastModified; + } + + @Override + public void setLastModified(Date lastModified) { + this.lastModified = lastModified; + } + + @Override + public Date getLastUserModified() { + return lastUserModified; + } + + public void setLastUserModified(Date lastUserModified) { + this.lastUserModified = lastUserModified; + } + + @Override + public Date getLastCoachModified() { + return lastCoachModified; + } + + public void setLastCoachModified(Date lastCoachModified) { + this.lastCoachModified = lastCoachModified; + } + + @Override + public Float getScore() { + 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 Integer getTotalNodes() { + return totalNodes; + } + + public void setTotalNodes(Integer totalNodes) { + this.totalNodes = totalNodes; + } + + @Override + public Integer getAttemptedNodes() { + return attemptedNodes; + } + + public void setAttemptedNodes(Integer attemptedNodes) { + this.attemptedNodes = attemptedNodes; + } + + @Override + public Integer getPassedNodes() { + return passedNodes; + } + + public void setPassedNodes(Integer passedNodes) { + this.passedNodes = passedNodes; + } + + public Long getIdentityKey() { + return identityKey; + } + + public void setIdentityKey(Long identityKey) { + this.identityKey = identityKey; + } + + public Long getResourceKey() { + return resourceKey; + } + + public void setResourceKey(Long resourceKey) { + this.resourceKey = resourceKey; + } + + @Override + public String getShortTitle() { + return shortTitle; + } + + public void setShortTitle(String shortTitle) { + this.shortTitle = shortTitle; + } + + @Override + public Long getCourseRepoKey() { + return courseRepoKey; + } + + public void setCourseRepoKey(Long courseRepoKey) { + this.courseRepoKey = courseRepoKey; + } + + @Override + public String toString() { + return super.toString(); + } + + @Override + public int hashCode() { + return getKey() == null ? -82654 : getKey().hashCode(); + } + + @Override + public boolean equals(Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof UserEfficiencyStatementForCoaching) { + UserEfficiencyStatementForCoaching statement = (UserEfficiencyStatementForCoaching)obj; + return getKey() != null && getKey().equals(statement.getKey()); + } + return false; + } + + @Override + public boolean equalsByPersistableKey(Persistable persistable) { + return equals(persistable); + } +} diff --git a/src/main/java/org/olat/modules/coach/manager/CoachingServiceImpl.java b/src/main/java/org/olat/modules/coach/manager/CoachingServiceImpl.java index bdbe07e5d875e26b6e64dc459bfbeeacb6fc547b..189f039b65e3dc8b196a095105119891c94b6802 100644 --- a/src/main/java/org/olat/modules/coach/manager/CoachingServiceImpl.java +++ b/src/main/java/org/olat/modules/coach/manager/CoachingServiceImpl.java @@ -30,6 +30,7 @@ import org.olat.basesecurity.GroupRoles; import org.olat.core.id.Identity; import org.olat.course.assessment.UserEfficiencyStatement; import org.olat.course.assessment.manager.EfficiencyStatementManager; +import org.olat.course.assessment.model.UserEfficiencyStatementForCoaching; import org.olat.group.BusinessGroup; import org.olat.group.BusinessGroupService; import org.olat.modules.coach.CoachingService; @@ -101,11 +102,11 @@ public class CoachingServiceImpl implements CoachingService { public List<EfficiencyStatementEntry> getGroup(BusinessGroup group, List<UserPropertyHandler> userPropertyHandlers, Locale locale) { List<Identity> students = businessGroupService.getMembers(group, GroupRoles.participant.name()); List<RepositoryEntry> courses = businessGroupService.findRepositoryEntries(Collections.singletonList(group), 0, -1); - List<UserEfficiencyStatement> statements = efficiencyStatementManager.getUserEfficiencyStatementLight(courses); + List<UserEfficiencyStatementForCoaching> statements = efficiencyStatementManager.getUserEfficiencyStatementForCoaching(group); - Map<IdentityRepositoryEntryKey,UserEfficiencyStatement> identityToStatements = new HashMap<>(); - for(UserEfficiencyStatement statement:statements) { - IdentityRepositoryEntryKey key = new IdentityRepositoryEntryKey(statement.getIdentity().getKey(), statement.getCourseRepoKey()); + Map<IdentityRepositoryEntryKey,UserEfficiencyStatementForCoaching> identityToStatements = new HashMap<>(); + for(UserEfficiencyStatementForCoaching statement:statements) { + IdentityRepositoryEntryKey key = new IdentityRepositoryEntryKey(statement.getIdentityKey(), statement.getCourseRepoKey()); identityToStatements.put(key, statement); } @@ -113,7 +114,7 @@ public class CoachingServiceImpl implements CoachingService { for(RepositoryEntry course:courses) { for(Identity student:students) { IdentityRepositoryEntryKey key = new IdentityRepositoryEntryKey(student.getKey(), course.getKey()); - UserEfficiencyStatement statement = identityToStatements.get(key); + UserEfficiencyStatementForCoaching statement = identityToStatements.get(key); entries.add(new EfficiencyStatementEntry(student, course, statement, userPropertyHandlers, locale)); } } @@ -124,15 +125,15 @@ public class CoachingServiceImpl implements CoachingService { public List<EfficiencyStatementEntry> getCourse(Identity coach, RepositoryEntry entry, List<UserPropertyHandler> userPropertyHandlers, Locale locale) { List<Identity> students = coachingDao.getStudents(coach, entry); - List<UserEfficiencyStatement> statements = efficiencyStatementManager.getUserEfficiencyStatementLight(entry); - Map<Identity,UserEfficiencyStatement> identityToStatements = new HashMap<>(); - for(UserEfficiencyStatement statement:statements) { - identityToStatements.put(statement.getIdentity(), statement); + List<UserEfficiencyStatementForCoaching> statements = efficiencyStatementManager.getUserEfficiencyStatementForCoaching(entry); + Map<Long,UserEfficiencyStatementForCoaching> identityToStatements = new HashMap<>(); + for(UserEfficiencyStatementForCoaching statement:statements) { + identityToStatements.put(statement.getIdentityKey(), statement); } List<EfficiencyStatementEntry> entries = new ArrayList<>(students.size()); for(Identity student:students) { - UserEfficiencyStatement statement = identityToStatements.get(student); + UserEfficiencyStatementForCoaching statement = identityToStatements.get(student.getKey()); entries.add(new EfficiencyStatementEntry(student, entry, statement, userPropertyHandlers, locale)); } return entries; diff --git a/src/main/java/org/olat/modules/coach/model/EfficiencyStatementEntry.java b/src/main/java/org/olat/modules/coach/model/EfficiencyStatementEntry.java index d6d40c63c8ebb3a269ec58d8ee27af2f77e66535..1a36e550e649a2a99a48b05f471beacd43573c50 100644 --- a/src/main/java/org/olat/modules/coach/model/EfficiencyStatementEntry.java +++ b/src/main/java/org/olat/modules/coach/model/EfficiencyStatementEntry.java @@ -19,11 +19,12 @@ */ package org.olat.modules.coach.model; +import java.util.Date; import java.util.List; import java.util.Locale; import org.olat.core.id.Identity; -import org.olat.course.assessment.UserEfficiencyStatement; +import org.olat.course.assessment.UserEfficiencyStatementShort; import org.olat.repository.RepositoryEntry; import org.olat.user.UserPropertiesRow; import org.olat.user.propertyhandlers.UserPropertyHandler; @@ -40,14 +41,40 @@ import org.olat.user.propertyhandlers.UserPropertyHandler; public class EfficiencyStatementEntry extends UserPropertiesRow { private final RepositoryEntry course; - private final UserEfficiencyStatement efficencyStatement; - public EfficiencyStatementEntry(Identity student, RepositoryEntry course, UserEfficiencyStatement efficencyStatement, + private final Long efficiencyStatementKey; + private final Float score; + private final Boolean passed; + private final Integer totalNodes; + private final Integer attemptedNodes; + private final Date lastModified; + private final Date lastUserModified; + private final Date lastCoachModified; + + public EfficiencyStatementEntry(Identity student, RepositoryEntry course, UserEfficiencyStatementShort efficiencyStatement, List<UserPropertyHandler> userPropertyHandlers, Locale locale) { super(student, userPropertyHandlers, locale); this.course = course; - this.efficencyStatement = efficencyStatement; + if(efficiencyStatement == null) { + passed = null; + score = null; + totalNodes = null; + attemptedNodes = null; + lastModified = null; + lastUserModified = null; + lastCoachModified = null; + efficiencyStatementKey = null; + } else { + efficiencyStatementKey = efficiencyStatement.getKey(); + passed = efficiencyStatement.getPassed(); + score = efficiencyStatement.getScore(); + totalNodes = efficiencyStatement.getTotalNodes(); + attemptedNodes = efficiencyStatement.getAttemptedNodes(); + lastModified = efficiencyStatement.getLastModified(); + lastUserModified = efficiencyStatement.getLastUserModified(); + lastCoachModified = efficiencyStatement.getLastCoachModified(); + } } public String getCourseDisplayName() { @@ -58,11 +85,35 @@ public class EfficiencyStatementEntry extends UserPropertiesRow { return course; } - /** - * Can return null - * @return - */ - public UserEfficiencyStatement getUserEfficencyStatement() { - return efficencyStatement; + public Long getUserEfficiencyStatementKey() { + return efficiencyStatementKey; + } + + public Float getScore() { + return score; + } + + public Boolean getPassed() { + return passed; + } + + public Integer getTotalNodes() { + return totalNodes; + } + + public Integer getAttemptedNodes() { + return attemptedNodes; + } + + public Date getLastModified() { + return lastModified; + } + + public Date getLastUserModified() { + return lastUserModified; + } + + public Date getLastCoachModified() { + return lastCoachModified; } } diff --git a/src/main/java/org/olat/modules/coach/ui/EfficiencyStatementEntryTableDataModel.java b/src/main/java/org/olat/modules/coach/ui/EfficiencyStatementEntryTableDataModel.java index 57047cbf8e62892c5356ef597665faa9b721ced8..020ce505b8f7aba5be179d5822ff91d440bb7fdd 100644 --- a/src/main/java/org/olat/modules/coach/ui/EfficiencyStatementEntryTableDataModel.java +++ b/src/main/java/org/olat/modules/coach/ui/EfficiencyStatementEntryTableDataModel.java @@ -28,7 +28,6 @@ import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiSorta import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableDataModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.SortableFlexiTableModelDelegate; -import org.olat.course.assessment.UserEfficiencyStatement; import org.olat.course.certificate.CertificateLight; import org.olat.modules.coach.model.EfficiencyStatementEntry; import org.olat.modules.coach.model.IdentityRepositoryEntryKey; @@ -85,25 +84,16 @@ public class EfficiencyStatementEntryTableDataModel extends DefaultFlexiTableDat RepositoryEntry re = entry.getCourse(); return re.getDisplayname(); } - case score: { - UserEfficiencyStatement s = entry.getUserEfficencyStatement(); - return s == null ? null : s.getScore(); - } - case passed: { - UserEfficiencyStatement s = entry.getUserEfficencyStatement(); - return s == null ? null : s.getPassed(); - } - case certificate: { - CertificateLight certificate = getCertificate(entry); - return certificate; - } + case score: return entry.getScore(); + case passed: return entry.getPassed(); + case certificate: return getCertificate(entry); case recertification: { CertificateLight certificate = getCertificate(entry); return certificate == null ? null : certificate.getNextRecertificationDate(); } case progress: { - UserEfficiencyStatement s = entry.getUserEfficencyStatement(); - if(s == null || s.getTotalNodes() == null) { + Integer totalNodes = entry.getTotalNodes(); + if(totalNodes == null) { ProgressValue val = new ProgressValue(); val.setTotal(100); val.setGreen(0); @@ -111,22 +101,14 @@ public class EfficiencyStatementEntryTableDataModel extends DefaultFlexiTableDat } ProgressValue val = new ProgressValue(); - val.setTotal(s.getTotalNodes().intValue()); - val.setGreen(s.getAttemptedNodes() == null ? 0 : s.getAttemptedNodes().intValue()); + val.setTotal(totalNodes.intValue()); + Integer attemptedNodes = entry.getAttemptedNodes(); + val.setGreen(attemptedNodes == null ? 0 : attemptedNodes.intValue()); return val; } - case lastModification: { - UserEfficiencyStatement s = entry.getUserEfficencyStatement(); - return s == null ? null : s.getLastModified(); - } - case lastUserModified: { - UserEfficiencyStatement s = entry.getUserEfficencyStatement(); - return s == null ? null : s.getLastUserModified(); - } - case lastCoachModified: { - UserEfficiencyStatement s = entry.getUserEfficencyStatement(); - return s == null ? null : s.getLastCoachModified(); - } + case lastModification: return entry.getLastModified(); + case lastUserModified: return entry.getLastUserModified(); + case lastCoachModified: return entry.getLastCoachModified(); case plannedLectures: { LectureBlockStatistics statistics = getLectureBlockStatistics(entry); return statistics == null ? null : statistics.getTotalPersonalPlannedLectures(); diff --git a/src/main/java/org/olat/modules/coach/ui/UserDetailsController.java b/src/main/java/org/olat/modules/coach/ui/UserDetailsController.java index e85982c001bcbe480543a5695b32ca36a14f9b2c..f5941eb65ecdf5e78d80bd89733c62a41f887ef2 100644 --- a/src/main/java/org/olat/modules/coach/ui/UserDetailsController.java +++ b/src/main/java/org/olat/modules/coach/ui/UserDetailsController.java @@ -44,7 +44,6 @@ import org.olat.core.id.context.StateEntry; import org.olat.core.util.StringHelper; import org.olat.course.CorruptedCourseException; import org.olat.course.assessment.EfficiencyStatement; -import org.olat.course.assessment.UserEfficiencyStatement; import org.olat.course.assessment.manager.EfficiencyStatementManager; import org.olat.course.assessment.ui.tool.AssessmentIdentityCourseController; import org.olat.course.certificate.ui.CertificateAndEfficiencyStatementController; @@ -242,9 +241,12 @@ public class UserDetailsController extends BasicController implements Activateab removeAsListenerAndDispose(statementCtrl); RepositoryEntry entry = statementEntry.getCourse(); - UserEfficiencyStatement statement = statementEntry.getUserEfficencyStatement(); + Long statementKey = statementEntry.getUserEfficiencyStatementKey(); EfficiencyStatement efficiencyStatement = null; - if(statement != null) { + if(statementKey != null) { + efficiencyStatement = efficiencyStatementManager.getUserEfficiencyStatementByKey(statementKey); + } + if(efficiencyStatement == null) { RepositoryEntry re = statementEntry.getCourse(); efficiencyStatement = efficiencyStatementManager.getUserEfficiencyStatementByCourseRepositoryEntry(re, assessedIdentity); } diff --git a/src/main/resources/META-INF/persistence.xml b/src/main/resources/META-INF/persistence.xml index 7b85a3db27e9513f0f40ff973b663805400f10a2..1909ea617bca1fb941a5a7a86fee4faf28ac209a 100644 --- a/src/main/resources/META-INF/persistence.xml +++ b/src/main/resources/META-INF/persistence.xml @@ -99,6 +99,7 @@ <class>org.olat.course.assessment.model.UserEfficiencyStatementImpl</class> <class>org.olat.course.assessment.model.UserEfficiencyStatementLight</class> <class>org.olat.course.assessment.model.UserEfficiencyStatementStandalone</class> + <class>org.olat.course.assessment.model.UserEfficiencyStatementForCoaching</class> <class>org.olat.course.nodes.cl.model.DBCheckbox</class> <class>org.olat.course.nodes.cl.model.DBCheck</class> <class>org.olat.course.nodes.dialog.model.DialogElementImpl</class> diff --git a/src/test/java/org/olat/course/assessment/manager/EfficiencyStatementManagerTest.java b/src/test/java/org/olat/course/assessment/manager/EfficiencyStatementManagerTest.java index e12aba70ca203fe1d182f5d967f77aff72c28ddb..2ed9ee85d62fc0a8f88a43406fc017103a5114f6 100644 --- a/src/test/java/org/olat/course/assessment/manager/EfficiencyStatementManagerTest.java +++ b/src/test/java/org/olat/course/assessment/manager/EfficiencyStatementManagerTest.java @@ -21,21 +21,28 @@ package org.olat.course.assessment.manager; import java.net.URISyntaxException; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; +import java.util.stream.Collectors; import org.junit.Assert; import org.junit.Test; import org.olat.basesecurity.GroupRoles; import org.olat.core.commons.persistence.DB; import org.olat.core.id.Identity; +import org.olat.core.id.Roles; +import org.olat.core.util.mail.MailPackage; import org.olat.course.CourseFactory; import org.olat.course.ICourse; import org.olat.course.assessment.EfficiencyStatement; import org.olat.course.assessment.UserEfficiencyStatement; +import org.olat.course.assessment.model.UserEfficiencyStatementForCoaching; import org.olat.course.assessment.model.UserEfficiencyStatementImpl; import org.olat.course.assessment.model.UserEfficiencyStatementLight; +import org.olat.group.BusinessGroup; +import org.olat.group.BusinessGroupService; import org.olat.modules.coach.CoachingLargeTest; import org.olat.repository.RepositoryEntry; import org.olat.repository.RepositoryService; @@ -57,6 +64,8 @@ public class EfficiencyStatementManagerTest extends OlatTestCase { private RepositoryService repositoryService; @Autowired private EfficiencyStatementManager effManager; + @Autowired + private BusinessGroupService businessGroupService; /** * Create and reload an efficiency statement. @@ -250,7 +259,7 @@ public class EfficiencyStatementManagerTest extends OlatTestCase { } @Test - public void getUserEfficiencyStatementLight_repo() throws URISyntaxException { + public void getUserEfficiencyStatementForCoaching_repo() throws URISyntaxException { RepositoryEntry re = deployTestcourse(); //add some members @@ -262,18 +271,18 @@ public class EfficiencyStatementManagerTest extends OlatTestCase { UserEfficiencyStatement statement = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participant, re.getOlatResource()); dbInstance.commitAndCloseSession(); - List<UserEfficiencyStatement> lightStatements = effManager.getUserEfficiencyStatementLight(re); + List<UserEfficiencyStatementForCoaching> lightStatements = effManager.getUserEfficiencyStatementForCoaching(re); Assert.assertNotNull(lightStatements); Assert.assertEquals(1, lightStatements.size()); - UserEfficiencyStatement lightStatement = lightStatements.get(0); + UserEfficiencyStatementForCoaching lightStatement = lightStatements.get(0); Assert.assertNotNull(lightStatement); Assert.assertEquals(statement.getKey(), lightStatement.getKey()); - Assert.assertEquals(participant, lightStatement.getIdentity()); + Assert.assertEquals(participant.getKey(), lightStatement.getIdentityKey()); Assert.assertEquals(re.getKey(), lightStatement.getCourseRepoKey()); } @Test - public void getUserEfficiencyStatementLight_repos() throws URISyntaxException { + public void getUserEfficiencyStatementForCoaching_repos() throws URISyntaxException { RepositoryEntry re = deployTestcourse(); //add some members @@ -285,16 +294,139 @@ public class EfficiencyStatementManagerTest extends OlatTestCase { UserEfficiencyStatement statement = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participant, re.getOlatResource()); dbInstance.commitAndCloseSession(); - List<UserEfficiencyStatement> lightStatements = effManager.getUserEfficiencyStatementLight(Collections.singletonList(re)); + List<UserEfficiencyStatementForCoaching> lightStatements = effManager.getUserEfficiencyStatementForCoaching(re); Assert.assertNotNull(lightStatements); Assert.assertEquals(1, lightStatements.size()); - UserEfficiencyStatement lightStatement = lightStatements.get(0); + UserEfficiencyStatementForCoaching lightStatement = lightStatements.get(0); Assert.assertNotNull(lightStatement); Assert.assertEquals(statement.getKey(), lightStatement.getKey()); - Assert.assertEquals(participant, lightStatement.getIdentity()); + Assert.assertEquals(participant.getKey(), lightStatement.getIdentityKey()); Assert.assertEquals(re.getKey(), lightStatement.getCourseRepoKey()); } + @Test + public void getUserEfficiencyStatementForCoaching_group() throws URISyntaxException { + RepositoryEntry re1 = deployTestcourse(); + RepositoryEntry re2 = deployTestcourse(); + + //add some members + Identity author = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7o"); + Identity participantRe = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7"); + repositoryService.addRole(participantRe, re1, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + BusinessGroup group = businessGroupService + .createBusinessGroup(author, "gcoach", "Group coaching", null, null, 0, 15, false, false, re1); + businessGroupService.addResourceTo(group, re2); + + Identity participantGrp1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7a"); + Identity participantGrp2 = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7b"); + Identity participantGrp3 = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7c"); + + List<Identity> participantsGroup = new ArrayList<>(); + participantsGroup.add(participantGrp1); + participantsGroup.add(participantGrp2); + participantsGroup.add(participantGrp3); + businessGroupService.addParticipants(author, Roles.administratorRoles(), participantsGroup, group, new MailPackage(false)); + dbInstance.commitAndCloseSession(); + + //make statements + UserEfficiencyStatement statement1 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantRe, re1.getOlatResource()); + UserEfficiencyStatement statement2 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp1, re1.getOlatResource()); + UserEfficiencyStatement statement3 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp2, re1.getOlatResource()); + UserEfficiencyStatement statement4 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp3, re1.getOlatResource()); + UserEfficiencyStatement statement5 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp1, re2.getOlatResource()); + dbInstance.commitAndCloseSession(); + + List<UserEfficiencyStatementForCoaching> lightStatements = effManager.getUserEfficiencyStatementForCoaching(group); + Assert.assertNotNull(lightStatements); + Assert.assertEquals(4, lightStatements.size()); + List<Long> lightStatementKeys = lightStatements.stream() + .map(UserEfficiencyStatementForCoaching::getKey) + .collect(Collectors.toList()); + Assert.assertFalse(lightStatementKeys.contains(statement1.getKey())); + Assert.assertTrue(lightStatementKeys.contains(statement2.getKey())); + Assert.assertTrue(lightStatementKeys.contains(statement3.getKey())); + Assert.assertTrue(lightStatementKeys.contains(statement4.getKey())); + Assert.assertTrue(lightStatementKeys.contains(statement5.getKey())); + } + + /** + * Test with 2 courses and 2 groups with people as participants across + * courses and groups. + * + * @throws URISyntaxException + */ + @Test + public void getUserEfficiencyStatementForCoaching_group_complex() throws URISyntaxException { + RepositoryEntry re1 = deployTestcourse(); + RepositoryEntry re2 = deployTestcourse(); + + //add some members + Identity author = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7o"); + Identity participantRe = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7"); + repositoryService.addRole(participantRe, re1, GroupRoles.participant.name()); + dbInstance.commitAndCloseSession(); + + BusinessGroup group1 = businessGroupService + .createBusinessGroup(author, "gcoach-1", "Group coaching", null, null, 0, 15, false, false, re1); + businessGroupService.addResourceTo(group1, re2); + + BusinessGroup group2 = businessGroupService + .createBusinessGroup(author, "gcoach-2", "Group coaching", null, null, 0, 15, false, false, re1); + businessGroupService.addResourceTo(group2, re2); + + Identity participantGrp1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7a"); + Identity participantGrp2 = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7b"); + Identity participantGrp3 = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7c"); + + List<Identity> participantsGroup1 = new ArrayList<>(); + participantsGroup1.add(participantGrp1); + participantsGroup1.add(participantGrp2); + participantsGroup1.add(participantGrp3); + businessGroupService.addParticipants(author, Roles.administratorRoles(), participantsGroup1, group1, new MailPackage(false)); + + Identity participantGrp4 = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7a"); + Identity participantGrp5 = JunitTestHelper.createAndPersistIdentityAsRndUser("Eff-Part-7b"); + + List<Identity> participantsGroup2 = new ArrayList<>(); + participantsGroup2.add(participantGrp1); + participantsGroup2.add(participantGrp4); + participantsGroup2.add(participantGrp5); + businessGroupService.addParticipants(author, Roles.administratorRoles(), participantsGroup2, group2, new MailPackage(false)); + + dbInstance.commitAndCloseSession(); + + //make statements + UserEfficiencyStatement statement1 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantRe, re1.getOlatResource()); + UserEfficiencyStatement statement2 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp1, re1.getOlatResource()); + UserEfficiencyStatement statement3 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp2, re1.getOlatResource()); + UserEfficiencyStatement statement4 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp3, re1.getOlatResource()); + UserEfficiencyStatement statement5 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp1, re2.getOlatResource()); + // noise + UserEfficiencyStatement statement6 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp4, re1.getOlatResource()); + UserEfficiencyStatement statement7 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp5, re1.getOlatResource()); + UserEfficiencyStatement statement8 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp4, re2.getOlatResource()); + UserEfficiencyStatement statement9 = effManager.createUserEfficiencyStatement(new Date(), 3.75f, false, participantGrp5, re2.getOlatResource()); + dbInstance.commitAndCloseSession(); + + List<UserEfficiencyStatementForCoaching> lightStatements = effManager.getUserEfficiencyStatementForCoaching(group1); + Assert.assertNotNull(lightStatements); + Assert.assertEquals(4, lightStatements.size()); + List<Long> lightStatementKeys = lightStatements.stream() + .map(UserEfficiencyStatementForCoaching::getKey) + .collect(Collectors.toList()); + Assert.assertFalse(lightStatementKeys.contains(statement1.getKey())); + Assert.assertTrue(lightStatementKeys.contains(statement2.getKey())); + Assert.assertTrue(lightStatementKeys.contains(statement3.getKey())); + Assert.assertTrue(lightStatementKeys.contains(statement4.getKey())); + Assert.assertTrue(lightStatementKeys.contains(statement5.getKey())); + Assert.assertFalse(lightStatementKeys.contains(statement6.getKey())); + Assert.assertFalse(lightStatementKeys.contains(statement7.getKey())); + Assert.assertFalse(lightStatementKeys.contains(statement8.getKey())); + Assert.assertFalse(lightStatementKeys.contains(statement9.getKey())); + } + @Test public void getUserEfficiencyStatementLightByResource() throws URISyntaxException { RepositoryEntry re = deployTestcourse();