Skip to content

Commit 2761614

Browse files
authored
Merge pull request #2125 from TechnologyEnhancedLearning/Develop/Features/TD-2184-Refactor-the-Tracking-System---Delegates-list-export-functionality-to-use-paginated-record-retrieval
TD-2184: Refactor the tracking system delegates list export functionality to use paginated record retrieval
2 parents 23166a1 + ff3cb70 commit 2761614

File tree

4 files changed

+63
-25
lines changed

4 files changed

+63
-25
lines changed

DigitalLearningSolutions.Data/DataServices/UserDataService/DelegateUserCardDataService.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
using System.Collections.Generic;
44
using System.Linq;
5+
using System.Threading.Tasks;
56
using Dapper;
67
using DigitalLearningSolutions.Data.Models.User;
78

@@ -111,7 +112,30 @@ public List<DelegateUserCard> GetDelegateUserCardsByCentreId(int centreId)
111112
new { centreId }
112113
).ToList();
113114
}
114-
115+
public int GetCountDelegateUserCardsForExportByCentreId(int centreId)
116+
{
117+
return connection.ExecuteScalar<int>(
118+
@$"SELECT COUNT(*)
119+
FROM DelegateAccounts AS da with(nolock)
120+
INNER JOIN Centres AS c with(nolock) ON c.CentreID = da.CentreID
121+
INNER JOIN Users AS u with(nolock) ON u.ID = da.UserID
122+
LEFT JOIN UserCentreDetails AS ucd with(nolock) ON ucd.UserID = da.UserID AND ucd.CentreID = da.CentreID
123+
INNER JOIN JobGroups AS jg with(nolock) ON jg.JobGroupID = u.JobGroupID
124+
WHERE da.CentreId = @centreId AND da.Approved = 1",
125+
new { centreId }
126+
);
127+
}
128+
public async Task<List<DelegateUserCard>> GetDelegateUserCardsForExportByCentreId(int centreId, int exportQueryRowLimit, int currentRun)
129+
{
130+
return connection.Query<DelegateUserCard>(
131+
@$"{DelegateUserCardSelectQuery}
132+
WHERE da.CentreId = @centreId AND da.Approved = 1
133+
ORDER BY LTRIM(u.LastName), LTRIM(u.FirstName)
134+
OFFSET @exportQueryRowLimit * (@currentRun - 1) ROWS
135+
FETCH NEXT @exportQueryRowLimit ROWS ONLY ",
136+
new { centreId, exportQueryRowLimit, currentRun }
137+
).ToList();
138+
}
115139
public (IEnumerable<DelegateUserCard>, int) GetDelegateUserCards(string searchString, int offSet, int itemsPerPage, string sortBy, string sortDirection, int centreId,
116140
string isActive, string isPasswordSet, string isAdmin, string isUnclaimed, string isEmailVerified, string registrationType, int jobGroupId,
117141
string answer1, string answer2, string answer3, string answer4, string answer5, string answer6)

DigitalLearningSolutions.Data/DataServices/UserDataService/UserDataService.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ void UpdateDelegateAccount(
9292
DelegateUserCard? GetDelegateUserCardById(int id);
9393

9494
List<DelegateUserCard> GetDelegateUserCardsByCentreId(int centreId);
95+
Task<List<DelegateUserCard>> GetDelegateUserCardsForExportByCentreId(int centreId, int exportQueryRowLimit, int currentRun);
96+
int GetCountDelegateUserCardsForExportByCentreId(int centreId);
9597

9698
(IEnumerable<DelegateUserCard>, int) GetDelegateUserCards(string searchString, int offSet, int itemsPerPage, string sortBy, string sortDirection, int centreId,
9799
string isActive, string isPasswordSet, string isAdmin, string isUnclaimed, string isEmailVerified, string registrationType, int jobGroupId,

DigitalLearningSolutions.Web.Tests/Services/DelegateDownloadFileServiceTests.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
using DigitalLearningSolutions.Web.Services;
1515
using FakeItEasy;
1616
using NUnit.Framework;
17-
17+
using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration;
1818
public class DelegateDownloadFileServiceTests
1919
{
2020
public const string TestAllDelegatesExportRelativeFilePath = "/TestData/AllDelegatesExportTest.xlsx";
@@ -93,14 +93,16 @@ public class DelegateDownloadFileServiceTests
9393
private IDelegateDownloadFileService delegateDownloadFileService = null!;
9494
private IJobGroupsDataService jobGroupsDataService = null!;
9595
private IUserDataService userDataService = null!;
96-
96+
private IConfiguration configuration = null!;
9797
[SetUp]
9898
public void SetUp()
9999
{
100100
centreRegistrationPromptsService = A.Fake<ICentreRegistrationPromptsService>();
101101
jobGroupsDataService = A.Fake<IJobGroupsDataService>();
102102
userDataService = A.Fake<IUserDataService>();
103-
delegateDownloadFileService = new DelegateDownloadFileService(centreRegistrationPromptsService, jobGroupsDataService, userDataService);
103+
configuration = A.Fake<IConfiguration>();
104+
A.CallTo(() => configuration["FeatureManagement:ExportQueryRowLimit"]).Returns("10");
105+
delegateDownloadFileService = new DelegateDownloadFileService(centreRegistrationPromptsService, jobGroupsDataService, userDataService, configuration);
104106
}
105107

106108
[Test]
@@ -144,7 +146,8 @@ public void GetAllDelegatesFileForCentre_returns_expected_excel_data()
144146
.Returns(new CentreRegistrationPrompts(centreId, centreRegistrationPrompts));
145147

146148
A.CallTo(() => userDataService.GetDelegateUserCardsByCentreId(2)).Returns(delegateUserCards);
147-
149+
A.CallTo(() => userDataService.GetCountDelegateUserCardsForExportByCentreId(2)).Returns(10);
150+
A.CallTo(() => userDataService.GetDelegateUserCardsForExportByCentreId(2, 10, 1)).Returns(delegateUserCards);
148151
// When
149152
var resultBytes = delegateDownloadFileService.GetAllDelegatesFileForCentre(2, null, null, GenericSortingHelper.Ascending, null);
150153
using var resultsStream = new MemoryStream(resultBytes);

DigitalLearningSolutions.Web/Services/DelegateDownloadFileService.cs

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
using System.Data;
66
using System.IO;
77
using System.Linq;
8+
using System.Threading.Tasks;
89
using ClosedXML.Excel;
910
using DigitalLearningSolutions.Data.DataServices;
1011
using DigitalLearningSolutions.Data.DataServices.UserDataService;
1112
using DigitalLearningSolutions.Data.Helpers;
1213
using DigitalLearningSolutions.Data.Models.CustomPrompts;
1314
using DigitalLearningSolutions.Data.Models.User;
15+
using Microsoft.Extensions.Configuration;
1416

1517
public interface IDelegateDownloadFileService
1618
{
@@ -41,6 +43,7 @@ public class DelegateDownloadFileService : IDelegateDownloadFileService
4143
private const string Active = "Active";
4244
private const string Approved = "Approved";
4345
private const string IsAdmin = "Is admin";
46+
private readonly IConfiguration configuration;
4447
private static readonly XLTableTheme TableTheme = XLTableTheme.TableStyleLight9;
4548
private readonly ICentreRegistrationPromptsService centreRegistrationPromptsService;
4649
private readonly IJobGroupsDataService jobGroupsDataService;
@@ -49,12 +52,13 @@ public class DelegateDownloadFileService : IDelegateDownloadFileService
4952
public DelegateDownloadFileService(
5053
ICentreRegistrationPromptsService centreRegistrationPromptsService,
5154
IJobGroupsDataService jobGroupsDataService,
52-
IUserDataService userDataService
55+
IUserDataService userDataService, IConfiguration configuration
5356
)
5457
{
5558
this.centreRegistrationPromptsService = centreRegistrationPromptsService;
5659
this.jobGroupsDataService = jobGroupsDataService;
5760
this.userDataService = userDataService;
61+
this.configuration = configuration;
5862
}
5963

6064
public byte[] GetDelegatesAndJobGroupDownloadFileForCentre(int centreId)
@@ -139,13 +143,18 @@ private void PopulateAllDelegatesSheet(
139143
)
140144
{
141145
var registrationPrompts = centreRegistrationPromptsService.GetCentreRegistrationPromptsByCentreId(centreId);
142-
var delegatesToExport = GetDelegatesToExport(centreId, searchString, sortBy, sortDirection, filterString)
143-
.ToList();
144-
146+
var delegatesToExport = Task.Run(() => GetDelegatesToExport(centreId)).Result;
147+
var searchedUsers = GenericSearchHelper.SearchItems(delegatesToExport, searchString).AsQueryable();
148+
var filteredItems = FilteringHelper.FilterItems(searchedUsers, filterString).AsQueryable();
149+
var sortedItems = GenericSortingHelper.SortAllItems(
150+
filteredItems,
151+
sortBy ?? nameof(DelegateUserCard.SearchableName),
152+
sortDirection
153+
).ToList();
145154
var dataTable = new DataTable();
146155
SetUpDataTableColumnsForAllDelegates(registrationPrompts, dataTable);
147156

148-
foreach (var delegateRecord in delegatesToExport)
157+
foreach (var delegateRecord in sortedItems)
149158
{
150159
SetDelegateRowValues(dataTable, delegateRecord, registrationPrompts);
151160
}
@@ -166,24 +175,24 @@ private void PopulateAllDelegatesSheet(
166175
FormatAllDelegateWorksheetColumns(workbook, dataTable);
167176
}
168177

169-
private IEnumerable<DelegateUserCard> GetDelegatesToExport(
170-
int centreId,
171-
string? searchString,
172-
string? sortBy,
173-
string sortDirection,
174-
string? filterString
178+
private async Task<IEnumerable<DelegateUserCard>> GetDelegatesToExport(
179+
int centreId
175180
)
176181
{
177-
var delegateUsers = userDataService.GetDelegateUserCardsByCentreId(centreId).Where(c => !Guid.TryParse(c.EmailAddress, out _));
178-
var searchedUsers = GenericSearchHelper.SearchItems(delegateUsers, searchString).AsQueryable();
179-
var filteredItems = FilteringHelper.FilterItems(searchedUsers, filterString).AsQueryable();
180-
var sortedItems = GenericSortingHelper.SortAllItems(
181-
filteredItems,
182-
sortBy ?? nameof(DelegateUserCard.SearchableName),
183-
sortDirection
184-
);
182+
var exportQueryRowLimit = Data.Extensions.ConfigurationExtensions.GetExportQueryRowLimit(configuration);
183+
int resultCount = userDataService.GetCountDelegateUserCardsForExportByCentreId(centreId);
184+
185+
int totalRun = (int)(resultCount / exportQueryRowLimit) + ((resultCount % exportQueryRowLimit) > 0 ? 1 : 0);
186+
int currentRun = 1;
187+
List<DelegateUserCard> delegates = new List<DelegateUserCard>();
188+
while (totalRun >= currentRun)
189+
{
190+
delegates.AddRange(await userDataService.GetDelegateUserCardsForExportByCentreId(centreId, exportQueryRowLimit, currentRun));
191+
currentRun++;
192+
}
193+
185194

186-
return sortedItems;
195+
return delegates.Where(c => !Guid.TryParse(c.EmailAddress, out _));
187196
}
188197

189198
private static void SetUpDataTableColumnsForAllDelegates(

0 commit comments

Comments
 (0)