Skip to content

Commit ff9534d

Browse files
committed
Merge branch 'DLS-Release-v1.2.2' into UAT
2 parents df1a198 + 618ee37 commit ff9534d

File tree

13 files changed

+265
-17
lines changed

13 files changed

+265
-17
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace DigitalLearningSolutions.Data.Migrations
2+
{
3+
using FluentMigrator;
4+
5+
[Migration(202508190845)]
6+
public class AddSelfAssessmentProcessAgreed : Migration
7+
{
8+
public override void Up()
9+
{
10+
Alter.Table("CandidateAssessments").AddColumn("SelfAssessmentProcessAgreed").AsDateTime().Nullable();
11+
}
12+
13+
public override void Down()
14+
{
15+
Delete.Column("SelfAssessmentProcessAgreed").FromTable("CandidateAssessments");
16+
}
17+
}
18+
}

DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/CandidateAssessmentsDataService.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ CandidateAssessments AS CA LEFT OUTER JOIN
193193
SA.LinearNavigation,
194194
SA.UseDescriptionExpanders,
195195
SA.ManageOptionalCompetenciesPrompt,
196+
CAST(CASE WHEN CA.SelfAssessmentProcessAgreed IS NOT NULL THEN 1 ELSE 0 END AS BIT) AS SelfAssessmentProcessAgreed,
196197
CAST(CASE WHEN SA.SupervisorSelfAssessmentReview = 1 OR SA.SupervisorResultsReview = 1 THEN 1 ELSE 0 END AS BIT) AS IsSupervised,
197198
CASE
198199
WHEN (SELECT COUNT(*) FROM SelfAssessmentSupervisorRoles WHERE SelfAssessmentID = @selfAssessmentId AND AllowDelegateNomination = 1) > 0
@@ -241,7 +242,7 @@ GROUP BY
241242
CA.LaunchCount, CA.SubmittedDate, SA.LinearNavigation, SA.UseDescriptionExpanders,
242243
SA.ManageOptionalCompetenciesPrompt, SA.SupervisorSelfAssessmentReview, SA.SupervisorResultsReview,
243244
SA.ReviewerCommentsLabel,SA.EnforceRoleRequirementsForSignOff, SA.ManageSupervisorsDescription,CA.NonReportable,
244-
U.FirstName , U.LastName,SA.MinimumOptionalCompetencies",
245+
U.FirstName , U.LastName,SA.MinimumOptionalCompetencies, CA.SelfAssessmentProcessAgreed",
245246
new { delegateUserId, selfAssessmentId }
246247
);
247248
}
@@ -325,6 +326,22 @@ public void SetCompleteByDate(int selfAssessmentId, int delegateUserId, DateTime
325326
}
326327
}
327328

329+
public void MarkProgressAgreed(int selfAssessmentId, int delegateUserId)
330+
{
331+
var numberOfAffectedRows = connection.Execute(
332+
@"UPDATE CandidateAssessments SET SelfAssessmentProcessAgreed = GETDATE()
333+
WHERE SelfAssessmentID = @selfAssessmentId AND DelegateUserID = @delegateUserId",
334+
new { selfAssessmentId, delegateUserId }
335+
);
336+
if (numberOfAffectedRows < 1)
337+
{
338+
logger.LogWarning(
339+
"SelfAssessmentProcessAgreed not set as db update failed. " +
340+
$"Self assessment id: {selfAssessmentId}, Delegate User id: {delegateUserId}"
341+
);
342+
}
343+
}
344+
328345
public void SetUpdatedFlag(int selfAssessmentId, int delegateUserId, bool status)
329346
{
330347
var numberOfAffectedRows = connection.Execute(

DigitalLearningSolutions.Data/DataServices/SelfAssessmentDataService/SelfAssessmentDataService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ int competencyId
8989

9090
void SetBookmark(int selfAssessmentId, int delegateUserId, string bookmark);
9191

92+
void MarkProgressAgreed(int selfAssessmentId, int delegateUserId);
9293
IEnumerable<CandidateAssessment> GetCandidateAssessments(int delegateUserId, int selfAssessmentId);
9394

9495
// SelfAssessmentSupervisorDataService

DigitalLearningSolutions.Data/Models/SelfAssessments/CurrentSelfAssessment.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ public class CurrentSelfAssessment : SelfAssessment
2424
public int? DelegateUserId { get; set; }
2525
public string? DelegateName { get; set; }
2626
public string? EnrolledByFullName { get; set; }
27+
public bool SelfAssessmentProcessAgreed { get; set; }
2728
}
2829
}

DigitalLearningSolutions.Web.Tests/Controllers/LearningPortal/SelfAssessmentTests.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,5 +870,86 @@ public void SelfAssessmentOverview_Should_Return_View_With_Optional_Filter_Appli
870870

871871
result.Should().BeViewResult().ModelAs<SelfAssessmentOverviewViewModel>().CompetencyGroups.ToList()[0].Count().Should().Be(1);
872872
}
873+
874+
[Test]
875+
public void SelfAssessment_should_return_process_agreement_view_when_not_agreed_and_supervised()
876+
{
877+
// Given
878+
var selfAssessment = SelfAssessmentTestHelper.CreateDefaultSelfAssessment();
879+
selfAssessment.IsSupervised = true;
880+
selfAssessment.SelfAssessmentProcessAgreed = false;
881+
A.CallTo(() => selfAssessmentService.GetSelfAssessmentForCandidateById(DelegateUserId, SelfAssessmentId))
882+
.Returns(selfAssessment);
883+
A.CallTo(() => selfAssessmentService.GetAllSupervisorsForSelfAssessmentId(SelfAssessmentId, DelegateUserId))
884+
.Returns(new List<SelfAssessmentSupervisor>());
885+
886+
// When
887+
var result = controller.SelfAssessment(SelfAssessmentId);
888+
889+
// Then
890+
result.Should().BeViewResult()
891+
.WithViewName("SelfAssessments/AgreeSelfAssessmentProcess")
892+
.Model.Should().BeOfType<SelfAssessmentProcessViewModel>()
893+
.Which.SelfAssessmentID.Should().Be(SelfAssessmentId);
894+
}
895+
896+
[Test]
897+
public void SelfAssessment_should_return_description_view_when_process_agreed_or_not_supervised()
898+
{
899+
// Given
900+
var selfAssessment = SelfAssessmentTestHelper.CreateDefaultSelfAssessment();
901+
selfAssessment.IsSupervised = false; // or set SelfAssessmentProcessAgreed = true
902+
A.CallTo(() => selfAssessmentService.GetSelfAssessmentForCandidateById(DelegateUserId, SelfAssessmentId))
903+
.Returns(selfAssessment);
904+
A.CallTo(() => selfAssessmentService.GetAllSupervisorsForSelfAssessmentId(SelfAssessmentId, DelegateUserId))
905+
.Returns(new List<SelfAssessmentSupervisor>());
906+
var expectedModel = new SelfAssessmentDescriptionViewModel(selfAssessment, new List<SelfAssessmentSupervisor>());
907+
908+
// When
909+
var result = controller.SelfAssessment(SelfAssessmentId);
910+
911+
// Then
912+
result.Should().BeViewResult()
913+
.WithViewName("SelfAssessments/SelfAssessmentDescription")
914+
.Model.Should().BeEquivalentTo(expectedModel);
915+
}
916+
917+
[Test]
918+
public void ProcessAgreed_should_return_agree_view_when_modelstate_invalid()
919+
{
920+
// Given
921+
var model = new SelfAssessmentProcessViewModel { SelfAssessmentID = SelfAssessmentId };
922+
controller.ModelState.AddModelError("Test", "Error");
923+
924+
// When
925+
var result = controller.ProcessAgreed(model);
926+
927+
// Then
928+
result.Should().BeViewResult()
929+
.WithViewName("SelfAssessments/AgreeSelfAssessmentProcess")
930+
.Model.Should().Be(model);
931+
}
932+
933+
[Test]
934+
public void ProcessAgreed_should_mark_progress_and_return_description_view()
935+
{
936+
// Given
937+
var selfAssessment = SelfAssessmentTestHelper.CreateDefaultSelfAssessment();
938+
var supervisors = new List<SelfAssessmentSupervisor>();
939+
var model = new SelfAssessmentProcessViewModel { SelfAssessmentID = SelfAssessmentId };
940+
A.CallTo(() => selfAssessmentService.GetSelfAssessmentForCandidateById(DelegateUserId, SelfAssessmentId))
941+
.Returns(selfAssessment);
942+
A.CallTo(() => selfAssessmentService.GetAllSupervisorsForSelfAssessmentId(SelfAssessmentId, DelegateUserId))
943+
.Returns(supervisors);
944+
945+
// When
946+
var result = controller.ProcessAgreed(model);
947+
948+
// Then
949+
A.CallTo(() => selfAssessmentService.MarkProgressAgreed(SelfAssessmentId, DelegateUserId)).MustHaveHappened();
950+
result.Should().BeViewResult()
951+
.WithViewName("SelfAssessments/SelfAssessmentDescription")
952+
.Model.Should().BeEquivalentTo(new SelfAssessmentDescriptionViewModel(selfAssessment, supervisors));
953+
}
873954
}
874955
}

DigitalLearningSolutions.Web/Controllers/LearningPortalController/SelfAssessment.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,55 @@ public IActionResult SelfAssessment(int selfAssessmentId)
6868
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
6969
}
7070

71+
if (!selfAssessment.SelfAssessmentProcessAgreed && selfAssessment.IsSupervised)
72+
{
73+
var processmodel = new SelfAssessmentProcessViewModel()
74+
{
75+
SelfAssessmentID = selfAssessmentId,
76+
Vocabulary = selfAssessment.Vocabulary,
77+
VocabPlural = FrameworkVocabularyHelper.VocabularyPlural(selfAssessment.Vocabulary)
78+
};
79+
return View("SelfAssessments/AgreeSelfAssessmentProcess", processmodel);
80+
}
81+
7182
selfAssessmentService.IncrementLaunchCount(selfAssessmentId, delegateUserId);
7283
selfAssessmentService.UpdateLastAccessed(selfAssessmentId, delegateUserId);
7384
var supervisors = selfAssessmentService.GetAllSupervisorsForSelfAssessmentId(
7485
selfAssessmentId,
7586
delegateUserId
7687
).ToList();
7788
var model = new SelfAssessmentDescriptionViewModel(selfAssessment, supervisors);
89+
7890
return View("SelfAssessments/SelfAssessmentDescription", model);
7991
}
8092

93+
[HttpPost]
94+
public IActionResult ProcessAgreed(SelfAssessmentProcessViewModel model)
95+
{
96+
if (!ModelState.IsValid)
97+
{
98+
return View("SelfAssessments/AgreeSelfAssessmentProcess", model);
99+
}
100+
var delegateUserId = User.GetUserIdKnownNotNull();
101+
int selfAssessmentId = model.SelfAssessmentID;
102+
var selfAssessment = selfAssessmentService.GetSelfAssessmentForCandidateById(delegateUserId, selfAssessmentId);
103+
if (selfAssessment == null)
104+
{
105+
logger.LogWarning(
106+
$"Attempt to display self assessment description for user {delegateUserId} with no self assessment"
107+
);
108+
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 403 });
109+
}
110+
var supervisors = selfAssessmentService.GetAllSupervisorsForSelfAssessmentId(
111+
selfAssessmentId,
112+
delegateUserId
113+
).ToList();
114+
var selfAssessmentDescriptionViewModel = new SelfAssessmentDescriptionViewModel(selfAssessment, supervisors);
115+
selfAssessmentService.MarkProgressAgreed(selfAssessmentId, delegateUserId);
116+
return View("SelfAssessments/SelfAssessmentDescription", selfAssessmentDescriptionViewModel);
117+
118+
}
119+
81120
[ServiceFilter(typeof(IsCentreAuthorizedSelfAssessment))]
82121
[Route("/LearningPortal/SelfAssessment/{selfAssessmentId:int}/{competencyNumber:int}")]
83122
public IActionResult SelfAssessmentCompetency(int selfAssessmentId, int competencyNumber)

DigitalLearningSolutions.Web/Services/SelfAssessmentService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public interface ISelfAssessmentService
3232

3333
void SetCompleteByDate(int selfAssessmentId, int delegateUserId, DateTime? completeByDate);
3434

35+
void MarkProgressAgreed(int selfAssessmentId, int delegateUserId);
3536
bool CanDelegateAccessSelfAssessment(int delegateUserId, int selfAssessmentId, int centreId);
3637

3738
// Competencies
@@ -216,6 +217,11 @@ public void SetCompleteByDate(int selfAssessmentId, int delegateUserId, DateTime
216217
selfAssessmentDataService.SetCompleteByDate(selfAssessmentId, delegateUserId, completeByDate);
217218
}
218219

220+
public void MarkProgressAgreed(int selfAssessmentId, int delegateUserId)
221+
{
222+
selfAssessmentDataService.MarkProgressAgreed(selfAssessmentId, delegateUserId);
223+
}
224+
219225
public IEnumerable<Competency> GetCandidateAssessmentResultsById(int candidateAssessmentId, int adminId, int? selfAssessmentResultId = null)
220226
{
221227
return selfAssessmentDataService.GetCandidateAssessmentResultsById(candidateAssessmentId, adminId, selfAssessmentResultId);

DigitalLearningSolutions.Web/Styles/nhsuk.scss

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ body:not(.js-enabled) {
4949

5050
/* .nhsuk-header--transactional brought from live design-system, not in current implentation */
5151
.nhsuk-header--transactional {
52-
.nhsuk-header__container {
53-
justify-content: normal;
54-
}
5552

5653
.nhsuk-header__link {
5754
display: block;
@@ -137,7 +134,18 @@ input[type=file].nhsuk-input--error {
137134
text-align: center;
138135
}
139136

137+
.nhsuk-header__logo {
138+
display: flex;
139+
justify-content: space-between;
140+
}
140141

142+
@media (max-width: 600px) {
143+
.nhsuk-header__transactional--logo {
144+
flex-direction: column;
145+
align-items: flex-start;
146+
gap: 4px;
147+
}
148+
}
141149

142150
/*
143151
styles/index.scss has the following nhsuk dependancies - FGC 2/6/25

DigitalLearningSolutions.Web/ViewModels/LearningPortal/SelfAssessments/SelfAssessmentDescriptionViewModel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public class SelfAssessmentDescriptionViewModel
1818
public readonly string VocabPlural;
1919
public readonly string? Vocabulary;
2020
public readonly bool NonReportable;
21+
public bool SelfAssessmentProcessAgreed { get; set; }
2122

2223
public SelfAssessmentDescriptionViewModel(
2324
CurrentSelfAssessment selfAssessment,
@@ -37,6 +38,7 @@ List<SelfAssessmentSupervisor> supervisors
3738
Vocabulary = selfAssessment.Vocabulary;
3839
VocabPlural = FrameworkVocabularyHelper.VocabularyPlural(selfAssessment.Vocabulary);
3940
NonReportable = selfAssessment.NonReportable;
41+
SelfAssessmentProcessAgreed = selfAssessment.SelfAssessmentProcessAgreed;
4042
}
4143

4244
public List<SelfAssessmentSupervisor> Supervisors { get; set; }
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace DigitalLearningSolutions.Web.ViewModels.LearningPortal.SelfAssessments
2+
{
3+
using System.Collections.Generic;
4+
using DigitalLearningSolutions.Data.Models.SelfAssessments;
5+
using DigitalLearningSolutions.Web.Attributes;
6+
using DigitalLearningSolutions.Web.Helpers;
7+
8+
public class SelfAssessmentProcessViewModel
9+
{
10+
public int SelfAssessmentID { get; set; }
11+
[BooleanMustBeTrue(ErrorMessage = "Please tick the checkbox to confirm that you understand and agree to the self-assessment process")]
12+
public bool ActionConfirmed { get; set; }
13+
14+
public string? VocabPlural { get; set; }
15+
public string? Vocabulary { get; set; }
16+
17+
}
18+
}

0 commit comments

Comments
 (0)