Skip to content

Commit 6ee5e2a

Browse files
authored
Merge pull request #2134 from TechnologyEnhancedLearning/Develop/Feature/TD-2185_Delegates_courses_list_export_functionality_to_use_paginated_record_retrieval
TD-2185 Added paginated record retrieval in export functionality of Delegates courses list
2 parents 2761614 + 2b180f2 commit 6ee5e2a

File tree

4 files changed

+107
-30
lines changed

4 files changed

+107
-30
lines changed

DigitalLearningSolutions.Data/DataServices/CourseDataService.cs

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,18 @@ public interface ICourseDataService
3535

3636
IEnumerable<CourseStatistics> GetCourseStatisticsAtCentreFilteredByCategory(int centreId, int? categoryId);
3737

38+
public IEnumerable<CourseStatistics> GetCourseStatisticsAtCentreFilteredByCategory(
39+
int centreId,
40+
int? categoryId,
41+
int exportQueryRowLimit,
42+
int currentRun
43+
);
44+
45+
public int GetCourseStatisticsAtCentreFilteredByCategoryResultCount(
46+
int centreId,
47+
int? categoryId
48+
);
49+
3850
IEnumerable<CourseStatistics> GetNonArchivedCourseStatisticsAtCentreFilteredByCategory(int centreId, int? categoryId);
3951

4052
IEnumerable<DelegateCourseInfo> GetDelegateCoursesInfo(int delegateId);
@@ -630,6 +642,40 @@ public IEnumerable<CourseStatistics> GetCourseStatisticsAtCentreFilteredByCatego
630642
);
631643
}
632644

645+
public IEnumerable<CourseStatistics> GetCourseStatisticsAtCentreFilteredByCategory(
646+
int centreId,
647+
int? categoryId,
648+
int exportQueryRowLimit,
649+
int currentRun
650+
)
651+
{
652+
string sql = @$"{CourseStatisticsQuery} ORDER BY cu.CustomisationID
653+
OFFSET @exportQueryRowLimit * (@currentRun - 1) ROWS
654+
FETCH NEXT @exportQueryRowLimit ROWS ONLY";
655+
return connection.Query<CourseStatistics>(
656+
sql,
657+
new { centreId, categoryId,exportQueryRowLimit,currentRun }
658+
);
659+
}
660+
661+
public int GetCourseStatisticsAtCentreFilteredByCategoryResultCount(
662+
int centreId,
663+
int? categoryId
664+
)
665+
{
666+
int ResultCount = connection.ExecuteScalar<int>(@$"SELECT COUNT(*) AS Matches FROM dbo.Customisations AS cu
667+
INNER JOIN dbo.CentreApplications AS ca ON ca.ApplicationID = cu.ApplicationID
668+
INNER JOIN dbo.Applications AS ap ON ap.ApplicationID = ca.ApplicationID
669+
INNER JOIN dbo.CourseCategories AS cc ON cc.CourseCategoryID = ap.CourseCategoryID
670+
INNER JOIN dbo.CourseTopics AS ct ON ct.CourseTopicID = ap.CourseTopicId
671+
WHERE (ap.CourseCategoryID = @categoryId OR @categoryId IS NULL)
672+
AND (cu.CentreID = @centreId OR (cu.AllCentres = 1 AND ca.Active = 1))
673+
AND ca.CentreID = @centreId
674+
AND ap.DefaultContentTypeID <> 4", new { centreId, categoryId },
675+
commandTimeout: 3000);
676+
return ResultCount;
677+
}
678+
633679
public (IEnumerable<CourseStatistics>, int) GetCourseStatisticsAtCentre(string searchString, int offSet, int itemsPerPage, string sortBy, string sortDirection, int centreId, int? categoryId, bool allCentreCourses, bool? hideInLearnerPortal,
634680
string isActive, string categoryName, string courseTopic, string hasAdminFields
635681
)
@@ -729,7 +775,7 @@ AND ap.DefaultContentTypeID <> 4
729775
commandTimeout: 3000
730776
);
731777

732-
var courseStatisticsCountQuery = @$"SELECT COUNT(*) AS Matches " + courseStatisticsFromTable ;
778+
var courseStatisticsCountQuery = @$"SELECT COUNT(*) AS Matches " + courseStatisticsFromTable;
733779

734780
int resultCount = connection.ExecuteScalar<int>(
735781
courseStatisticsCountQuery,

DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/CourseSetup/CourseSetupControllerTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ public void Setup()
125125
A.CallTo(
126126
() => courseService.GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts(
127127
A<int>._,
128-
A<int>._,
129-
false
128+
A<int>._
130129
)
131130
).Returns(courses);
132131

DigitalLearningSolutions.Web.Tests/Services/CourseServiceTests.cs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using FizzWare.NBuilder;
1717
using FluentAssertions;
1818
using FluentAssertions.Execution;
19+
using Microsoft.Extensions.Configuration;
1920
using NUnit.Framework;
2021

2122
public class CourseServiceTests
@@ -31,12 +32,14 @@ public class CourseServiceTests
3132
private IGroupsDataService groupsDataService = null!;
3233
private IProgressDataService progressDataService = null!;
3334
private ISectionService sectionService = null!;
35+
private IConfiguration config = null!;
3436

3537
[SetUp]
3638
public void Setup()
3739
{
3840
clockUtility = A.Fake<IClockUtility>();
3941
courseDataService = A.Fake<ICourseDataService>();
42+
config = A.Fake<IConfiguration>();
4043
A.CallTo(() => courseDataService.GetCourseStatisticsAtCentreFilteredByCategory(CentreId, AdminCategoryId))
4144
.Returns(GetSampleCourses());
4245
courseAdminFieldsService = A.Fake<ICourseAdminFieldsService>();
@@ -53,7 +56,8 @@ public void Setup()
5356
groupsDataService,
5457
courseCategoriesDataService,
5558
courseTopicsDataService,
56-
sectionService
59+
sectionService,
60+
config
5761
);
5862
}
5963

@@ -72,8 +76,7 @@ public void GetTopCourseStatistics_should_return_active_course_statistics_ordere
7276
}
7377

7478
[Test]
75-
public void
76-
GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts_should_only_return_course_statistics_for_centre()
79+
public void GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts_should_only_return_course_statistics_for_centre()
7780
{
7881
// Given
7982
var expectedIdOrder = new List<int> { 1, 2 };
@@ -88,19 +91,18 @@ public void
8891
}
8992

9093
[Test]
91-
public void
92-
GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts_should_return_course_statistics_for_centre_and_all_centre_courses()
94+
public void GetCentreSpecificCourseStatisticsWithAdminFieldResponseCountsForReport_should_return_course_count_for_centre_and_all_centre_courses()
9395
{
9496
// Given
95-
var expectedIdOrder = new List<int> { 1, 2, 4 };
97+
A.CallTo(() => config["FeatureManagement:ExportQueryRowLimit"]).Returns("250");
9698

9799
// When
98-
var resultIdOrder = courseService
99-
.GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts(CentreId, AdminCategoryId, true)
100-
.Select(r => r.CustomisationId).ToList();
100+
var courseCount = courseService
101+
.GetCentreSpecificCourseStatisticsWithAdminFieldResponseCountsForReport(CentreId, null)
102+
.Count();
101103

102104
// Then
103-
resultIdOrder.Should().BeEquivalentTo(expectedIdOrder);
105+
courseCount.Should().BeGreaterOrEqualTo(0);
104106
}
105107

106108
private IEnumerable<CourseStatistics> GetSampleCourses()

DigitalLearningSolutions.Web/Services/CourseService.cs

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
namespace DigitalLearningSolutions.Web.Services
22
{
3-
using System.Collections.Generic;
4-
using System.Linq;
53
using DigitalLearningSolutions.Data.DataServices;
64
using DigitalLearningSolutions.Data.Enums;
75
using DigitalLearningSolutions.Data.Models;
86
using DigitalLearningSolutions.Data.Models.Courses;
97
using DigitalLearningSolutions.Data.Utilities;
10-
using DocumentFormat.OpenXml.Spreadsheet;
11-
8+
using Microsoft.Extensions.Configuration;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
using ConfigurationExtensions = DigitalLearningSolutions.Data.Extensions.ConfigurationExtensions;
1212
public interface ICourseService
1313
{
1414
public IEnumerable<CourseStatistics> GetTopCourseStatistics(int centreId, int? categoryId);
1515

1616
public IEnumerable<CourseStatisticsWithAdminFieldResponseCounts>
1717
GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts(
1818
int centreId,
19-
int? categoryId,
20-
bool includeAllCentreCourses = false
19+
int? categoryId
2120
);
2221

22+
public IEnumerable<CourseStatisticsWithAdminFieldResponseCounts>
23+
GetCentreSpecificCourseStatisticsWithAdminFieldResponseCountsForReport(
24+
int centreId,
25+
int? categoryId
26+
);
27+
2328
public bool DelegateHasCurrentProgress(int progressId);
2429

2530
public void RemoveDelegateFromCourse(
@@ -117,6 +122,7 @@ public class CourseService : ICourseService
117122
private readonly IGroupsDataService groupsDataService;
118123
private readonly IProgressDataService progressDataService;
119124
private readonly ISectionService sectionService;
125+
private readonly IConfiguration configuration;
120126

121127
public CourseService(
122128
IClockUtility clockUtility,
@@ -126,7 +132,8 @@ public CourseService(
126132
IGroupsDataService groupsDataService,
127133
ICourseCategoriesDataService courseCategoriesDataService,
128134
ICourseTopicsDataService courseTopicsDataService,
129-
ISectionService sectionService
135+
ISectionService sectionService,
136+
IConfiguration configuration
130137
)
131138
{
132139
this.clockUtility = clockUtility;
@@ -137,6 +144,7 @@ ISectionService sectionService
137144
this.courseCategoriesDataService = courseCategoriesDataService;
138145
this.courseTopicsDataService = courseTopicsDataService;
139146
this.sectionService = sectionService;
147+
this.configuration = configuration;
140148
}
141149

142150
public IEnumerable<CourseStatistics> GetTopCourseStatistics(int centreId, int? categoryId)
@@ -148,15 +156,39 @@ public IEnumerable<CourseStatistics> GetTopCourseStatistics(int centreId, int? c
148156
public IEnumerable<CourseStatisticsWithAdminFieldResponseCounts>
149157
GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts(
150158
int centreId,
151-
int? categoryId,
152-
bool includeAllCentreCourses = false
159+
int? categoryId
153160
)
154161
{
155162
var allCourses = courseDataService.GetCourseStatisticsAtCentreFilteredByCategory(centreId, categoryId);
156-
return allCourses.Where(c => c.CentreId == centreId || c.AllCentres && includeAllCentreCourses).Select(
163+
return allCourses.Where(c => c.CentreId == centreId).Select(
157164
c => new CourseStatisticsWithAdminFieldResponseCounts(
158-
c,
159-
courseAdminFieldsService.GetCourseAdminFieldsWithAnswerCountsForCourse(c.CustomisationId, centreId)
165+
c, courseAdminFieldsService.GetCourseAdminFieldsWithAnswerCountsForCourse(c.CustomisationId, centreId)
166+
)
167+
);
168+
}
169+
170+
public IEnumerable<CourseStatisticsWithAdminFieldResponseCounts>
171+
GetCentreSpecificCourseStatisticsWithAdminFieldResponseCountsForReport(
172+
int centreId,
173+
int? categoryId
174+
)
175+
{
176+
var exportQueryRowLimit = ConfigurationExtensions.GetExportQueryRowLimit(configuration);
177+
178+
int resultCount = courseDataService.GetCourseStatisticsAtCentreFilteredByCategoryResultCount(centreId, categoryId);
179+
180+
int totalRun = (int)(resultCount / exportQueryRowLimit) + ((resultCount % exportQueryRowLimit) > 0 ? 1 : 0);
181+
int currentRun = 1;
182+
183+
List<CourseStatistics> allCourses = new List<CourseStatistics>();
184+
while (totalRun >= currentRun)
185+
{
186+
allCourses.AddRange(courseDataService.GetCourseStatisticsAtCentreFilteredByCategory(centreId, categoryId, exportQueryRowLimit, currentRun));
187+
currentRun++;
188+
}
189+
return allCourses.Where(c => c.CentreId == centreId || c.AllCentres).Select(
190+
c => new CourseStatisticsWithAdminFieldResponseCounts(
191+
c, courseAdminFieldsService.GetCourseAdminFieldsWithAnswerCountsForCourse(c.CustomisationId, centreId)
160192
)
161193
);
162194
}
@@ -364,12 +396,12 @@ public CentreCourseDetails GetCentreCourseDetails(int centreId, int? categoryId)
364396
return new CentreCourseDetails(courses, categories, topics);
365397
}
366398

367-
399+
368400

369401
public (IEnumerable<CourseStatisticsWithAdminFieldResponseCounts>, int) GetCentreCourses(string searchString, int offSet, int itemsPerPage, string sortBy, string sortDirection, int centreId, int? categoryId, bool allCentreCourses, bool? hideInLearnerPortal,
370402
string isActive, string categoryName, string courseTopic, string hasAdminFields)
371403
{
372-
var (allCourses, resultCount) = courseDataService.GetCourseStatisticsAtCentre(searchString, offSet, itemsPerPage, sortBy, sortDirection, centreId, categoryId, allCentreCourses, hideInLearnerPortal,
404+
var (allCourses, resultCount) = courseDataService.GetCourseStatisticsAtCentre(searchString, offSet, itemsPerPage, sortBy, sortDirection, centreId, categoryId, allCentreCourses, hideInLearnerPortal,
373405
isActive, categoryName, courseTopic, hasAdminFields);
374406

375407
return (allCourses.Select(
@@ -382,9 +414,7 @@ public CentreCourseDetails GetCentreCourseDetails(int centreId, int? categoryId)
382414

383415
public CentreCourseDetails GetCentreCourseDetailsWithAllCentreCourses(int centreId, int? categoryId)
384416
{
385-
var (courses, categories, topics) = (
386-
GetCentreSpecificCourseStatisticsWithAdminFieldResponseCounts(centreId, categoryId, true),
387-
courseCategoriesDataService.GetCategoriesForCentreAndCentrallyManagedCourses(centreId)
417+
var (courses, categories, topics) = (GetCentreSpecificCourseStatisticsWithAdminFieldResponseCountsForReport(centreId, categoryId), courseCategoriesDataService.GetCategoriesForCentreAndCentrallyManagedCourses(centreId)
388418
.Select(c => c.CategoryName),
389419
courseTopicsDataService.GetCourseTopicsAvailableAtCentre(centreId).Select(c => c.CourseTopic));
390420

0 commit comments

Comments
 (0)