diff --git a/DigitalLearningSolutions.Data.Migrations/202508191440_CreateSendRetiringSelfAssessmentNotificationSP.cs b/DigitalLearningSolutions.Data.Migrations/202508191440_CreateSendRetiringSelfAssessmentNotificationSP.cs new file mode 100644 index 0000000000..e657f3d384 --- /dev/null +++ b/DigitalLearningSolutions.Data.Migrations/202508191440_CreateSendRetiringSelfAssessmentNotificationSP.cs @@ -0,0 +1,31 @@ +namespace DigitalLearningSolutions.Data.Migrations +{ + using FluentMigrator; + [Migration(202508191440)] + public class CreateSendRetiringSelfAssessmentNotificationSP : Migration + { + public override void Up() + { + string generalTELTeam = + @"[ + { ""FirstName"":"""", ""LastName"":"""", ""Email"":""Support@dls.nhs.uk"" }, + { ""FirstName"":""Anna"", ""LastName"":""Athanasopoulou"", ""Email"":""anna.athanasopoulou@nhs.net"" }, + { ""FirstName"":""Benjamin"", ""LastName"":""Witton"", ""Email"":""Benjamin.witton1@nhs.net"" } + ]"; + + Execute.Sql(@$"IF NOT EXISTS (SELECT ConfigID FROM Config WHERE ConfigName = 'GeneralTELTeam') + BEGIN + INSERT INTO Config VALUES ('GeneralTELTeam', '{generalTELTeam}', 0,GETDATE(), GETDATE()) + END" + ); + + Execute.Sql(Properties.Resources.TD_5552_SendRetiringNotification); + } + public override void Down() + { + Execute.Sql(@"DELETE FROM Config WHERE ConfigName = N'GeneralTELTeam'"); + + Execute.Sql("DROP PROCEDURE [dbo].[SendRetiringSelfAssessmentNotification]"); + } + } +} diff --git a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs index 631af7bc66..5a70756bd6 100644 --- a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs +++ b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.Designer.cs @@ -2564,6 +2564,34 @@ internal static string TD_5535_Alter_GetActivitiesForDelegateEnrolment_Up { } } + /// + /// Looks up a localized string similar to SET ANSI_NULLS ON + ///GO + /// + ///SET QUOTED_IDENTIFIER ON + ///GO + /// + /// + /// + ///-- ============================================= + ///-- Author: Auldrin Possa + ///-- Create date: 04/08/2015 + ///-- Description: Uses DB mail to send notification to delegates on retiring self assessment. + ///-- ============================================= + ///CREATE PROCEDURE [dbo].[SendRetiringSelfAssessmentNotification] + /// @SelfAssessmentId int, + /// @TestOnly bit + ///AS + ///BEGIN + /// -- SET NOCOUNT ON added to prevent extra result sets from + /// -- interfering with SELEC [rest of string was truncated]";. + /// + internal static string TD_5552_SendRetiringNotification { + get { + return ResourceManager.GetString("TD_5552_SendRetiringNotification", resourceCulture); + } + } + /// /// Looks up a localized string similar to IF OBJECT_ID('dbo.IndexOptimize', 'P') IS NOT NULL DROP PROCEDURE dbo.IndexOptimize; ///IF OBJECT_ID('dbo.CommandExecute', 'P') IS NOT NULL DROP PROCEDURE dbo.CommandExecute; diff --git a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx index 41e1de40a2..138250507c 100644 --- a/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx +++ b/DigitalLearningSolutions.Data.Migrations/Properties/Resources.resx @@ -505,4 +505,7 @@ ..\Scripts\TD-5535-Alter_GetActivitiesForDelegateEnrolment_Up.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + + ..\Scripts\TD-5552-SendRetiringNotification.sql;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16 + \ No newline at end of file diff --git a/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5552-SendRetiringNotification.sql b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5552-SendRetiringNotification.sql new file mode 100644 index 0000000000..a5c5437375 Binary files /dev/null and b/DigitalLearningSolutions.Data.Migrations/Scripts/TD-5552-SendRetiringNotification.sql differ diff --git a/DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnRoleProfile.cs b/DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnRoleProfile.cs index 29b7b1b261..6d2f3e777a 100644 --- a/DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnRoleProfile.cs +++ b/DigitalLearningSolutions.Data/Models/SessionData/Supervisor/SessionEnrolOnRoleProfile.cs @@ -6,5 +6,6 @@ public class SessionEnrolOnRoleProfile public int? SelfAssessmentID { get; set; } public DateTime? CompleteByDate { get; set; } public int? SelfAssessmentSupervisorRoleId { get; set; } + public bool ActionConfirmed { get; set; } } } diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterDelegateByCentreControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterDelegateByCentreControllerTests.cs index 0d4a77fc61..0040c2b514 100644 --- a/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterDelegateByCentreControllerTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Controllers/Register/RegisterDelegateByCentreControllerTests.cs @@ -176,7 +176,7 @@ public void LearnerInformationPost_updates_tempdata_correctly() const string answer4 = "answer4"; const string answer5 = "answer5"; const string answer6 = "answer6"; - const string professionalRegistrationNumber = "PRN1234"; + const string professionalRegistrationNumber = "PR123456"; var model = new LearnerInformationViewModel { JobGroup = jobGroupId, diff --git a/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/Delegates/EditDelegateControllerTests.cs b/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/Delegates/EditDelegateControllerTests.cs index 5c5df8ac44..c08f3dbe35 100644 --- a/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/Delegates/EditDelegateControllerTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Controllers/TrackingSystem/Delegates/EditDelegateControllerTests.cs @@ -175,7 +175,7 @@ public void Index_post_returns_view_with_model_error_with_invalid_prn() result.As().Model.Should().BeOfType(); AssertModelStateErrorIsExpected( result, - "Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed" + ErrorMessagesTestHelper.InvalidFormatError ); A.CallTo(() => userService.GetDelegateById(A._)).MustNotHaveHappened(); } diff --git a/DigitalLearningSolutions.Web.Tests/Helpers/ProfessionalRegistrationNumberHelperTests.cs b/DigitalLearningSolutions.Web.Tests/Helpers/ProfessionalRegistrationNumberHelperTests.cs index d78c74f042..a7270f280d 100644 --- a/DigitalLearningSolutions.Web.Tests/Helpers/ProfessionalRegistrationNumberHelperTests.cs +++ b/DigitalLearningSolutions.Web.Tests/Helpers/ProfessionalRegistrationNumberHelperTests.cs @@ -1,11 +1,12 @@ namespace DigitalLearningSolutions.Web.Tests.Helpers { - using System.Linq; using DigitalLearningSolutions.Web.Helpers; + using DigitalLearningSolutions.Web.Tests.TestHelpers; using FluentAssertions; using FluentAssertions.Execution; using Microsoft.AspNetCore.Mvc.ModelBinding; using NUnit.Framework; + using System.Linq; public class ProfessionalRegistrationNumberHelperTests { @@ -70,7 +71,7 @@ public void ValidateProfessionalRegistrationNumber_does_not_set_errors_when_vali { // Given var state = new ModelStateDictionary(); - const string validPrn = "abc-123"; + const string validPrn = "AB123456"; // When ProfessionalRegistrationNumberHelper.ValidateProfessionalRegistrationNumber( @@ -104,22 +105,13 @@ public void ValidateProfessionalRegistrationNumber_sets_error_when_hasPrn_is_not } } - [TestCase(null, "Enter a professional registration number")] - [TestCase("", "Enter a professional registration number")] - [TestCase("123", "Professional registration number must be between 5 and 20 characters")] - [TestCase("0123456789-0123456789", "Professional registration number must be between 5 and 20 characters")] - [TestCase( - "01234_", - "Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed" - )] - [TestCase( - "01234 ", - "Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed" - )] - [TestCase( - "01234$", - "Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed" - )] + [TestCase(null, ErrorMessagesTestHelper.MissingNumberError)] + [TestCase("", ErrorMessagesTestHelper.MissingNumberError)] + [TestCase("1234", ErrorMessagesTestHelper.LengthError)] + [TestCase("1234", ErrorMessagesTestHelper.LengthError)] + [TestCase("01234_", ErrorMessagesTestHelper.InvalidFormatError)] + [TestCase("01234 ", ErrorMessagesTestHelper.InvalidFormatError)] + [TestCase("01234$", ErrorMessagesTestHelper.InvalidFormatError)] public void ValidateProfessionalRegistrationNumber_sets_error_when_prn_is_invalid( string prn, string expectedError diff --git a/DigitalLearningSolutions.Web.Tests/TestHelpers/ErrorMessagesTestHelper.cs b/DigitalLearningSolutions.Web.Tests/TestHelpers/ErrorMessagesTestHelper.cs new file mode 100644 index 0000000000..7636944e7a --- /dev/null +++ b/DigitalLearningSolutions.Web.Tests/TestHelpers/ErrorMessagesTestHelper.cs @@ -0,0 +1,17 @@ + +namespace DigitalLearningSolutions.Web.Tests.TestHelpers +{ + public static class ErrorMessagesTestHelper + { + public const string InvalidFormatError = + "Invalid professional registration number format. " + + "Valid formats include: 7 digits (e.g., 1234567), 1–2 letters followed by 6 digits (e.g., AB123456), " + + "4–8 digits, an optional 'P' plus 5–6 digits, 'C' or 'P' plus 6 digits, " + + "an optional letter plus 5–6 digits, 'L' plus 4–6 digits, " + + "or 2 digits followed by a hyphen and 4–5 alphanumeric characters (e.g., 12-AB123)."; + + public const string MissingNumberError = "Enter a professional registration number"; + public const string LengthError = "Professional registration number must be between 5 and 20 characters"; + + } +} diff --git a/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs b/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs index 8a42ac8f73..fbeea40adb 100644 --- a/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs +++ b/DigitalLearningSolutions.Web/Controllers/SupervisorController/Supervisor.cs @@ -391,7 +391,7 @@ public IActionResult ReviewDelegateSelfAssessment(int supervisorDelegateId, int foreach (var competency in competencies) { competency.CompetencyFlags = flags.Where(f => f.CompetencyId == competency.Id); - }; + } if (superviseDelegate.DelegateUserID != null) { @@ -784,18 +784,6 @@ public IActionResult EnrolSetRoleProfile(int supervisorDelegateId, int selfAsses }; return View("EnrolDelegateOnProfileAssessment", model); } - var retirementDate = selfAssessmentService.GetSelfAssessmentById(selfAssessmentID).RetirementDate; - if (retirementDate?.Date is DateTime date && date >= DateTime.Today && - date <= DateTime.Today.AddDays(14)) - { - var model = new RetiringSelfAssessmentViewModel() - { - SelfAssessmentID = selfAssessmentID, - SupervisorDelegateID = supervisorDelegateId, - RetirementDate = retirementDate - }; - return View("ConfirmRetiringSelfAssessment", model); - } sessionEnrolOnRoleProfile.SelfAssessmentID = selfAssessmentID; multiPageFormService.SetMultiPageFormData( @@ -803,6 +791,13 @@ public IActionResult EnrolSetRoleProfile(int supervisorDelegateId, int selfAsses MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); + + var retirementDate = selfAssessmentService.GetSelfAssessmentById(selfAssessmentID).RetirementDate; + if (CheckRetirementDate(retirementDate)) + { + return RedirectToAction("ConfirmRetiringSelfAssessment", "Supervisor", new { supervisorDelegateId }); + } + return RedirectToAction( "EnrolDelegateCompleteBy", "Supervisor", @@ -810,22 +805,48 @@ public IActionResult EnrolSetRoleProfile(int supervisorDelegateId, int selfAsses ); } - [HttpPost] - public IActionResult RetiringSelfAssessmentConfirmed(RetiringSelfAssessmentViewModel retiringSelfAssessment) + [Route("/Supervisor/Staff/{supervisorDelegateId}/ProfileAssessment/Enrol/Confirm")] + public IActionResult ConfirmRetiringSelfAssessment(int supervisorDelegateId) { - if (ModelState.IsValid && retiringSelfAssessment.ActionConfirmed) + var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData( + MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, + TempData + ).GetAwaiter().GetResult(); + + var retirementDate = selfAssessmentService.GetSelfAssessmentById((int)sessionEnrolOnRoleProfile.SelfAssessmentID).RetirementDate; + if (!CheckRetirementDate((retirementDate))) { - var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData( + return RedirectToAction("StatusCode", "LearningSolutions", new { code = 410 }); + } + var model = new RetiringSelfAssessmentViewModel() + { + SelfAssessmentID = (int)sessionEnrolOnRoleProfile.SelfAssessmentID, + SupervisorDelegateID = supervisorDelegateId, + RetirementDate = retirementDate, + ActionConfirmed = sessionEnrolOnRoleProfile.ActionConfirmed + }; + return View("ConfirmRetiringSelfAssessment", model); + } + + [HttpPost] + [Route("/Supervisor/Staff/{supervisorDelegateId}/ProfileAssessment/Enrol/Confirm")] + public IActionResult ConfirmRetiringSelfAssessment(RetiringSelfAssessmentViewModel retiringSelfAssessment) + { + var sessionEnrolOnRoleProfile = multiPageFormService.GetMultiPageFormData( MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ).GetAwaiter().GetResult(); - sessionEnrolOnRoleProfile.SelfAssessmentID = retiringSelfAssessment.SelfAssessmentID; - multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, - MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, - TempData - ); + sessionEnrolOnRoleProfile.SelfAssessmentID = retiringSelfAssessment.SelfAssessmentID; + sessionEnrolOnRoleProfile.ActionConfirmed = retiringSelfAssessment.ActionConfirmed; + multiPageFormService.SetMultiPageFormData( + sessionEnrolOnRoleProfile, + MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, + TempData + ); + + if (ModelState.IsValid && retiringSelfAssessment.ActionConfirmed) + { return RedirectToAction( "EnrolDelegateCompleteBy", "Supervisor", @@ -850,11 +871,12 @@ public IActionResult EnrolDelegateCompleteBy(int supervisorDelegateId, int? day, MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ).GetAwaiter().GetResult(); - multiPageFormService.SetMultiPageFormData( - sessionEnrolOnRoleProfile, - MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, - TempData - ); + + var retirementDate = selfAssessmentService.GetSelfAssessmentById((int)sessionEnrolOnRoleProfile.SelfAssessmentID).RetirementDate; + if (CheckRetirementDate(retirementDate) && !sessionEnrolOnRoleProfile.ActionConfirmed) + { + return RedirectToAction("ConfirmRetiringSelfAssessment", "Supervisor", new { supervisorDelegateId }); + } var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); var roleProfile = supervisorService.GetRoleProfileById((int)sessionEnrolOnRoleProfile.SelfAssessmentID); @@ -862,7 +884,8 @@ public IActionResult EnrolDelegateCompleteBy(int supervisorDelegateId, int? day, { SupervisorDelegateDetail = supervisorDelegate, RoleProfile = roleProfile, - CompleteByDate = sessionEnrolOnRoleProfile.CompleteByDate + CompleteByDate = sessionEnrolOnRoleProfile.CompleteByDate, + ActionConfirmed = sessionEnrolOnRoleProfile.ActionConfirmed }; if (day != null && month != null && year != null) { @@ -1008,6 +1031,13 @@ public IActionResult EnrolDelegateSummary(int supervisorDelegateId) MultiPageFormDataFeature.EnrolDelegateOnProfileAssessment, TempData ); + + var retirementDate = selfAssessmentService.GetSelfAssessmentById((int)sessionEnrolOnRoleProfile.SelfAssessmentID).RetirementDate; + if (CheckRetirementDate(retirementDate) && !sessionEnrolOnRoleProfile.ActionConfirmed) + { + return RedirectToAction("ConfirmRetiringSelfAssessment", "Supervisor", new { supervisorDelegateId }); + } + var supervisorDelegate = supervisorService.GetSupervisorDelegateDetailsById(supervisorDelegateId, GetAdminId(), 0); var roleProfile = supervisorService.GetRoleProfileById((int)sessionEnrolOnRoleProfile.SelfAssessmentID); @@ -1035,6 +1065,7 @@ public IActionResult EnrolDelegateSummary(int supervisorDelegateId) ViewBag.completeByMonth = TempData["completeByMonth"]; ViewBag.completeByYear = TempData["completeByYear"]; ViewBag.navigatedFrom = TempData["navigatedFrom"]; + ViewBag.actionConfirmed = sessionEnrolOnRoleProfile.ActionConfirmed; return View("EnrolDelegateSummary", model); } @@ -1558,5 +1589,15 @@ private static string RenderRazorViewToString(Controller controller, string view return sw.GetStringBuilder().ToString(); } } + + private bool CheckRetirementDate(DateTime? date) + { + if (date == null) + return false; + + DateTime retirementOffsetDate = DateTime.Today.AddDays(14); + DateTime today = DateTime.Today; + return (date >= today && date <= retirementOffsetDate); + } } } diff --git a/DigitalLearningSolutions.Web/Helpers/CompetencyFilterHelper.cs b/DigitalLearningSolutions.Web/Helpers/CompetencyFilterHelper.cs index 26b0e181ab..bf4e79abea 100644 --- a/DigitalLearningSolutions.Web/Helpers/CompetencyFilterHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/CompetencyFilterHelper.cs @@ -43,12 +43,12 @@ private static void ApplyResponseStatusFilters(ref IEnumerable compe let searchTextMatchesCompetencyDescription = wordsInSearchText.All(w => c.Description?.Contains(w, StringComparison.CurrentCultureIgnoreCase) ?? false) let searchTextMatchesCompetencyName = wordsInSearchText.All(w => c.Name?.Contains(w, StringComparison.CurrentCultureIgnoreCase) ?? false) let responseStatusFilterMatchesAll = - (!filters.Contains((int)SelfAssessmentCompetencyFilter.RequiresSelfAssessment) || c.AssessmentQuestions.Any(q => q.ResultId == null)) - && (!filters.Contains((int)SelfAssessmentCompetencyFilter.SelfAssessed) || c.AssessmentQuestions.Any(q => q.ResultId != null && q.Requested == null && q.SignedOff == null)) - && (!filters.Contains((int)SelfAssessmentCompetencyFilter.ConfirmationRequested) || c.AssessmentQuestions.Any(q => q.Verified == null && q.Requested != null)) - && (!filters.Contains((int)SelfAssessmentCompetencyFilter.ConfirmationRejected) || c.AssessmentQuestions.Any(q => q.Verified.HasValue && q.SignedOff != true)) - && (!filters.Contains((int)SelfAssessmentCompetencyFilter.Verified) || c.AssessmentQuestions.Any(q => q.Verified.HasValue && q.SignedOff == true)) - && (!filters.Contains((int)SelfAssessmentCompetencyFilter.Optional) || c.Optional) + (filters.Contains((int)SelfAssessmentCompetencyFilter.RequiresSelfAssessment) && c.AssessmentQuestions.Any(q => q.ResultId == null)) + || (filters.Contains((int)SelfAssessmentCompetencyFilter.SelfAssessed) && c.AssessmentQuestions.Any(q => q.ResultId != null && q.Requested == null && q.SignedOff == null)) + || (filters.Contains((int)SelfAssessmentCompetencyFilter.ConfirmationRequested) && c.AssessmentQuestions.Any(q => q.Verified == null && q.Requested != null)) + || (filters.Contains((int)SelfAssessmentCompetencyFilter.ConfirmationRejected) && c.AssessmentQuestions.Any(q => q.Verified.HasValue && q.SignedOff != true)) + || (filters.Contains((int)SelfAssessmentCompetencyFilter.Verified) && c.AssessmentQuestions.Any(q => q.Verified.HasValue && q.SignedOff == true)) + || (filters.Contains((int)SelfAssessmentCompetencyFilter.Optional) && c.Optional) where (wordsInSearchText.Count() == 0 || searchTextMatchesGroup || searchTextMatchesCompetencyDescription || searchTextMatchesCompetencyName) && (!appliedResponseStatusFilters.Any() || responseStatusFilterMatchesAll) select c; diff --git a/DigitalLearningSolutions.Web/Helpers/ProfessionalRegistrationNumberHelper.cs b/DigitalLearningSolutions.Web/Helpers/ProfessionalRegistrationNumberHelper.cs index 461d7ae46b..130c8d52b6 100644 --- a/DigitalLearningSolutions.Web/Helpers/ProfessionalRegistrationNumberHelper.cs +++ b/DigitalLearningSolutions.Web/Helpers/ProfessionalRegistrationNumberHelper.cs @@ -1,7 +1,7 @@ namespace DigitalLearningSolutions.Web.Helpers { - using System.Text.RegularExpressions; using Microsoft.AspNetCore.Mvc.ModelBinding; + using System.Text.RegularExpressions; public class ProfessionalRegistrationNumberHelper { @@ -48,13 +48,17 @@ public static void ValidateProfessionalRegistrationNumber( ); } - const string pattern = @"^[a-z\d-]+$"; + const string pattern = @"^(\d{7}|[A-Za-z]{1,2}\d{6}|\d{4,8}|P?\d{5,6}|[C|P]\d{6}|[A-Za-z]?\d{5,6}|L\d{4,6}|\d{2}-[A-Za-z\d]{4,5})$"; var rg = new Regex(pattern, RegexOptions.IgnoreCase); if (!rg.Match(prn).Success) { modelState.AddModelError( "ProfessionalRegistrationNumber", - "Invalid professional registration number format - Only alphanumeric characters (a-z, A-Z and 0-9) and hyphens (-) allowed" + "Invalid professional registration number format. " + + "Valid formats include: 7 digits (e.g., 1234567), 1–2 letters followed by 6 digits (e.g., AB123456), " + + "4–8 digits, an optional 'P' plus 5–6 digits, 'C' or 'P' plus 6 digits, " + + "an optional letter plus 5–6 digits, 'L' plus 4–6 digits, " + + "or 2 digits followed by a hyphen and 4–5 alphanumeric characters (e.g., 12-AB123)." ); } } diff --git a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSetCompletByDateViewModel.cs b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSetCompletByDateViewModel.cs index cac66da25f..935e257fb5 100644 --- a/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSetCompletByDateViewModel.cs +++ b/DigitalLearningSolutions.Web/ViewModels/Supervisor/EnrolDelegateSetCompletByDateViewModel.cs @@ -11,5 +11,6 @@ public class EnrolDelegateSetCompletByDateViewModel public RoleProfile RoleProfile { get; set; } public DateTime? CompleteByDate { get; set; } public OldDateValidator.ValidationResult? CompleteByValidationResult { get; set; } + public bool ActionConfirmed { get; set; } } } diff --git a/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml b/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml index 7a8371ca4c..5ef9742313 100644 --- a/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml +++ b/DigitalLearningSolutions.Web/Views/LearningPortal/SelfAssessments/CompetencySelfAssessmentCertificate.cshtml @@ -45,23 +45,23 @@