From 93e941e2079e5bb109211ada9fe1a53fdef8635f Mon Sep 17 00:00:00 2001
From: srosse <none@none>
Date: Mon, 21 Jul 2014 16:58:22 +0200
Subject: [PATCH] OO-1000: fix an issue with the edition of coach role of
 course, fix some issues with the views of the coaching tool

---
 .../user/course/CourseOverviewController.java |   2 +-
 .../java/org/olat/course/CourseFactory.java   |  14 ++--
 .../olat/modules/coach/CoachingService.java   |   2 +-
 .../modules/coach/manager/CoachingDAO.java    |   2 +-
 .../coach/manager/CoachingServiceImpl.java    |  33 ++++++----
 .../modules/coach/ui/CourseController.java    |   2 +-
 .../manager/RepositoryEntryRelationDAO.java   |  15 ++++-
 .../manager/RepositoryServiceImpl.java        |   9 +++
 .../database/mysql/alter_9_4_0_to_10_0_0.sql  |  21 ++++--
 .../database/mysql/setupDatabase.sql          |  21 ++++--
 .../database/oracle/alter_9_4_0_to_10_0_0.sql |  11 +++-
 .../database/oracle/setupDatabase.sql         |  11 +++-
 .../postgresql/alter_9_4_0_to_10_0_0.sql      |   9 ++-
 .../database/postgresql/setupDatabase.sql     |   9 ++-
 .../org/olat/modules/coach/CoachingCourse.zip | Bin 0 -> 19145 bytes
 .../olat/modules/coach/CoachingDAOTest.java   |  62 ++++++++++++++++++
 .../modules/coach/CoachingServiceTest.java    |   2 +-
 17 files changed, 182 insertions(+), 43 deletions(-)
 create mode 100644 src/test/java/org/olat/modules/coach/CoachingCourse.zip
 create mode 100644 src/test/java/org/olat/modules/coach/CoachingDAOTest.java

diff --git a/src/main/java/org/olat/admin/user/course/CourseOverviewController.java b/src/main/java/org/olat/admin/user/course/CourseOverviewController.java
index a9dc5975dc3..c1d4545bf1b 100644
--- a/src/main/java/org/olat/admin/user/course/CourseOverviewController.java
+++ b/src/main/java/org/olat/admin/user/course/CourseOverviewController.java
@@ -161,7 +161,7 @@ public class CourseOverviewController extends BasicController  {
 		//course membership
 		List<RepositoryEntryMembership> memberships = repositoryManager.getRepositoryEntryMembership(null, editedIdentity);
 
-		//group memebership
+		//group membership
 		List<BusinessGroupMembership> groupMemberships =  businessGroupService.getBusinessGroupMembership(Collections.<Long>emptyList(), editedIdentity);
 		Collection<Long> groupKeys = new ArrayList<Long>(groupMemberships.size());
 		for(BusinessGroupMembership membership: groupMemberships) {
diff --git a/src/main/java/org/olat/course/CourseFactory.java b/src/main/java/org/olat/course/CourseFactory.java
index 3fe66fd49d7..85dde404468 100644
--- a/src/main/java/org/olat/course/CourseFactory.java
+++ b/src/main/java/org/olat/course/CourseFactory.java
@@ -660,7 +660,8 @@ public class CourseFactory extends BasicManager {
 				(CourseEditorTreeNode)course.getEditorTreeModel().getRootNode());
 		// register any references in the run structure. The referenced entries have been 
 		// previousely deplyed (as part of the editor structure deployment process - see above method call)
-		registerReferences(course, course.getRunStructure().getRootNode());
+		registerReferences(course, 
+				(CourseEditorTreeNode)course.getEditorTreeModel().getRootNode());
 		// import shared folder references
 		deployReferencedSharedFolders(courseExportData, course);
 		// import glossary references
@@ -693,12 +694,13 @@ public class CourseFactory extends BasicManager {
 	 * @param course
 	 * @param currentNode
 	 */
-	private static void registerReferences(ICourse course, CourseNode currentNode) {
+	private static void registerReferences(ICourse course, CourseEditorTreeNode currentNode) {
 		for (int i = 0; i < currentNode.getChildCount(); i++) {
-			CourseNode childNode = (CourseNode)currentNode.getChildAt(i);
-			if (childNode.needsReferenceToARepositoryEntry()) {
-				referenceManager.addReference(course,
-					childNode.getReferencedRepositoryEntry().getOlatResource(), childNode.getIdent());
+			CourseEditorTreeNode childNode = (CourseEditorTreeNode)currentNode.getChildAt(i);
+			CourseNode childCourseNode = childNode.getCourseNode();
+			if (childCourseNode.needsReferenceToARepositoryEntry()) {
+				RepositoryEntry re = childCourseNode.getReferencedRepositoryEntry();
+				referenceManager.addReference(course, re.getOlatResource(), childNode.getIdent());
 			}
 			registerReferences(course, childNode);
 		}
diff --git a/src/main/java/org/olat/modules/coach/CoachingService.java b/src/main/java/org/olat/modules/coach/CoachingService.java
index 99a0ee262ca..ef203b325bc 100644
--- a/src/main/java/org/olat/modules/coach/CoachingService.java
+++ b/src/main/java/org/olat/modules/coach/CoachingService.java
@@ -55,7 +55,7 @@ public interface CoachingService {
 	
 	public List<EfficiencyStatementEntry> getGroup(BusinessGroup group);
 	
-	public List<EfficiencyStatementEntry> getCourse(Identity coach, RepositoryEntry entry, int firstResult, int maxResults);
+	public List<EfficiencyStatementEntry> getCourse(Identity coach, RepositoryEntry entry);
 	
 	public EfficiencyStatementEntry getEfficencyStatement(UserEfficiencyStatement statement);
 	
diff --git a/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java b/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
index 22c42e7390b..f7b26509e04 100644
--- a/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
+++ b/src/main/java/org/olat/modules/coach/manager/CoachingDAO.java
@@ -268,7 +268,7 @@ public class CoachingDAO extends BasicManager {
 		return stats;
 	}
 	
-	public List<Long> getStudents(Identity coach, RepositoryEntry entry, int firstResult, int maxResults) {
+	public List<Long> getStudents(Identity coach, RepositoryEntry entry) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select distinct(participant.identity.key) from repoentrytogroup as relGroup ")
 		  .append(" inner join relGroup.group as baseGroup")
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 3868dbf4df0..ac7a2a40fe2 100644
--- a/src/main/java/org/olat/modules/coach/manager/CoachingServiceImpl.java
+++ b/src/main/java/org/olat/modules/coach/manager/CoachingServiceImpl.java
@@ -60,11 +60,13 @@ public class CoachingServiceImpl implements CoachingService {
 	@Autowired
 	private BusinessGroupService businessGroupService;
 	
-	
+
+	@Override
 	public boolean isCoach(Identity coach) {
 		return coachingDao.isCoach(coach);
 	}
-	
+
+	@Override
 	public Map<Long, String> getIdentities(Collection<Long> identityNames) {
 		Map<Long,String> identityMap = new HashMap<Long,String>();
 		
@@ -76,44 +78,53 @@ public class CoachingServiceImpl implements CoachingService {
 		return identityMap;
 	}
 
+	@Override
 	public List<RepositoryEntry> getStudentsCourses(Identity coach, Identity student, int firstResult, int maxResults) {
 		return coachingDao.getStudentsCourses(coach, student, firstResult, maxResults);
 	}
-	
+
+	@Override
 	public List<StudentStatEntry> getStudentsStatistics(Identity coach) {
 		return coachingDao.getStudentsStatistics(coach);
 	}
-	
+
+	@Override
 	public List<CourseStatEntry> getCoursesStatistics(Identity coach) {
 		return coachingDao.getCoursesStatistics(coach);
 	}
-	
+
+	@Override
 	public List<GroupStatEntry> getGroupsStatistics(Identity coach) {
 		return coachingDao.getGroupsStatistics(coach);
 	}
-	
+
+	@Override
 	public List<EfficiencyStatementEntry> getGroup(BusinessGroup group) {
 		List<Identity> students = businessGroupService.getMembers(group, GroupRoles.participant.name());
 		List<RepositoryEntry> courses = businessGroupService.findRepositoryEntries(Collections.singletonList(group), 0, -1);
 		return coachingDao.getEfficencyStatementEntriesAlt(students, courses);
 	}
-	
-	public List<EfficiencyStatementEntry> getCourse(Identity coach, RepositoryEntry entry, int firstResult, int maxResults) {
-		List<Long> studentKeys = coachingDao.getStudents(coach, entry, firstResult, maxResults);
+
+	@Override
+	public List<EfficiencyStatementEntry> getCourse(Identity coach, RepositoryEntry entry) {
+		List<Long> studentKeys = coachingDao.getStudents(coach, entry);
 		List<IdentityShort> students = securityManager.findShortIdentitiesByKey(studentKeys);
 		return coachingDao.getEfficencyStatementEntries(students, Collections.singletonList(entry));
 	}
-	
+
+	@Override
 	public EfficiencyStatementEntry getEfficencyStatement(UserEfficiencyStatement statement) {
 		return coachingDao.getEfficencyStatementEntry(statement);
 	}
-	
+
+	@Override
 	public List<EfficiencyStatementEntry> getEfficencyStatements(Identity student, List<RepositoryEntry> courses) {
 		IdentityShort identity = securityManager.loadIdentityShortByKey(student.getKey());
 		List<IdentityShort> students = Collections.singletonList(identity);
 		return coachingDao.getEfficencyStatementEntries(students, courses);
 	}
 	
+	@Override
 	public List<UserEfficiencyStatement> getEfficencyStatements(Identity student) {
 		return coachingDao.getEfficencyStatementEntries(student);
 	}
diff --git a/src/main/java/org/olat/modules/coach/ui/CourseController.java b/src/main/java/org/olat/modules/coach/ui/CourseController.java
index f16e749c9f6..b86e04ce48e 100644
--- a/src/main/java/org/olat/modules/coach/ui/CourseController.java
+++ b/src/main/java/org/olat/modules/coach/ui/CourseController.java
@@ -168,7 +168,7 @@ public class CourseController extends BasicController implements Activateable2 {
 	}
 	
 	public List<EfficiencyStatementEntry> loadModel() {
-		List<EfficiencyStatementEntry> entries = coachingService.getCourse(getIdentity(), course, 0, -1);
+		List<EfficiencyStatementEntry> entries = coachingService.getCourse(getIdentity(), course);
 		TableDataModel<EfficiencyStatementEntry> model = new EfficiencyStatementEntryTableDataModel(entries);
 		tableCtr.setTableDataModel(model);
 		return entries;
diff --git a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
index 117431ef664..4fa41651b68 100644
--- a/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
+++ b/src/main/java/org/olat/repository/manager/RepositoryEntryRelationDAO.java
@@ -56,6 +56,12 @@ public class RepositoryEntryRelationDAO {
 	@Autowired
 	private GroupDAO groupDao;
 	
+	/**
+	 * Get roles in the repository entry, with business groups too
+	 * @param identity
+	 * @param re
+	 * @return
+	 */
 	public List<String> getRoles(IdentityRef identity, RepositoryEntryRef re) {
 		StringBuilder sb = new StringBuilder();
 		sb.append("select membership.role from ").append(RepositoryEntry.class.getName()).append(" as v")
@@ -71,12 +77,19 @@ public class RepositoryEntryRelationDAO {
 				.getResultList();
 	}
 
+	/**
+	 * Has role in the repository entry only (without business groups)
+	 * @param identity
+	 * @param re
+	 * @param roles
+	 * @return
+	 */
 	public boolean hasRole(IdentityRef identity, RepositoryEntryRef re, String... roles) {
 		List<String> roleList = GroupRoles.toList(roles);
 		
 		StringBuilder sb = new StringBuilder();
 		sb.append("select count(membership) from ").append(RepositoryEntry.class.getName()).append(" as v")
-		  .append(" inner join v.groups as relGroup")
+		  .append(" inner join v.groups as relGroup on relGroup.defaultGroup=true")
 		  .append(" inner join relGroup.group as baseGroup")
 		  .append(" inner join baseGroup.members as membership")
 		  .append(" where v.key=:repoKey and membership.identity.key=:identityKey");
diff --git a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
index 78aade40b73..55c57c4e641 100644
--- a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
+++ b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
@@ -304,11 +304,20 @@ public class RepositoryServiceImpl implements RepositoryService {
 		return reToGroupDao.getDefaultGroup(ref);
 	}
 
+	/**
+	 * Get the role in the specified resource, business group are included in
+	 * the query.
+	 * 
+	 */
 	@Override
 	public List<String> getRoles(Identity identity, RepositoryEntryRef re) {
 		return reToGroupDao.getRoles(identity, re);
 	}
 
+	/**
+	 * Has specific role in the specified resource WITHOUT business groups included in
+	 * the query.
+	 */
 	@Override
 	public boolean hasRole(Identity identity, RepositoryEntryRef re, String... roles) {
 		return reToGroupDao.hasRole(identity, re, roles);
diff --git a/src/main/resources/database/mysql/alter_9_4_0_to_10_0_0.sql b/src/main/resources/database/mysql/alter_9_4_0_to_10_0_0.sql
index eaacd7e0595..a9ba9b1840d 100644
--- a/src/main/resources/database/mysql/alter_9_4_0_to_10_0_0.sql
+++ b/src/main/resources/database/mysql/alter_9_4_0_to_10_0_0.sql
@@ -235,7 +235,7 @@ create or replace view o_re_membership_v as (
       bmember.g_role as g_role,
       re.repositoryentry_id as fk_entry_id
    from o_repositoryentry as re
-   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id)
+   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id and relgroup.r_defgroup=1)
    inner join o_bs_group_member as bmember on (bmember.fk_group_id=relgroup.fk_group_id) 
 );
 
@@ -246,8 +246,8 @@ create or replace view o_as_eff_statement_students_v as (
       sg_coach.fk_identity_id as tutor_id,
       sg_participant.fk_identity_id as student_id,
       sg_statement.id as st_id,
-      (case when sg_statement.passed = true then 1 else 0 end) as st_passed,
-      (case when sg_statement.passed = false then 1 else 0 end) as st_failed,
+      (case when sg_statement.passed = 1 then 1 else 0 end) as st_passed,
+      (case when sg_statement.passed = 0 then 1 else 0 end) as st_failed,
       (case when sg_statement.passed is null then 1 else 0 end) as st_not_attempted,
       sg_statement.score as st_score,
       pg_initial_launch.id as pg_id
@@ -257,6 +257,8 @@ create or replace view o_as_eff_statement_students_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create or replace view o_as_eff_statement_courses_v as (
@@ -266,8 +268,8 @@ create or replace view o_as_eff_statement_courses_v as (
       sg_coach.fk_identity_id as tutor_id,
       sg_participant.fk_identity_id as student_id,
       sg_statement.id as st_id,
-      (case when sg_statement.passed = true then 1 else 0 end) as st_passed,
-      (case when sg_statement.passed = false then 1 else 0 end) as st_failed,
+      (case when sg_statement.passed = 1 then 1 else 0 end) as st_passed,
+      (case when sg_statement.passed = 0 then 1 else 0 end) as st_failed,
       (case when sg_statement.passed is null then 1 else 0 end) as st_not_attempted,
       sg_statement.score as st_score,
       pg_initial_launch.id as pg_id
@@ -277,6 +279,8 @@ create or replace view o_as_eff_statement_courses_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create or replace view o_as_eff_statement_groups_v as (
@@ -288,8 +292,8 @@ create or replace view o_as_eff_statement_groups_v as (
       sg_coach.fk_identity_id as tutor_id,
       sg_participant.fk_identity_id as student_id,
       sg_statement.id as st_id,
-      (case when sg_statement.passed = true then 1 else 0 end) as st_passed,
-      (case when sg_statement.passed = false then 1 else 0 end) as st_failed,
+      (case when sg_statement.passed = 1 then 1 else 0 end) as st_passed,
+      (case when sg_statement.passed = 0 then 1 else 0 end) as st_failed,
       (case when sg_statement.passed is null then 1 else 0 end) as st_not_attempted,
       sg_statement.score as st_score,
       pg_initial_launch.id as pg_id
@@ -300,6 +304,9 @@ create or replace view o_as_eff_statement_groups_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_bg.group_id, sg_bg.groupname,
+      sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 -- drop views
diff --git a/src/main/resources/database/mysql/setupDatabase.sql b/src/main/resources/database/mysql/setupDatabase.sql
index c9efaf968bb..def00f1d840 100644
--- a/src/main/resources/database/mysql/setupDatabase.sql
+++ b/src/main/resources/database/mysql/setupDatabase.sql
@@ -1461,7 +1461,7 @@ create or replace view o_re_membership_v as (
       bmember.g_role as g_role,
       re.repositoryentry_id as fk_entry_id
    from o_repositoryentry as re
-   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id)
+   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id and relgroup.r_defgroup=1)
    inner join o_bs_group_member as bmember on (bmember.fk_group_id=relgroup.fk_group_id) 
 );
   
@@ -1513,8 +1513,8 @@ create view o_as_eff_statement_students_v as (
       sg_coach.fk_identity_id as tutor_id,
       sg_participant.fk_identity_id as student_id,
       sg_statement.id as st_id,
-      (case when sg_statement.passed = true then 1 else 0 end) as st_passed,
-      (case when sg_statement.passed = false then 1 else 0 end) as st_failed,
+      (case when sg_statement.passed = 1 then 1 else 0 end) as st_passed,
+      (case when sg_statement.passed = 0 then 1 else 0 end) as st_failed,
       (case when sg_statement.passed is null then 1 else 0 end) as st_not_attempted,
       sg_statement.score as st_score,
       pg_initial_launch.id as pg_id
@@ -1524,6 +1524,8 @@ create view o_as_eff_statement_students_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create view o_as_eff_statement_courses_v as (
@@ -1533,8 +1535,8 @@ create view o_as_eff_statement_courses_v as (
       sg_coach.fk_identity_id as tutor_id,
       sg_participant.fk_identity_id as student_id,
       sg_statement.id as st_id,
-      (case when sg_statement.passed = true then 1 else 0 end) as st_passed,
-      (case when sg_statement.passed = false then 1 else 0 end) as st_failed,
+      (case when sg_statement.passed = 1 then 1 else 0 end) as st_passed,
+      (case when sg_statement.passed = 0 then 1 else 0 end) as st_failed,
       (case when sg_statement.passed is null then 1 else 0 end) as st_not_attempted,
       sg_statement.score as st_score,
       pg_initial_launch.id as pg_id
@@ -1544,6 +1546,8 @@ create view o_as_eff_statement_courses_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create view o_as_eff_statement_groups_v as (
@@ -1555,8 +1559,8 @@ create view o_as_eff_statement_groups_v as (
       sg_coach.fk_identity_id as tutor_id,
       sg_participant.fk_identity_id as student_id,
       sg_statement.id as st_id,
-      (case when sg_statement.passed = true then 1 else 0 end) as st_passed,
-      (case when sg_statement.passed = false then 1 else 0 end) as st_failed,
+      (case when sg_statement.passed = 1 then 1 else 0 end) as st_passed,
+      (case when sg_statement.passed = 0 then 1 else 0 end) as st_failed,
       (case when sg_statement.passed is null then 1 else 0 end) as st_not_attempted,
       sg_statement.score as st_score,
       pg_initial_launch.id as pg_id
@@ -1567,6 +1571,9 @@ create view o_as_eff_statement_groups_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_bg.group_id, sg_bg.groupname,
+      sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 -- instant messaging
diff --git a/src/main/resources/database/oracle/alter_9_4_0_to_10_0_0.sql b/src/main/resources/database/oracle/alter_9_4_0_to_10_0_0.sql
index 6a484abfcf4..d5ac592fe17 100644
--- a/src/main/resources/database/oracle/alter_9_4_0_to_10_0_0.sql
+++ b/src/main/resources/database/oracle/alter_9_4_0_to_10_0_0.sql
@@ -237,7 +237,7 @@ create or replace view o_re_membership_v as (
       bmember.g_role as g_role,
       re.repositoryentry_id as fk_entry_id
    from o_repositoryentry re
-   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id)
+   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id and relgroup.r_defgroup=1)
    inner join o_bs_group_member bmember on (bmember.fk_group_id=relgroup.fk_group_id) 
 );
 
@@ -248,7 +248,7 @@ create or replace view o_as_eff_statement_students_v as (
       sg_coach.fk_identity_id as tutor_id,
       sg_participant.fk_identity_id as student_id,
       sg_statement.id as st_id,
-      (case when sg_statement.passed > 1 then 1 else 0 end) as st_passed,
+      (case when sg_statement.passed > 0 then 1 else 0 end) as st_passed,
       (case when sg_statement.passed = 0 then 1 else 0 end) as st_failed,
       (case when sg_statement.passed is null then 1 else 0 end) as st_not_attempted,
       sg_statement.score as st_score,
@@ -259,6 +259,8 @@ create or replace view o_as_eff_statement_students_v as (
    inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.passed, sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create or replace view o_as_eff_statement_courses_v as (
@@ -279,6 +281,8 @@ create or replace view o_as_eff_statement_courses_v as (
    inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.passed, sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create or replace view o_as_eff_statement_groups_v as (
@@ -302,6 +306,9 @@ create or replace view o_as_eff_statement_groups_v as (
    inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_bg.group_id, sg_bg.groupname,
+      sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.passed, sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 -- drop views
diff --git a/src/main/resources/database/oracle/setupDatabase.sql b/src/main/resources/database/oracle/setupDatabase.sql
index b2f7fb32616..e48a52819ed 100644
--- a/src/main/resources/database/oracle/setupDatabase.sql
+++ b/src/main/resources/database/oracle/setupDatabase.sql
@@ -1513,7 +1513,7 @@ create or replace view o_re_membership_v as (
       bmember.g_role as g_role,
       re.repositoryentry_id as fk_entry_id
    from o_repositoryentry re
-   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id)
+   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id and relgroup.r_defgroup=1)
    inner join o_bs_group_member bmember on (bmember.fk_group_id=relgroup.fk_group_id) 
 );
 
@@ -1565,7 +1565,7 @@ create view o_as_eff_statement_students_v as (
       sg_coach.fk_identity_id as tutor_id,
       sg_participant.fk_identity_id as student_id,
       sg_statement.id as st_id,
-      (case when sg_statement.passed > 1 then 1 else 0 end) as st_passed,
+      (case when sg_statement.passed > 0 then 1 else 0 end) as st_passed,
       (case when sg_statement.passed = 0 then 1 else 0 end) as st_failed,
       (case when sg_statement.passed is null then 1 else 0 end) as st_not_attempted,
       sg_statement.score as st_score,
@@ -1576,6 +1576,8 @@ create view o_as_eff_statement_students_v as (
    inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.passed, sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create view o_as_eff_statement_courses_v as (
@@ -1596,6 +1598,8 @@ create view o_as_eff_statement_courses_v as (
    inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.passed, sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create view o_as_eff_statement_groups_v as (
@@ -1619,6 +1623,9 @@ create view o_as_eff_statement_groups_v as (
    inner join o_bs_group_member sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_bg.group_id, sg_bg.groupname,
+      sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.passed, sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create or replace view o_im_roster_entry_v as (
diff --git a/src/main/resources/database/postgresql/alter_9_4_0_to_10_0_0.sql b/src/main/resources/database/postgresql/alter_9_4_0_to_10_0_0.sql
index 1da122c77c2..0769af2d370 100644
--- a/src/main/resources/database/postgresql/alter_9_4_0_to_10_0_0.sql
+++ b/src/main/resources/database/postgresql/alter_9_4_0_to_10_0_0.sql
@@ -240,7 +240,7 @@ create or replace view o_re_membership_v as (
       bmember.g_role as g_role,
       re.repositoryentry_id as fk_entry_id
    from o_repositoryentry as re
-   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id)
+   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id and relgroup.r_defgroup=true)
    inner join o_bs_group_member as bmember on (bmember.fk_group_id=relgroup.fk_group_id) 
 );
 
@@ -262,6 +262,8 @@ create view o_as_eff_statement_students_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create view o_as_eff_statement_courses_v as (
@@ -282,6 +284,8 @@ create view o_as_eff_statement_courses_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 drop view o_as_eff_statement_groups_v;
@@ -306,6 +310,9 @@ create view o_as_eff_statement_groups_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_bg.group_id, sg_bg.groupname,
+      sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 -- drop views
diff --git a/src/main/resources/database/postgresql/setupDatabase.sql b/src/main/resources/database/postgresql/setupDatabase.sql
index 467c328313a..170448b3ac0 100644
--- a/src/main/resources/database/postgresql/setupDatabase.sql
+++ b/src/main/resources/database/postgresql/setupDatabase.sql
@@ -1462,7 +1462,7 @@ create or replace view o_re_membership_v as (
       bmember.g_role as g_role,
       re.repositoryentry_id as fk_entry_id
    from o_repositoryentry as re
-   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id)
+   inner join o_re_to_group relgroup on (relgroup.fk_entry_id=re.repositoryentry_id and relgroup.r_defgroup=true)
    inner join o_bs_group_member as bmember on (bmember.fk_group_id=relgroup.fk_group_id) 
 );
   
@@ -1525,6 +1525,8 @@ create view o_as_eff_statement_students_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create view o_as_eff_statement_courses_v as (
@@ -1545,6 +1547,8 @@ create view o_as_eff_statement_courses_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 create view o_as_eff_statement_groups_v as (
@@ -1568,6 +1572,9 @@ create view o_as_eff_statement_groups_v as (
    inner join o_bs_group_member as sg_participant on (sg_participant.fk_group_id=sg_coach.fk_group_id and sg_participant.g_role='participant')
    left join o_as_eff_statement as sg_statement on (sg_statement.fk_identity = sg_participant.fk_identity_id and sg_statement.fk_resource_id = sg_re.fk_olatresource)
    left join o_as_user_course_infos as pg_initial_launch on (pg_initial_launch.fk_resource_id = sg_re.fk_olatresource and pg_initial_launch.fk_identity = sg_participant.fk_identity_id)
+   group by sg_re.repositoryentry_id, sg_re.displayname, sg_bg.group_id, sg_bg.groupname,
+      sg_coach.fk_identity_id, sg_participant.fk_identity_id,
+      sg_statement.id, sg_statement.score, pg_initial_launch.id
 );
 
 -- instant messaging
diff --git a/src/test/java/org/olat/modules/coach/CoachingCourse.zip b/src/test/java/org/olat/modules/coach/CoachingCourse.zip
new file mode 100644
index 0000000000000000000000000000000000000000..a3963ce7795afa2f5cd700670287848521a13106
GIT binary patch
literal 19145
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
K6Qhf8lm7$7MU_wh

literal 0
HcmV?d00001

diff --git a/src/test/java/org/olat/modules/coach/CoachingDAOTest.java b/src/test/java/org/olat/modules/coach/CoachingDAOTest.java
new file mode 100644
index 00000000000..11c747222d3
--- /dev/null
+++ b/src/test/java/org/olat/modules/coach/CoachingDAOTest.java
@@ -0,0 +1,62 @@
+package org.olat.modules.coach;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+import java.util.UUID;
+
+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.course.CourseFactory;
+import org.olat.course.ICourse;
+import org.olat.modules.coach.manager.CoachingDAO;
+import org.olat.modules.coach.model.StudentStatEntry;
+import org.olat.repository.RepositoryEntry;
+import org.olat.repository.RepositoryService;
+import org.olat.test.JunitTestHelper;
+import org.olat.test.OlatTestCase;
+import org.springframework.beans.factory.annotation.Autowired;
+
+public class CoachingDAOTest extends OlatTestCase {
+	
+	@Autowired
+	private DB dbInstance;
+	@Autowired
+	private CoachingDAO coachingDAO;
+	@Autowired
+	private RepositoryService repositoryService;
+	
+	@Test
+	public void getStudents()
+	throws URISyntaxException {
+		URL courseWithForumsUrl = CoachingDAOTest.class.getResource("CoachingCourse.zip");
+		File courseWithForums = new File(courseWithForumsUrl.toURI());
+		String softKey = UUID.randomUUID().toString();
+		RepositoryEntry re = CourseFactory.deployCourseFromZIP(courseWithForums, softKey, 4);
+		Assert.assertNotNull(re);
+
+		dbInstance.commitAndCloseSession();
+		
+		ICourse course = CourseFactory.loadCourse(re.getOlatResource().getResourceableId());			
+		boolean enabled =course.getCourseEnvironment().getCourseConfig().isEfficencyStatementEnabled();
+		Assert.assertTrue(enabled);
+		
+		Identity coach = JunitTestHelper.createAndPersistIdentityAsAuthor("Coach-1-" + UUID.randomUUID());
+		repositoryService.addRole(coach, re, GroupRoles.coach.name());
+		Identity participant1 = JunitTestHelper.createAndPersistIdentityAsRndUser("Coaching-Part-1");
+		repositoryService.addRole(participant1, re, GroupRoles.participant.name());
+		Identity participant2 = JunitTestHelper.createAndPersistIdentityAsRndUser("Coaching-Part-2");
+		repositoryService.addRole(participant2, re, GroupRoles.participant.name());
+		dbInstance.commitAndCloseSession();
+		
+		
+		List<StudentStatEntry> stats = coachingDAO.getStudentsStatistics(coach);
+		Assert.assertNotNull(stats);
+		Assert.assertEquals(2, stats.size());
+	}
+
+}
diff --git a/src/test/java/org/olat/modules/coach/CoachingServiceTest.java b/src/test/java/org/olat/modules/coach/CoachingServiceTest.java
index b74397f7077..d62511e9afb 100644
--- a/src/test/java/org/olat/modules/coach/CoachingServiceTest.java
+++ b/src/test/java/org/olat/modules/coach/CoachingServiceTest.java
@@ -315,7 +315,7 @@ public class CoachingServiceTest extends OlatTestCase {
 		List<Long> myCourses = coachToCourseMap.get(coach10.getKey());
 		assertNotNull(myCourses);
 
-		List<EfficiencyStatementEntry> statEntries = coachingService.getCourse(coach10, course10, 0, -1);
+		List<EfficiencyStatementEntry> statEntries = coachingService.getCourse(coach10, course10);
 		assertNotNull(statEntries);
 		assertFalse(statEntries.isEmpty());
 		assertTrue(myCourses.contains(course10.getKey()));
-- 
GitLab