Skip to content

Commit cdc19f3

Browse files
authored
Merge pull request #3371 from TechnologyEnhancedLearning/DLS-Release-v1.2.3
Dls release v1.2.3 to UAT
2 parents 468e0b2 + 872033a commit cdc19f3

File tree

17 files changed

+201
-69
lines changed

17 files changed

+201
-69
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace DigitalLearningSolutions.Data.Migrations
2+
{
3+
using FluentMigrator;
4+
[Migration(202508191440)]
5+
public class CreateSendRetiringSelfAssessmentNotificationSP : Migration
6+
{
7+
public override void Up()
8+
{
9+
string generalTELTeam =
10+
@"[
11+
{ ""FirstName"":"""", ""LastName"":"""", ""Email"":""[email protected]"" },
12+
{ ""FirstName"":""Anna"", ""LastName"":""Athanasopoulou"", ""Email"":""[email protected]"" },
13+
{ ""FirstName"":""Benjamin"", ""LastName"":""Witton"", ""Email"":""[email protected]"" }
14+
]";
15+
16+
Execute.Sql(@$"IF NOT EXISTS (SELECT ConfigID FROM Config WHERE ConfigName = 'GeneralTELTeam')
17+
BEGIN
18+
INSERT INTO Config VALUES ('GeneralTELTeam', '{generalTELTeam}', 0,GETDATE(), GETDATE())
19+
END"
20+
);
21+
22+
Execute.Sql(Properties.Resources.TD_5552_SendRetiringNotification);
23+
}
24+
public override void Down()
25+
{
26+
Execute.Sql(@"DELETE FROM Config WHERE ConfigName = N'GeneralTELTeam'");
27+
28+
Execute.Sql("DROP PROCEDURE [dbo].[SendRetiringSelfAssessmentNotification]");
29+
}
30+
}
31+
}

DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,4 +505,7 @@
505505
<data name="TD_5535_Alter_GetActivitiesForDelegateEnrolment_Up" type="System.Resources.ResXFileRef, System.Windows.Forms">
506506
<value>..\Scripts\TD-5535-Alter_GetActivitiesForDelegateEnrolment_Up.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
507507
</data>
508+
<data name="TD_5552_SendRetiringNotification" type="System.Resources.ResXFileRef, System.Windows.Forms">
509+
<value>..\Scripts\TD-5552-SendRetiringNotification.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
510+
</data>
508511
</root>
Binary file not shown.

DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnRoleProfile.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ public class SessionEnrolOnRoleProfile
66
public int? SelfAssessmentID { get; set; }
77
public DateTime? CompleteByDate { get; set; }
88
public int? SelfAssessmentSupervisorRoleId { get; set; }
9+
public bool ActionConfirmed { get; set; }
910
}
1011
}

DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterDelegateByCentreControllerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ public void LearnerInformationPost_updates_tempdata_correctly()
176176
const string answer4 = "answer4";
177177
const string answer5 = "answer5";
178178
const string answer6 = "answer6";
179-
const string professionalRegistrationNumber = "PRN1234";
179+
const string professionalRegistrationNumber = "PR123456";
180180
var model = new LearnerInformationViewModel
181181
{
182182
JobGroup = jobGroupId,

DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/Delegates/EditDelegateControllerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public void Index_post_returns_view_with_model_error_with_invalid_prn()
175175
result.As<ViewResult>().Model.Should().BeOfType<EditDelegateViewModel>();
176176
AssertModelStateErrorIsExpected(
177177
result,
178-
"Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed"
178+
ErrorMessagesTestHelper.InvalidFormatError
179179
);
180180
A.CallTo(() => userService.GetDelegateById(A<int>._)).MustNotHaveHappened();
181181
}

DigitalLearningSolutions.Web.Tests/Helpers/ProfessionalRegistrationNumberHelperTests.cs

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
namespace DigitalLearningSolutions.Web.Tests.Helpers
22
{
3-
using System.Linq;
43
using DigitalLearningSolutions.Web.Helpers;
4+
using DigitalLearningSolutions.Web.Tests.TestHelpers;
55
using FluentAssertions;
66
using FluentAssertions.Execution;
77
using Microsoft.AspNetCore.Mvc.ModelBinding;
88
using NUnit.Framework;
9+
using System.Linq;
910

1011
public class ProfessionalRegistrationNumberHelperTests
1112
{
@@ -70,7 +71,7 @@ public void ValidateProfessionalRegistrationNumber_does_not_set_errors_when_vali
7071
{
7172
// Given
7273
var state = new ModelStateDictionary();
73-
const string validPrn = "abc-123";
74+
const string validPrn = "AB123456";
7475

7576
// When
7677
ProfessionalRegistrationNumberHelper.ValidateProfessionalRegistrationNumber(
@@ -104,22 +105,13 @@ public void ValidateProfessionalRegistrationNumber_sets_error_when_hasPrn_is_not
104105
}
105106
}
106107

107-
[TestCase(null, "Enter a professional registration number")]
108-
[TestCase("", "Enter a professional registration number")]
109-
[TestCase("123", "Professional registration number must be between 5 and 20 characters")]
110-
[TestCase("0123456789-0123456789", "Professional registration number must be between 5 and 20 characters")]
111-
[TestCase(
112-
"01234_",
113-
"Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed"
114-
)]
115-
[TestCase(
116-
"01234 ",
117-
"Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed"
118-
)]
119-
[TestCase(
120-
"01234$",
121-
"Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed"
122-
)]
108+
[TestCase(null, ErrorMessagesTestHelper.MissingNumberError)]
109+
[TestCase("", ErrorMessagesTestHelper.MissingNumberError)]
110+
[TestCase("1234", ErrorMessagesTestHelper.LengthError)]
111+
[TestCase("1234", ErrorMessagesTestHelper.LengthError)]
112+
[TestCase("01234_", ErrorMessagesTestHelper.InvalidFormatError)]
113+
[TestCase("01234 ", ErrorMessagesTestHelper.InvalidFormatError)]
114+
[TestCase("01234$", ErrorMessagesTestHelper.InvalidFormatError)]
123115
public void ValidateProfessionalRegistrationNumber_sets_error_when_prn_is_invalid(
124116
string prn,
125117
string expectedError
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+

2+
namespace DigitalLearningSolutions.Web.Tests.TestHelpers
3+
{
4+
public static class ErrorMessagesTestHelper
5+
{
6+
public const string InvalidFormatError =
7+
"Invalid professional registration number format. " +
8+
"Valid formats include: 7 digits (e.g., 1234567), 1–2 letters followed by 6 digits (e.g., AB123456), " +
9+
"4–8 digits, an optional 'P' plus 5–6 digits, 'C' or 'P' plus 6 digits, " +
10+
"an optional letter plus 5–6 digits, 'L' plus 4–6 digits, " +
11+
"or 2 digits followed by a hyphen and 4–5 alphanumeric characters (e.g., 12-AB123).";
12+
13+
public const string MissingNumberError = "Enter a professional registration number";
14+
public const string LengthError = "Professional registration number must be between 5 and 20 characters";
15+
16+
}
17+
}

DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ public IActionResult ReviewDelegateSelfAssessment(int supervisorDelegateId, int
391391
foreach (var competency in competencies)
392392
{
393393
competency.CompetencyFlags = flags.Where(f => f.CompetencyId == competency.Id);
394-
};
394+
}
395395

396396
if (superviseDelegate.DelegateUserID != null)
397397
{
@@ -784,48 +784,69 @@ public IActionResult EnrolSetRoleProfile(int supervisorDelegateId, int selfAsses
784784
};
785785
return View("EnrolDelegateOnProfileAssessment", model);
786786
}
787-
var retirementDate = selfAssessmentService.GetSelfAssessmentById(selfAssessmentID).RetirementDate;
788-
if (retirementDate?.Date is DateTime date && date >= DateTime.Today &&
789-
date <= DateTime.Today.AddDays(14))
790-
{
791-
var model = new RetiringSelfAssessmentViewModel()
792-
{
793-
SelfAssessmentID = selfAssessmentID,
794-
SupervisorDelegateID = supervisorDelegateId,
795-
RetirementDate = retirementDate
796-
};
797-
return View("ConfirmRetiringSelfAssessment", model);
798-
}
799787

800788
sessionEnrolOnRoleProfile.SelfAssessmentID = selfAssessmentID;
801789
multiPageFormService.SetMultiPageFormData(
802790
sessionEnrolOnRoleProfile,
803791
MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment,
804792
TempData
805793
);
794+
795+
var retirementDate = selfAssessmentService.GetSelfAssessmentById(selfAssessmentID).RetirementDate;
796+
if (CheckRetirementDate(retirementDate))
797+
{
798+
return RedirectToAction("ConfirmRetiringSelfAssessment", "Supervisor", new { supervisorDelegateId });
799+
}
800+
806801
return RedirectToAction(
807802
"EnrolDelegateCompleteBy",
808803
"Supervisor",
809804
new { supervisorDelegateId = supervisorDelegateId }
810805
);
811806
}
812807

813-
[HttpPost]
814-
public IActionResult RetiringSelfAssessmentConfirmed(RetiringSelfAssessmentViewModel retiringSelfAssessment)
808+
[Route("/Supervisor/Staff/{supervisorDelegateId}/ProfileAssessment/Enrol/Confirm")]
809+
public IActionResult ConfirmRetiringSelfAssessment(int supervisorDelegateId)
815810
{
816-
if (ModelState.IsValid && retiringSelfAssessment.ActionConfirmed)
811+
var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData<SessionEnrolOnRoleProfile>(
812+
MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment,
813+
TempData
814+
).GetAwaiter().GetResult();
815+
816+
var retirementDate = selfAssessmentService.GetSelfAssessmentById((int)sessionEnrolOnRoleProfile.SelfAssessmentID).RetirementDate;
817+
if (!CheckRetirementDate((retirementDate)))
817818
{
818-
var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData<SessionEnrolOnRoleProfile>(
819+
return RedirectToAction("StatusCode", "LearningSolutions", new { code = 410 });
820+
}
821+
var model = new RetiringSelfAssessmentViewModel()
822+
{
823+
SelfAssessmentID = (int)sessionEnrolOnRoleProfile.SelfAssessmentID,
824+
SupervisorDelegateID = supervisorDelegateId,
825+
RetirementDate = retirementDate,
826+
ActionConfirmed = sessionEnrolOnRoleProfile.ActionConfirmed
827+
};
828+
return View("ConfirmRetiringSelfAssessment", model);
829+
}
830+
831+
[HttpPost]
832+
[Route("/Supervisor/Staff/{supervisorDelegateId}/ProfileAssessment/Enrol/Confirm")]
833+
public IActionResult ConfirmRetiringSelfAssessment(RetiringSelfAssessmentViewModel retiringSelfAssessment)
834+
{
835+
var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData<SessionEnrolOnRoleProfile>(
819836
MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment,
820837
TempData
821838
).GetAwaiter().GetResult();
822839

823-
sessionEnrolOnRoleProfile.SelfAssessmentID = retiringSelfAssessment.SelfAssessmentID;
824-
multiPageFormService.SetMultiPageFormData(
825-
sessionEnrolOnRoleProfile,
826-
MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment,
827-
TempData
828-
);
840+
sessionEnrolOnRoleProfile.SelfAssessmentID = retiringSelfAssessment.SelfAssessmentID;
841+
sessionEnrolOnRoleProfile.ActionConfirmed = retiringSelfAssessment.ActionConfirmed;
842+
multiPageFormService.SetMultiPageFormData(
843+
sessionEnrolOnRoleProfile,
844+
MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment,
845+
TempData
846+
);
847+
848+
if (ModelState.IsValid && retiringSelfAssessment.ActionConfirmed)
849+
{
829850
return RedirectToAction(
830851
"EnrolDelegateCompleteBy",
831852
"Supervisor",
@@ -850,19 +871,21 @@ public IActionResult EnrolDelegateCompleteBy(int supervisorDelegateId, int? day,
850871
MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment,
851872
TempData
852873
).GetAwaiter().GetResult();
853-
multiPageFormService.SetMultiPageFormData(
854-
sessionEnrolOnRoleProfile,
855-
MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment,
856-
TempData
857-
);
874+
875+
var retirementDate = selfAssessmentService.GetSelfAssessmentById((int)sessionEnrolOnRoleProfile.SelfAssessmentID).RetirementDate;
876+
if (CheckRetirementDate(retirementDate) && !sessionEnrolOnRoleProfile.ActionConfirmed)
877+
{
878+
return RedirectToAction("ConfirmRetiringSelfAssessment", "Supervisor", new { supervisorDelegateId });
879+
}
858880
var supervisorDelegate =
859881
supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0);
860882
var roleProfile = supervisorService.GetRoleProfileById((int)sessionEnrolOnRoleProfile.SelfAssessmentID);
861883
var model = new EnrolDelegateSetCompletByDateViewModel()
862884
{
863885
SupervisorDelegateDetail = supervisorDelegate,
864886
RoleProfile = roleProfile,
865-
CompleteByDate = sessionEnrolOnRoleProfile.CompleteByDate
887+
CompleteByDate = sessionEnrolOnRoleProfile.CompleteByDate,
888+
ActionConfirmed = sessionEnrolOnRoleProfile.ActionConfirmed
866889
};
867890
if (day != null && month != null && year != null)
868891
{
@@ -1008,6 +1031,13 @@ public IActionResult EnrolDelegateSummary(int supervisorDelegateId)
10081031
MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment,
10091032
TempData
10101033
);
1034+
1035+
var retirementDate = selfAssessmentService.GetSelfAssessmentById((int)sessionEnrolOnRoleProfile.SelfAssessmentID).RetirementDate;
1036+
if (CheckRetirementDate(retirementDate) && !sessionEnrolOnRoleProfile.ActionConfirmed)
1037+
{
1038+
return RedirectToAction("ConfirmRetiringSelfAssessment", "Supervisor", new { supervisorDelegateId });
1039+
}
1040+
10111041
var supervisorDelegate =
10121042
supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0);
10131043
var roleProfile = supervisorService.GetRoleProfileById((int)sessionEnrolOnRoleProfile.SelfAssessmentID);
@@ -1035,6 +1065,7 @@ public IActionResult EnrolDelegateSummary(int supervisorDelegateId)
10351065
ViewBag.completeByMonth = TempData["completeByMonth"];
10361066
ViewBag.completeByYear = TempData["completeByYear"];
10371067
ViewBag.navigatedFrom = TempData["navigatedFrom"];
1068+
ViewBag.actionConfirmed = sessionEnrolOnRoleProfile.ActionConfirmed;
10381069
return View("EnrolDelegateSummary", model);
10391070
}
10401071

@@ -1558,5 +1589,15 @@ private static string RenderRazorViewToString(Controller controller, string view
15581589
return sw.GetStringBuilder().ToString();
15591590
}
15601591
}
1592+
1593+
private bool CheckRetirementDate(DateTime? date)
1594+
{
1595+
if (date == null)
1596+
return false;
1597+
1598+
DateTime retirementOffsetDate = DateTime.Today.AddDays(14);
1599+
DateTime today = DateTime.Today;
1600+
return (date >= today && date <= retirementOffsetDate);
1601+
}
15611602
}
15621603
}

0 commit comments

Comments
 (0)