Skip to content

Commit 0aeac45

Browse files
committed
Merge branch 'Release-2024.32' into Release-2024.38
2 parents 33594e0 + 827693c commit 0aeac45

File tree

10 files changed

+266
-23
lines changed

10 files changed

+266
-23
lines changed

DigitalLearningSolutions.Data/DataServices/CourseDataService.cs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ int EnrolOnActivitySelfAssessment(int selfAssessmentId, int candidateId, int sup
125125
int selfAssessmentSupervisorRoleId, DateTime? completeByDate, int delegateUserId, int centreId, int? enrolledByAdminId);
126126

127127
bool IsCourseCompleted(int candidateId, int customisationId);
128-
128+
bool IsCourseCompleted(int candidateId, int customisationId, int progressID);
129129
public IEnumerable<Course> GetApplicationsAvailableToCentre(int centreId);
130130

131131
public (IEnumerable<CourseStatistics>, int) GetCourseStatisticsAtCentre(string searchString, int offSet, int itemsPerPage, string sortBy, string sortDirection, int centreId, int? categoryId, bool allCentreCourses, bool? hideInLearnerPortal,
@@ -137,6 +137,8 @@ int EnrolOnActivitySelfAssessment(int selfAssessmentId, int candidateId, int sup
137137
public IEnumerable<CourseStatistics> GetDelegateCourseStatisticsAtCentre(string searchString, int centreId, int? categoryId, bool allCentreCourses, bool? hideInLearnerPortal, string isActive, string categoryName, string courseTopic, string hasAdminFields);
138138

139139
public IEnumerable<DelegateAssessmentStatistics> GetDelegateAssessmentStatisticsAtCentre(string searchString, int centreId, string categoryName, string isActive);
140+
bool IsSelfEnrollmentAllowed(int customisationId);
141+
Customisation? GetCourse(int customisationId);
140142
}
141143

142144
public class CourseDataService : ICourseDataService
@@ -1828,13 +1830,28 @@ SELECT p.Completed
18281830
FROM Progress AS p INNER JOIN
18291831
Customisations AS cu ON p.CustomisationID = cu.CustomisationID INNER JOIN
18301832
Applications AS a ON cu.ApplicationID = a.ApplicationID
1831-
WHERE (p.CandidateID = @candidateId) AND p.CustomisationID = @customisationId
1833+
WHERE (p.CandidateID = @candidateId) AND p.CustomisationID = @customisationId
18321834
AND (NOT (p.Completed IS NULL)))
18331835
THEN CAST(1 AS BIT)
18341836
ELSE CAST(0 AS BIT) END",
18351837
new { candidateId, customisationId }
18361838
);
18371839
}
1840+
public bool IsCourseCompleted(int candidateId, int customisationId, int progressID)
1841+
{
1842+
return connection.ExecuteScalar<bool>(
1843+
@"SELECT CASE WHEN EXISTS (
1844+
SELECT p.Completed
1845+
FROM Progress AS p INNER JOIN
1846+
Customisations AS cu ON p.CustomisationID = cu.CustomisationID INNER JOIN
1847+
Applications AS a ON cu.ApplicationID = a.ApplicationID
1848+
WHERE (p.CandidateID = @candidateId) AND p.CustomisationID = @customisationId AND progressID =@progressID
1849+
AND (NOT (p.Completed IS NULL)))
1850+
THEN CAST(1 AS BIT)
1851+
ELSE CAST(0 AS BIT) END",
1852+
new { candidateId, customisationId, progressID }
1853+
);
1854+
}
18381855

18391856
public IEnumerable<Course> GetApplicationsAvailableToCentre(int centreId)
18401857
{
@@ -1969,5 +1986,38 @@ AND sa.[Name] LIKE '%' + @searchString + '%'
19691986
new { searchString, centreId, categoryName, isActive }, commandTimeout: 3000);
19701987
return delegateAssessmentStatistics;
19711988
}
1989+
1990+
public bool IsSelfEnrollmentAllowed(int customisationId)
1991+
{
1992+
int selfRegister = connection.QueryFirstOrDefault<int>(
1993+
@"SELECT COUNT(CustomisationID) FROM Customisations
1994+
WHERE CustomisationID = @customisationID AND SelfRegister = 1 AND Active = 1",
1995+
new { customisationId });
1996+
1997+
return selfRegister > 0;
1998+
}
1999+
2000+
public Customisation? GetCourse(int customisationId)
2001+
{
2002+
return connection.Query<Customisation>(
2003+
@"SELECT CustomisationID
2004+
,Active
2005+
,CentreID
2006+
,ApplicationID
2007+
,CustomisationName
2008+
,IsAssessed
2009+
,Password
2010+
,SelfRegister
2011+
,TutCompletionThreshold
2012+
,DiagCompletionThreshold
2013+
,DiagObjSelect
2014+
,HideInLearnerPortal
2015+
,NotificationEmails
2016+
FROM Customisations
2017+
WHERE CustomisationID = @customisationID ",
2018+
new { customisationId }).FirstOrDefault();
2019+
2020+
2021+
}
19722022
}
19732023
}

DigitalLearningSolutions.Data/Models/Courses/Customisation.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
{
33
public class Customisation
44
{
5+
public Customisation() { }
56
public Customisation(
67
int centreId,
78
int applicationId,
@@ -40,5 +41,8 @@ public Customisation(
4041
public bool DiagObjSelect { get; set; }
4142
public bool HideInLearnerPortal { get; set; }
4243
public string? NotificationEmails { get; set; }
44+
public int CustomisationId { get; set; }
45+
public bool Active { get; set; }
46+
4347
}
4448
}

DigitalLearningSolutions.Web.Tests/Controllers/LearningMenu/IndexTests.cs

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
namespace DigitalLearningSolutions.Web.Tests.Controllers.LearningMenu
22
{
3+
using DigitalLearningSolutions.Data.Models.Progress;
34
using DigitalLearningSolutions.Web.Tests.TestHelpers;
45
using DigitalLearningSolutions.Web.ViewModels.LearningMenu;
56
using FakeItEasy;
67
using FluentAssertions;
78
using FluentAssertions.AspNetCore.Mvc;
89
using Microsoft.AspNetCore.Http;
910
using NUnit.Framework;
11+
using System.Collections.Generic;
1012

1113
public partial class LearningMenuControllerTests
1214
{
@@ -15,13 +17,18 @@ public void Index_should_render_view()
1517
{
1618
// Given
1719
var expectedCourseContent = CourseContentHelper.CreateDefaultCourseContent(CustomisationId);
20+
var course = CourseContentHelper.CreateDefaultCourse();
21+
A.CallTo(() => courseService.GetCourse(CustomisationId)).Returns(course);
22+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, CustomisationId)).Returns(
23+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
24+
);
1825
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, CustomisationId))
1926
.Returns(expectedCourseContent);
2027
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId)).Returns(10);
2128
A.CallTo(() => courseContentService.GetProgressId(CandidateId, CustomisationId)).Returns(10);
2229

2330
// When
24-
var result = controller.Index(CustomisationId);
31+
var result = controller.Index(CustomisationId, progressID);
2532

2633
// Then
2734
var expectedModel = new InitialMenuViewModel(expectedCourseContent);
@@ -38,13 +45,19 @@ public void Index_should_redirect_to_section_page_if_one_section_in_course()
3845
var section = CourseContentHelper.CreateDefaultCourseSection(id: sectionId);
3946
var expectedCourseContent = CourseContentHelper.CreateDefaultCourseContent(customisationId);
4047
expectedCourseContent.Sections.Add(section);
48+
var course = CourseContentHelper.CreateDefaultCourse();
49+
course.CustomisationId = customisationId;
4150

51+
A.CallTo(() => courseService.GetCourse(customisationId)).Returns(course);
52+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, customisationId)).Returns(
53+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
54+
);
4255
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, customisationId))
4356
.Returns(expectedCourseContent);
4457
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, customisationId, CentreId)).Returns(10);
4558

4659
// When
47-
var result = controller.Index(customisationId);
60+
var result = controller.Index(customisationId, progressID);
4861

4962
// Then
5063
result.Should()
@@ -67,14 +80,21 @@ public void Index_should_not_redirect_to_section_page_if_more_than_one_section_i
6780

6881
var expectedCourseContent = CourseContentHelper.CreateDefaultCourseContent(customisationId);
6982
expectedCourseContent.Sections.AddRange(new[] { section1, section2, section3 });
83+
var course = CourseContentHelper.CreateDefaultCourse();
84+
course.CustomisationId = customisationId;
85+
86+
A.CallTo(() => courseService.GetCourse(customisationId)).Returns(course);
87+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, customisationId)).Returns(
88+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
89+
);
7090

7191
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, customisationId))
7292
.Returns(expectedCourseContent);
7393
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, customisationId, CentreId)).Returns(10);
7494
A.CallTo(() => courseContentService.GetProgressId(CandidateId, customisationId)).Returns(10);
7595

7696
// When
77-
var result = controller.Index(customisationId);
97+
var result = controller.Index(customisationId, progressID);
7898

7999
// Then
80100
var expectedModel = new InitialMenuViewModel(expectedCourseContent);
@@ -86,12 +106,18 @@ public void Index_should_not_redirect_to_section_page_if_more_than_one_section_i
86106
public void Index_should_return_404_if_unknown_course()
87107
{
88108
// Given
109+
var course = CourseContentHelper.CreateDefaultCourse();
110+
111+
A.CallTo(() => courseService.GetCourse(CustomisationId)).Returns(course);
112+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, CustomisationId)).Returns(
113+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
114+
);
89115
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, CustomisationId)).Returns(null);
90116
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId))
91117
.Returns(3);
92118

93119
// When
94-
var result = controller.Index(CustomisationId);
120+
var result = controller.Index(CustomisationId, progressID);
95121

96122
// Then
97123
result.Should()
@@ -106,13 +132,19 @@ public void Index_should_return_404_if_unable_to_enrol()
106132
{
107133
// Given
108134
var defaultCourseContent = CourseContentHelper.CreateDefaultCourseContent(CustomisationId);
135+
var course = CourseContentHelper.CreateDefaultCourse();
136+
137+
A.CallTo(() => courseService.GetCourse(CustomisationId)).Returns(course);
138+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, CustomisationId)).Returns(
139+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
140+
);
109141
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, CustomisationId))
110142
.Returns(defaultCourseContent);
111143
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId))
112144
.Returns(null);
113145

114146
// When
115-
var result = controller.Index(CustomisationId);
147+
var result = controller.Index(CustomisationId, progressID);
116148

117149
// Then
118150
result.Should()
@@ -127,9 +159,16 @@ public void Index_always_calls_get_course_content()
127159
{
128160
// Given
129161
const int customisationId = 1;
162+
var course = CourseContentHelper.CreateDefaultCourse();
163+
164+
A.CallTo(() => courseService.GetCourse(customisationId)).Returns(course);
165+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, customisationId)).Returns(
166+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
167+
);
168+
130169

131170
// When
132-
controller.Index(1);
171+
controller.Index(1,2);
133172

134173
// Then
135174
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, customisationId)).MustHaveHappened();
@@ -141,13 +180,19 @@ public void Index_valid_customisation_id_should_update_login_and_duration()
141180
// Given
142181
const int progressId = 13;
143182
var defaultCourseContent = CourseContentHelper.CreateDefaultCourseContent(CustomisationId);
183+
var course = CourseContentHelper.CreateDefaultCourse();
184+
185+
A.CallTo(() => courseService.GetCourse(CustomisationId)).Returns(course);
186+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, CustomisationId)).Returns(
187+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
188+
);
144189
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, CustomisationId))
145190
.Returns(defaultCourseContent);
146191
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId)).Returns(progressId);
147192
A.CallTo(() => courseContentService.GetProgressId(CandidateId, CustomisationId)).Returns(progressId);
148193

149194
// When
150-
controller.Index(CustomisationId);
195+
controller.Index(CustomisationId, progressID);
151196

152197
// Then
153198
A.CallTo(() => sessionService.StartOrUpdateDelegateSession(CandidateId, CustomisationId, A<ISession>._)).MustHaveHappened();
@@ -160,7 +205,7 @@ public void Index_invalid_customisation_id_should_not_insert_new_progress()
160205
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, CustomisationId)).Returns(null);
161206

162207
// When
163-
controller.Index(CustomisationId);
208+
controller.Index(CustomisationId, progressID);
164209

165210
// Then
166211
A.CallTo(() => courseContentService.GetOrCreateProgressId(A<int>._, A<int>._, A<int>._)).MustNotHaveHappened();
@@ -173,7 +218,7 @@ public void Index_invalid_customisation_id_should_not_update_login_and_duration(
173218
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, CustomisationId)).Returns(null);
174219

175220
// When
176-
controller.Index(CustomisationId);
221+
controller.Index(CustomisationId, progressID);
177222

178223
// Then
179224
A.CallTo(() => courseContentService.UpdateProgress(A<int>._)).MustNotHaveHappened();
@@ -186,7 +231,7 @@ public void Index_failing_to_insert_progress_should_not_update_progress()
186231
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId)).Returns(null);
187232

188233
// When
189-
controller.Index(CustomisationId);
234+
controller.Index(CustomisationId, progressID);
190235

191236
// Then
192237
A.CallTo(() => courseContentService.UpdateProgress(A<int>._)).MustNotHaveHappened();
@@ -197,13 +242,19 @@ public void Index_valid_customisationId_should_StartOrUpdate_course_sessions()
197242
{
198243
// Given
199244
var defaultCourseContent = CourseContentHelper.CreateDefaultCourseContent(CustomisationId);
245+
var course = CourseContentHelper.CreateDefaultCourse();
246+
247+
A.CallTo(() => courseService.GetCourse(CustomisationId)).Returns(course);
248+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, CustomisationId)).Returns(
249+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
250+
);
200251
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, CustomisationId))
201252
.Returns(defaultCourseContent);
202253
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId)).Returns(1);
203254
A.CallTo(() => courseContentService.GetProgressId(CandidateId, CustomisationId)).Returns(1);
204255

205256
// When
206-
controller.Index(CustomisationId);
257+
controller.Index(CustomisationId, progressID);
207258

208259
// Then
209260
A.CallTo(() => sessionService.StartOrUpdateDelegateSession(CandidateId, CustomisationId, httpContextSession)).MustHaveHappenedOnceExactly();
@@ -221,7 +272,7 @@ public void Index_invalid_customisationId_should_not_StartOrUpdate_course_sessio
221272
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId)).Returns(1);
222273

223274
// When
224-
controller.Index(CustomisationId);
275+
controller.Index(CustomisationId, progressID);
225276

226277
// Then
227278
A.CallTo(() => sessionService.StartOrUpdateDelegateSession(A<int>._, A<int>._, A<ISession>._)).MustNotHaveHappened();
@@ -236,7 +287,7 @@ public void Index_unable_to_enrol_should_not_StartOrUpdate_course_sessions()
236287
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId)).Returns(null);
237288

238289
// When
239-
controller.Index(CustomisationId);
290+
controller.Index(CustomisationId, progressID);
240291

241292
// Then
242293
A.CallTo(() => sessionService.StartOrUpdateDelegateSession(A<int>._, A<int>._, A<ISession>._)).MustNotHaveHappened();
@@ -291,14 +342,21 @@ public void Index_not_detects_id_manipulation_self_register_true()
291342
{
292343
// Given
293344
var expectedCourseContent = CourseContentHelper.CreateDefaultCourseContent(CustomisationId);
345+
346+
var course = CourseContentHelper.CreateDefaultCourse();
347+
348+
A.CallTo(() => courseService.GetCourse(CustomisationId)).Returns(course);
349+
A.CallTo(() => progressService.GetDelegateProgressForCourse(CandidateId, CustomisationId)).Returns(
350+
new List<Progress> { new Progress { ProgressId = 1, Completed = null, RemovedDate = null } }
351+
);
294352
A.CallTo(() => courseContentService.GetCourseContent(CandidateId, CustomisationId))
295353
.Returns(expectedCourseContent);
296354
A.CallTo(() => courseContentService.GetOrCreateProgressId(CandidateId, CustomisationId, CentreId)).Returns(10);
297355
A.CallTo(() => courseContentService.GetProgressId(CandidateId, CustomisationId)).Returns(null);
298356
A.CallTo(() => courseService.GetSelfRegister(CustomisationId)).Returns(true);
299357

300358
// When
301-
var result = controller.Index(CustomisationId);
359+
var result = controller.Index(CustomisationId, progressID);
302360

303361
// Then
304362
result.Should()

0 commit comments

Comments
 (0)